Claude Fable 5 y Claude Opus 5 incluyen clasificadores de seguridad que pueden declinar una solicitud. Cuando eso sucede, recibes una respuesta normal, no un error, con stop_reason: "refusal". Por lo general, aún puedes obtener una respuesta enviando la misma solicitud a otro modelo de Claude. Esta página te muestra cómo reconocer un rechazo y cómo configurar ese reintento.
Lee esta página cuando construyas sobre Claude Fable 5 o Claude Opus 5 y quieras que las solicitudes declinadas pasen automáticamente a otro modelo. También aplica cuando acabas de ver "refusal" en una respuesta y quieres saber qué hacer a continuación.
Páginas relacionadas:
stop_reason.La configuración más simple, en beta en la API de Claude: establece fallbacks en "default", y la API reintenta una solicitud declinada en el modelo de fallback que Anthropic recomienda para su categoría de rechazo. Para las categorías sin un fallback recomendado, el rechazo se mantiene.
client = Anthropic()
response = client.beta.messages.create(
model="claude-fable-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
fallbacks="default",
betas=["server-side-fallback-2026-07-01"],
)
print(response.model)Las siguientes secciones cubren qué contiene una respuesta de rechazo, cuándo usar fallback del lado del servidor o del lado del cliente, y cómo se factura cada uno.
Un rechazo es una respuesta HTTP 200 exitosa con stop_reason: "refusal":
{
"id": "msg_01XFUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"model": "claude-fable-5",
"content": [],
"stop_reason": "refusal",
"stop_details": {
"type": "refusal",
"category": "cyber",
"explanation": "This request was declined because it could enable cyber harm."
},
"usage": {
"input_tokens": 412,
"output_tokens": 0
}
}El objeto stop_details explica la declinación:
category: nombra el área de política que activó el clasificador.explanation: una descripción legible para humanos. El texto no es estable, así que muéstralo en lugar de analizarlo.null cuando el rechazo no corresponde a una categoría con nombre. Ese null es un valor normal y permanente, no un marcador de posición.stop_details en sí es null para cualquier razón de detención distinta de refusal.category | Qué significa |
|---|---|
"cyber" | La solicitud podría habilitar daño cibernético, como el desarrollo de malware o exploits. El trabajo benigno de ciberseguridad también puede activar esta categoría. |
"bio" | La solicitud podría habilitar daño biológico, como métodos de laboratorio peligrosos. El trabajo beneficioso en ciencias de la vida también puede activar esta categoría. |
"frontier_llm" | La solicitud podría ayudar al desarrollo de modelos de IA competidores, lo cual está restringido bajo los términos comerciales de Anthropic. El trabajo benigno de aprendizaje automático también puede activar esta categoría. |
"reasoning_extraction" | La solicitud pide al modelo que reproduzca su razonamiento interno en el texto de la respuesta. Para obtener el razonamiento en una forma estructurada en su lugar, usa el pensamiento adaptativo. |
"general_harms" | La solicitud podría estar relacionada con un área que se determinó como dañina. El trabajo benigno a veces puede activar esta categoría. |
Un rechazo puede llegar antes de cualquier salida, o a mitad del stream después de una salida parcial. En cualquier caso, trata cualquier salida parcial como incompleta y descártala.
Cómo se facturan los rechazos: No se te factura por un rechazo que llega antes de cualquier salida. content está vacío, y los conteos de tokens aparecen en usage pero no se cobran. La solicitud aún cuenta contra tus límites de velocidad. Un rechazo a mitad del stream factura los tokens de entrada y la salida ya transmitida a tarifas normales.
Hay tres formas de reintentar una solicitud rechazada en otro modelo. La correcta depende de dónde estés ejecutando y cuánto control necesites.
| Tu situación | Usa | Por qué |
|---|---|---|
| API de Claude, configuración más simple | Fallback del lado del servidor | Una solicitud, una respuesta. La API maneja el reintento. |
| Cualquier plataforma, usando un SDK de Anthropic | El middleware del SDK | Configura una vez en el cliente. Los reintentos ocurren automáticamente. |
| HTTP sin procesar o lógica de reintento personalizada | Reintento manual con crédito de fallback | Control total. El crédito de fallback mantiene el costo bajo. |
El fallback del lado del servidor y el middleware del SDK aplican el crédito de fallback por ti. Solo necesitas la página de Crédito de fallback cuando construyes el reintento tú mismo.
El fallback del lado del servidor reintenta una solicitud rechazada dentro de una sola llamada a la API. En el modo predeterminado, cuando el modelo principal declina y la categoría de rechazo tiene un fallback recomendado, la API ejecuta la misma solicitud en el modelo que Anthropic recomienda para esa categoría. En su lugar, puedes nombrar hasta tres modelos de fallback propios (abajo). De cualquier manera, obtienes una sola respuesta que nombra el modelo que respondió, por lo que tu usuario obtiene una respuesta en un solo viaje de ida y vuelta.
El fallback del lado del servidor está en beta en la API de Claude. El parámetro fallbacks no es compatible con la API de Message Batches (un elemento de lote que lo incluye regresa como un resultado con error) y no está disponible en Amazon Bedrock, Google Cloud o Microsoft Foundry. En esas plataformas, usa el fallback del lado del cliente con el middleware del SDK en su lugar.
Establece el parámetro fallbacks en la cadena "default" y envía el encabezado beta server-side-fallback-2026-07-01. La API entonces aplica el enrutamiento predeterminado definido por el servidor para el modelo solicitado, que selecciona un modelo de fallback recomendado según la categoría de rechazo que reporta el clasificador, de modo que las solicitudes rechazadas se atienden sin que tengas que mantener una lista de modelos a medida que cambian las recomendaciones.
client = Anthropic()
response = client.beta.messages.create(
model="claude-fable-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
fallbacks="default",
betas=["server-side-fallback-2026-07-01"],
)
# Una entrada fallback_message en usage.iterations significa que se ejecutó un modelo de respaldo;
# combínala con stop_reason para confirmar que el respaldo sirvió la respuesta.
fallback_ran = any(
iteration.type == "fallback_message"
for iteration in response.usage.iterations or []
)
served_by_fallback = fallback_ran and response.stop_reason != "refusal"
print(
json.dumps(
{
"stop_reason": response.stop_reason,
"model": response.model,
"served_by_fallback": served_by_fallback,
}
)
)Anthropic establece salvaguardas para cada modelo individualmente y para cada categoría de política, en línea con la capacidad del modelo: dependiendo de la categoría, una solicitud marcada puede recurrir a un modelo menos capaz o ser declinada. El modo "default" codifica estas recomendaciones por modelo y por categoría por ti, de modo que una solicitud rechazada se reintenta en el modelo que Anthropic recomienda para esa categoría. Los fallbacks son visibles de cualquier manera: la respuesta nombra el modelo que la atendió, y el bloque de contenido fallback marca el traspaso.
El enrutamiento se aplica del lado del servidor y no se publica por modelo en la API de Models. Para ver qué modelo atendió una solicitud rechazada, revisa el campo model de nivel superior de la respuesta y busca una entrada fallback_message en usage.iterations, como lo hacen los ejemplos de esta página.
Solo una declinación del clasificador de seguridad activa el fallback. Un límite de velocidad, una sobrecarga o un error del servidor en el modelo solicitado se te devuelve tal cual.
El encabezado beta debe llevar exactamente la fecha 2026-07-01, que admite tanto "default" como la forma de lista explícita de abajo, o 2026-06-01, que acepta solo la forma de lista explícita. Bajo cualquier otro valor server-side-fallback-*, el parámetro fallbacks se rechaza con un error 400. Si construiste contra una vista previa anterior de esta función, actualiza el encabezado beta y las formas de solicitud y respuesta juntas a las de esta página.
En lugar del enrutamiento predeterminado, puedes establecer fallbacks en una lista de hasta tres modelos. Cuando el modelo solicitado declina, la API ejecuta el siguiente modelo de la cadena en la misma solicitud. Usa esta forma cuando quieras controlar exactamente qué modelos atienden las solicitudes rechazadas, como fijar un modelo que tu aplicación ha calificado.
client = Anthropic()
response = client.beta.messages.create(
model="claude-fable-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
fallbacks=[{"model": "claude-opus-4-8"}],
betas=["server-side-fallback-2026-07-01"],
)
print(response.model)Algunas reglas aplican a la lista fallbacks:
allowed_fallback_models en la entrada del modelo en la API de Models.model y puede anular max_tokens, thinking, output_config y speed solo para ese intento.La forma de lista explícita también funciona bajo el encabezado beta server-side-fallback-2026-06-01; el modo "default" no.
La respuesta tiene la misma forma en ambos modos: el modelo que atendió el turno aparece en el campo model de nivel superior, un bloque de contenido fallback marca el traspaso, y usage.iterations registra cada intento.
La respuesta se ve como cualquier otro mensaje, con dos adiciones:
model de nivel superior reporta el modelo que produjo el mensaje devuelto, ya sea el modelo solicitado o un fallback.fallback marca cada punto en content donde la salida de un modelo da paso al siguiente: {"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}.
from.model repite la cadena de modelo que enviaste cuando el salto que declina es el modelo solicitado.to.model es siempre el ID resuelto del modelo que continúa.En un rechazo antes de cualquier salida, el bloque fallback es el primer bloque de contenido. Por ejemplo, cuando el enrutamiento predeterminado selecciona Claude Opus 4.8 para la categoría del rechazo:
{
"id": "msg_01XFUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"model": "claude-opus-4-8",
"content": [
{
"type": "fallback",
"from": { "model": "claude-fable-5" },
"to": { "model": "claude-opus-4-8" }
},
{ "type": "text", "text": "Hi! How can I help you today?" }
],
"stop_reason": "end_turn",
"stop_details": null,
"usage": {
"input_tokens": 412,
"output_tokens": 264,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0,
"iterations": [
{
"type": "message",
"model": "claude-fable-5",
"input_tokens": 535,
"output_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
},
{
"type": "fallback_message",
"model": "claude-opus-4-8",
"input_tokens": 412,
"output_tokens": 264,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
}
]
}
}El arreglo usage.iterations registra cada intento. Un modelo que declinó aparece como una entrada message ordinaria, y el modelo que atendió el turno aparece como una entrada fallback_message. Si todos los modelos de la cadena declinan, la respuesta es el rechazo del último modelo, con una entrada message para cada salto anterior y una entrada fallback_message para el último.
En el siguiente turno, envía el contenido del asistente de vuelta tal como lo recibiste. Después de un fallback a mitad de salida, content puede incluir tipos de bloque que el modelo que declinó produjo antes del traspaso; la siguiente tabla cubre cuáles conservar y cuáles descartar cuando repites el turno.
| Tipo de bloque | En el siguiente turno |
|---|---|
fallback | Consérvalo exactamente donde apareció. La API usa su posición para validar los bloques de pensamiento a su alrededor, por lo que una solicitud que repite bloques de pensamiento de ambos lados del límite se rechaza si el bloque se omite o se mueve. |
text | Conservar. |
Cualquier bloque después del bloque fallback final | Conservar. |
thinking, redacted_thinking o connector_text antes del bloque fallback final | Descartar. |
tool_use del lado del cliente antes del bloque fallback final | Descartar. |
server_tool_use antes del bloque fallback final | Conservar cuando está emparejado con su resultado. Descartar cuando no tiene un resultado correspondiente. |
Un bloque connector_text lleva texto de narración que algunas respuestas con uso de herramientas incluyen entre llamadas a herramientas.
En una solicitud de streaming, el reintento ocurre en el mismo stream, y nada de lo que ya has recibido se invalida. Lo que ves depende de cuándo ocurre la declinación.
Cuando la declinación ocurre antes de cualquier salida:
message_start nombra el modelo de fallback, y el bloque fallback es el primer bloque de contenido.message_start espera a que comience el intento de fallback, el tiempo hasta el primer byte incluye el intento declinado.Cuando la declinación ocurre a mitad de la salida:
fallback (un par ordinario de content_block_start y content_block_stop sin deltas) marca el límite.text de la salida parcial se pasan al modelo de fallback como contexto; otros tipos de bloque permanecen en content.message_start ya nombró el modelo solicitado, así que lee el modelo que atiende desde el to.model del bloque fallback y desde la entrada fallback_message en usage.iterations del message_delta final.En una solicitud sin streaming, una declinación a mitad de salida se comporta de manera diferente: la respuesta omite la salida parcial del modelo que declinó, y el modelo de fallback responde desde cero. El resultado se ve como una declinación antes de cualquier salida, con el bloque fallback primero. El intento declinado y sus tokens de salida aún aparecen en usage.iterations.
Declinaciones durante el uso de herramientas: el trabajo de herramientas completado no bloquea el fallback. Cuando una declinación se dispara después de que las herramientas del servidor (por ejemplo, búsqueda web o ejecución de código) han terminado de ejecutarse dentro de una solicitud, el intento de fallback procede: los resultados de herramientas completados se trasladan, y el modelo de fallback puede seguir invocando herramientas del servidor. El único caso que no se reintenta es una declinación en streaming que se dispara mientras un bloque de uso de herramientas de cualquier tipo (una herramienta del cliente, una herramienta del servidor o una llamada a herramienta MCP) aún está abierto en el stream: ese rechazo se devuelve directamente, y si el encabezado fallback-credit-2026-07-01 está establecido, aún lleva un token de crédito canjeable al continuar la respuesta parcial. Las solicitudes sin streaming no se ven afectadas; la API limpia el trabajo parcial y reintenta antes de responder.
Cada SDK de Anthropic incluye un middleware de fallback por rechazo. Lo configuras una vez en el cliente con tu lista de modelos de fallback. Las llamadas a través de client.beta.messages entonces reintentan las solicitudes rechazadas automáticamente, en cualquier plataforma. El middleware también envía el encabezado beta fallback-credit-2026-07-01 en cada solicitud que maneja, por lo que los reintentos se vuelven a tarificar sin configuración por solicitud.
Pasa el middleware al constructor del cliente y comparte una instancia de BetaFallbackState entre las solicitudes de una conversación.
from anthropic import Anthropic, BetaFallbackState, BetaRefusalFallbackMiddleware
# Ante un rechazo, el middleware reintenta con el modelo de respaldo indicado y
# envía automáticamente el encabezado beta de crédito por respaldo en cada solicitud que maneja.
client = Anthropic(
middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])],
)
state = BetaFallbackState() # pins follow-ups to the model that accepted
# Streaming: ante un rechazo, el middleware reintenta con el modelo de respaldo y
# empalma sus eventos en el stream abierto.
with (
state,
client.beta.messages.stream(
max_tokens=1024,
model="claude-fable-5",
messages=[{"role": "user", "content": "Hello, Claude"}],
) as stream,
):
for text in stream.text_stream:
print(text, end="", flush=True)
final_message = stream.get_final_message()
print(f"\nserved by: {final_message.model}")
# Sin streaming: reutilizar el estado mantiene la conversación fijada.
with state:
message = client.beta.messages.create(
max_tokens=1024,
model="claude-fable-5",
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(f"served by: {message.model}")fallback que él mismo agregó.fallback en cada límite de modelo, igual que las respuestas de fallback del lado del servidor. El middleware gestiona esos bloques por ti en solicitudes posteriores.BetaFallbackState, por lo que las solicitudes de seguimiento que comparten el estado permanecen fijadas a él en lugar de volver a preguntar a un modelo que rechazó.El middleware y el parámetro fallbacks del lado del servidor hacen el mismo trabajo. Configura uno u otro, nunca ambos en la misma solicitud. Para enviar una solicitud con fallbacks del lado del servidor desde una aplicación que instala el middleware, usa una instancia de cliente separada sin él.
Una solicitud rechazada en un Message Batch regresa como result.type: "succeeded" con stop_reason: "refusal". Los resultados de lote llevan el mismo objeto stop_details que las respuestas síncronas, por lo que puedes detectar rechazos a través de stop_reason o de stop_details.type. Una diferencia: los rechazos de lote no emiten créditos de fallback, por lo que stop_details en un resultado de lote nunca incluye un fallback_credit_token.
El fallback del lado del servidor no está disponible para lotes (una solicitud de lote que incluye fallbacks produce un resultado con error por elemento). Para reintentar elementos de lote rechazados:
fallbacks no se propaga a las llamadas al modelo hechas desde dentro de la ejecución de herramientas.fallback_message en usage.iterations marca esta última), luego alerta sobre la brecha entre los dos conteos.stop_reason o stop_details.type, no sobre content ni los campos internos de stop_details. El objeto stop_details siempre está presente en un rechazo, pero sus campos category y explanation pueden ser null. Verifica directamente que stop_reason sea igual a "refusal".Evita pagar el costo de la caché de prompts dos veces cuando construyes el reintento tú mismo.
Cada valor de stop_reason y cómo manejarlo.
Cómo funciona el middleware del SDK, incluido el ayudante de fallback por rechazo.
Mueve una aplicación existente a Claude Fable 5.
Was this page helpful?