Rechazos y fallback
Cómo los modelos Claude Fable, los modelos Claude Opus, Claude Sonnet 5.5 y Claude Haiku 5.5 devuelven rechazos del clasificador y cómo reintentar las solicitudes rechazadas en un modelo de fallback.
Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Sonnet 5.5 y Claude Haiku 5.5 incluyen clasificadores de seguridad que pueden rechazar una solicitud. Cuando eso ocurre, recibes una respuesta normal, no un error, con stop_reason: "refusal". Su stop_details.category indica el área de política (consulta Cómo se ve un rechazo). 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 "refusal" (rechazo) y cómo configurar ese reintento.
Lee esta página cuando construyas sobre cualquiera de estos modelos y quieras que las solicitudes declinadas pasen automáticamente a otro modelo. También aplica cuando has visto "refusal" en una respuesta y quieres saber qué hacer a continuación.
Páginas relacionadas:
- Motivos de parada y fallback: la lista completa de valores de
stop_reason. - Crédito de fallback: cómo evitar pagar dos veces el costo de la caché de prompts cuando construyes el reintento tú mismo.
- Middleware del SDK: el asistente del SDK que envuelve todo esto.
- Cookbook de fallback y facturación: un ejemplo completo desarrollado de principio a fin.
La configuración más sencilla, en beta en la Claude API: establece fallbacks en "default", y la API reintenta una solicitud rechazada 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. Claude Haiku 5.5 no tiene fallback del lado del servidor, así que para él usa fallback del lado del cliente con el middleware del SDK o escribe el reintento tú mismo.
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.
Cómo se ve un rechazo
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.recommended_model: presente solo en solicitudes que establecenfallbacks(fallback del lado del servidor, beta). Nombra un modelo para reintentar directamente cuando la API omitió el intento de fallback (por ejemplo, el modelo de fallback alcanzó su límite de velocidad), y esnullen caso contrario. Es una sugerencia, no una garantía.categoryyexplanationson ambosnullcuando el rechazo no corresponde a una categoría con nombre. Esenulles un valor normal y permanente, no un marcador de posición.stop_detailsen sí esnullpara todos los motivos de parada distintos derefusal.
category | Qué significa | Se factura antes de cualquier salida |
|---|---|---|
"cyber" | La solicitud podría facilitar daño cibernético, como el desarrollo de malware o exploits. El trabajo benigno de ciberseguridad también puede activar esta categoría. | No |
"bio" | La solicitud podría facilitar 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. | Sí |
"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. | Sí |
"reasoning_extraction" | La solicitud pide al modelo que reproduzca su razonamiento interno en el texto de la respuesta. Para obtener el razonamiento en forma estructurada, usa pensamiento adaptativo. Consulta Mantén el razonamiento en bloques de pensamiento. | Sí |
"general_harms" | La solicitud cae dentro de un área de la política de uso fuera de las cuatro categorías con nombre. El trabajo benigno también puede activar esta categoría. | No |
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.
Mantén el razonamiento en bloques de pensamiento
Un rechazo reasoning_extraction suele provenir de un prompt que pide al modelo que ponga su pensamiento o razonamiento en la salida, ya sea textualmente o en un formato fijo. Ejemplos comunes:
- Una sección
<thinking>,<reasoning>o de borrador que el modelo completa antes de responder - Un campo
reasoning,thinkingotraceen la salida JSON o en la entrada de una herramienta - Las notas privadas del modelo, o un registro continuo de su razonamiento
- Razonamiento solicitado textualmente o de forma completa
La redacción puede estar en una indicación del sistema, una skill o la descripción de una herramienta, así que revisa también esos lugares.
Aún puedes pedirle a Claude que explique su respuesta. Pide una explicación breve, la evidencia detrás de un resultado o un resumen de las acciones que realizó. Para ver cómo razonó el modelo, establece display: "summarized" y lee los bloques thinking. Esta categoría no tiene un modelo de fallback recomendado, así que cambia el prompt en lugar de reintentar la solicitud. Si una solicitud reformulada sigue siendo rechazada, contacta al soporte e incluye el ID de solicitud.
Cómo se facturan los rechazos
Estas reglas de facturación se aplican en todas las plataformas: la Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud y Microsoft Foundry.
Rechazos antes de cualquier salida: Para frustrar los intentos de eludir las salvaguardas de Anthropic a gran escala, un rechazo que llega antes de cualquier salida se factura cuando su stop_details.category es "bio", "frontier_llm" o "reasoning_extraction". Estas son las categorías en las que Anthropic mide volúmenes bajos de falsos positivos, a septiembre de 2026. Estos rechazos se facturan como cualquier otra solicitud, a las tarifas del modelo que la ejecutó. Un rechazo antes de cualquier salida en cualquier otra categoría, o con una categoría null, no se factura. En cualquier caso, content está vacío y los conteos de tokens aparecen en usage. La solicitud aún cuenta contra tus límites de velocidad.
Rechazos a mitad del stream: Un rechazo a mitad del stream factura los tokens de entrada y la salida ya transmitida a las tarifas normales.
Fallback: Cuando usas fallback, el rechazo que lo activó se factura, además de la solicitud de fallback, cuando llegó a mitad del stream o pertenece a una de las categorías facturadas. El crédito de fallback compensa el fallo de caché de prompts de la solicitud de fallback, para que no pagues dos veces por almacenar en caché la conversación. Un rechazo de Claude Haiku 5.5 no incluye crédito de fallback, así que un fallback posterior paga el costo completo de escribir la caché de prompts del modelo de fallback. Para saber cómo el fallback del lado del servidor reporta cada intento, consulta Facturación y límites de velocidad.
Las categorías facturadas pueden cambiar a medida que Anthropic sigue midiendo y refinando las tasas de falsos positivos de sus salvaguardas. La columna Se factura antes de cualquier salida de la tabla de categorías de rechazo enumera las categorías facturadas.
Elegir un enfoque de fallback
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é |
|---|---|---|
| Claude API, 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 | Configúralo una vez en el cliente. Los reintentos ocurren automáticamente. |
| HTTP directo o lógica de reintento personalizada | Un reintento manual con crédito de fallback | Control total. El crédito de fallback mantiene bajo el costo. |
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. Claude Haiku 5.5 no tiene fallback del lado del servidor ni crédito de fallback, así que usa el middleware del SDK o un reintento manual.
Fallback del lado del servidor
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. De cualquier forma, recibes una sola respuesta que nombra el modelo que respondió, de modo que tu usuario obtiene una respuesta en un solo viaje de ida y vuelta.
Realizar la solicitud
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.
El enrutamiento predeterminado nunca provoca el rechazo anticipado por imagen sobredimensionada para modelos que no elegiste: un modelo enrutado que redimensionaría una imagen marcada con "oversized_image": "error" se elimina del enrutamiento en su lugar, de modo que una imagen marcada nunca se sirve redimensionada.
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 indica 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, de acuerdo 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 por ti estas recomendaciones por modelo y por categoría, de modo que una solicitud rechazada se reintenta en el modelo que Anthropic recomienda para esa categoría. Los fallbacks son visibles de cualquier forma: 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 Models API. 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.
Nombrar tus propios modelos de fallback
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 con 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.
Los modelos de fallback nombrados cuentan para la verificación de imagen sobredimensionada: una solicitud cuyo bloque de imagen establece "oversized_image": "error" se verifica de antemano contra el modelo solicitado y cada fallback nombrado, se rechaza si cualquiera de ellos redimensionaría esa imagen, y el objetivo de reescalado reportado en el rechazo se ajusta a todos ellos.
Las líneas resaltadas son la única diferencia con respecto a la solicitud de enrutamiento predeterminado.
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:
- Las entradas se prueban en orden. Cada una debe ser distinta de las demás entradas y del modelo solicitado.
- Cada entrada debe ser uno de los destinos permitidos del modelo solicitado. Con el encabezado beta establecido, esa lista se publica como
allowed_fallback_modelsen la entrada del modelo en la Models API. - Cada entrada indica un
modely puede sobrescribirmax_tokens,thinking,output_configyspeedsolo para ese intento. - La solicitud debe ser válida como solicitud directa a cada modelo nombrado. Si un modelo de respaldo no admite una función que usa la solicitud, la API rechaza la solicitud de antemano. Con el encabezado
2026-07-01,thinking: {"type": "between_tools"}es la excepción: cuando una solicitud a Claude Sonnet 5.5 pasa a Claude Sonnet 5, el intento de respaldo se ejecuta conthinking: {"type": "disabled"}ydisplay: "omitted". Con2026-06-01, establecethinkingen la entrada de Claude Sonnet 5, o la solicitud se rechaza de antemano. - Al igual que en el modo predeterminado, solo un rechazo del clasificador de seguridad activa el respaldo. Un límite de velocidad, una sobrecarga o un error del servidor en el modelo solicitado se te devuelve tal cual.
- Si un modelo de respaldo alcanza su límite de velocidad o está sobrecargado, el intento de respaldo no se realiza y en su lugar se devuelve el rechazo anterior. El
stop_details.recommended_modeldel rechazo indica entonces un modelo al que reintentar directamente. Dimensiona los límites de velocidad del modelo de respaldo para el volumen de rechazos que esperas, o los respaldos se degradarán a rechazos bajo carga.
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.
Qué contiene la respuesta
La respuesta se ve como cualquier otro mensaje, con dos adiciones:
- El campo
modelde nivel superior reporta el modelo que produjo el mensaje devuelto, ya sea el modelo solicitado o un fallback. - Un bloque de contenido
fallbackmarca cada punto encontentdonde la salida de un modelo da paso al siguiente:{"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}.from.modelrepite la cadena de modelo que enviaste cuando el salto que declina es el modelo solicitado.to.modeles 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 por cada salto anterior y una entrada fallback_message para el último.
El enrutamiento persistente puede enviar un turno posterior directamente al modelo de fallback. Dicho turno no lleva ningún bloque de contenido fallback, porque ningún modelo declinó ese turno. Identifícalo por la entrada fallback_message en usage.iterations, la ausencia de una entrada message para el modelo solicitado, y el campo model de la respuesta.
Continuar la conversación
En el siguiente turno, envía de vuelta el contenido del asistente tal como lo recibiste. Después de un fallback a mitad de la 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. |
Streaming
En una solicitud con streaming, el reintento ocurre en el mismo stream, y nada de lo que ya recibiste se invalida. Lo que ves depende de cuándo ocurre la declinación.
Cuando la declinación ocurre antes de cualquier salida:
message_startnombra el modelo de fallback, y el bloquefallbackes el primer bloque de contenido.- Debido a que
message_startespera 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:
- El bloque de contenido abierto se cierra, y el bloque
fallback(un par ordinario decontent_block_startycontent_block_stopsin deltas) marca el límite. - El modelo de fallback continúa desde la salida parcial. Solo los bloques
textde la salida parcial se pasan al modelo de fallback como contexto. Los demás tipos de bloque permanecen encontent. message_startya nombró el modelo solicitado, así que lee el modelo que atiende desde elto.modeldel bloquefallbacky desde la entradafallback_messageen elusage.iterationsdelmessage_deltafinal.
Respuestas sin streaming
En una solicitud sin streaming, una declinación a mitad de la salida se comporta de manera diferente: la respuesta omite la salida parcial del modelo declinado, 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.
Facturación y límites de velocidad
Cada intento sigue las reglas de Cómo se facturan los rechazos, a las tarifas del modelo que lo ejecutó. Un intento que declinó antes de producir cualquier salida se factura solo cuando su categoría de rechazo es facturable, y sus tokens se reportan en su entrada de usage.iterations en cualquier caso. Cada intento que produjo salida, incluido uno que declinó a mitad de su respuesta, se factura por separado. El arreglo usage.iterations es el registro por intento de lo que se te factura. Los conteos de usage de nivel superior describen solo el intento que produjo el mensaje devuelto. Los tokens de diferentes modelos nunca se suman en un solo campo.
Cada intento que se ejecuta, incluido uno que declinó, cuenta contra los límites de velocidad de su propio modelo.
Enrutamiento persistente
Después de que una conversación recurre al fallback, la API registra qué modelo la atendió. Las solicitudes posteriores de esa conversación que incluyen fallbacks van directamente a ese modelo de fallback, sin ejecutar el modelo solicitado. Este "sticky routing" (enrutamiento persistente) evita pagar por un intento que previsiblemente sería declinado de nuevo en cada turno.
Algunas propiedades de la decisión de enrutamiento:
- Se conserva durante aproximadamente 1 hora y está limitada a tu organización.
- Se almacena como un hash de contenido del prefijo de la conversación más el modelo que la atendió. El contenido del mensaje en sí no se almacena.
- Es de mejor esfuerzo, por lo que tu código debe manejar que el modelo solicitado se vuelva a probar en cualquier momento.
El enrutamiento persistente aplica tanto a solicitudes con streaming como sin streaming. En una solicitud con streaming, la decisión de enrutamiento se toma antes de que se abra el stream, por lo que el campo model del evento message_start ya lleva el ID del modelo de fallback.
Fallback del lado del cliente con el middleware del SDK
El SDK incluye un middleware de fallback ante rechazos. Lo configuras una vez en el cliente con tu lista de modelos de fallback. Las llamadas a través de client.beta.messages reintentan entonces 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, de modo que los reintentos se vuelven a tarificar sin configuración por solicitud. Un rechazo de Claude Haiku 5.5 no incluye crédito de fallback, así que un reintento posterior paga el costo completo de escribir la caché de prompts del modelo de fallback.
Configurarlo
Pasa BetaRefusalFallbackMiddleware 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 fallback-credit 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}")Cómo se comporta
- Los reintentos recorren tu lista de respaldo en orden. Un modelo de respaldo que a su vez rechaza pasa la solicitud a la siguiente entrada.
- Cuando todos los modelos de la lista han rechazado, el middleware devuelve el rechazo final (la respuesta de rechazo del último modelo) en lugar de generar un error.
- Los bloques de pensamiento de Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5, Claude Haiku 5.5 o Claude Fable 5 pasan sin cambios. Cada reintento reenvía el cuerpo de tu solicitud original, y los únicos bloques que el middleware elimina del historial de la conversación en solicitudes posteriores son los bloques de límite
fallbackque él mismo agregó. El modelo de fallback no puede leer los bloques de Claude Fable 5.1, que solo leen Claude Fable 5.1 y Claude Mythos 5.1, así que la API los descarta. La API también descarta los bloques de Claude Opus 5.5 para todos los modelos de fallback excepto Claude Fable 5.1 y Claude Mythos 5.1 (consulta Cambiar de modelo a mitad de la conversación). También descarta los bloques de Claude Sonnet 5.5, para todos los modelos de fallback excepto Claude Opus 5.5 en la Claude API y Google Cloud. Claude Opus 5.5 y Claude Sonnet 5.5 leen los bloques de Claude Haiku 5.5 en la Claude API y Google Cloud, y la API los descarta para un modelo de fallback que no puede leerlos. - Las respuestas atendidas a través del middleware incluyen un bloque de contenido
fallbacken cada límite entre modelos, igual que las respuestas del respaldo del lado del servidor. El middleware gestiona esos bloques por ti en solicitudes posteriores. - El modelo que aceptó se registra en
BetaFallbackState, de modo que las solicitudes de seguimiento que comparten el estado permanecen fijadas a él en lugar de volver a preguntar a un modelo que rechazó.
Escribir el reintento tú mismo
Sobre HTTP directo o con lógica de reintento personalizada, implementa el patrón que el middleware envuelve:
Detecta el rechazo
Revisa la respuesta en busca de
stop_reason: "refusal".Reenvía en un modelo de respaldo
Envía la misma solicitud con
modelestablecido en un modelo de respaldo, como Claude Opus 4.8. Si la solicitud rechazada envióthinking: {"type": "between_tools"}, cambiathinkingprimero: solo Claude Sonnet 5.5 acepta ese valor, así que omitethinkingo establece un valor que el modelo de respaldo acepte. El fallback del lado del servidor con el encabezado2026-07-01hace este cambio por ti cuando pasa a Claude Sonnet 5. Otro modelo normalmente puede atender una solicitud que Claude Fable 5.1 o Claude Fable 5 rechaza. Cómo manejes el historial de la conversación depende de si canjeas un crédito de respaldo:- Sin canjear un crédito: puedes dejar los bloques
thinkingyredacted_thinkinganteriores en su lugar o eliminarlos para ahorrar tokens de entrada. El modelo de fallback normalmente no puede usarlos en ningún caso: solo Claude Fable 5.1 y Claude Mythos 5.1 leen los bloques de Claude Fable 5.1, y solo esos dos modelos, además de Claude Fable 5 y Claude Mythos 5, leen los bloques de Claude Fable 5, así que para cualquier otro modelo de fallback la API los descarta. La API también descarta los bloques de Claude Opus 5.5 para todos los modelos de fallback excepto Claude Fable 5.1 y Claude Mythos 5.1 (consulta Cambiar de modelo a mitad de la conversación). También descarta los bloques de Claude Sonnet 5.5, para todos los modelos de fallback excepto Claude Opus 5.5 en la Claude API y Google Cloud. Un reintento después de un rechazo de Claude Haiku 5.5 siempre corresponde a este caso. Claude Opus 5.5 y Claude Sonnet 5.5 leen los bloques de Claude Haiku 5.5 en la Claude API y Google Cloud, así que deja esos bloques en su lugar cuando pases a cualquiera de esos dos modelos en esas plataformas. Para un modelo de fallback que no puede leerlos, la API los descarta sin facturarlos. - Canjeando un crédito: envía el cuerpo sin cambios, porque el canje requiere una coincidencia exacta. El servidor maneja los bloques de pensamiento del modelo anterior en un canje, así que no los elimines (consulta Campos que deben coincidir con la solicitud rechazada).
- Sin canjear un crédito: puedes dejar los bloques
Permanece en el modelo de respaldo
En conversaciones de varios turnos, sigue usando el modelo de respaldo en los turnos siguientes en lugar de volver al anterior.
Un reintento manual escribe la caché de prompts del modelo de fallback desde cero, lo cual cuesta más que leer una caché existente. El crédito de fallback reembolsa ese costo; canjéalo en cada reintento que construyas tú mismo. Un rechazo de Claude Haiku 5.5 no incluye crédito de fallback, así que un reintento posterior paga el costo completo de escribir la caché de prompts del modelo de fallback.
Rechazos en Message Batches
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 en 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 los elementos de lote rechazados:
- Recopila los elementos rechazados de los resultados.
- Deja en su lugar los bloques de pensamiento de los historiales de varios turnos, o elimínalos para ahorrar tokens de entrada. Para un modelo de fallback que no puede leerlos, la API los descarta sin facturarlos, como en un reintento manual.
- Si un elemento rechazado envió
thinking: {"type": "between_tools"}, omitethinkingo establece un valor que el modelo de fallback acepte. Solo Claude Sonnet 5.5 aceptabetween_tools. - Reenvíalos en un modelo de fallback como un nuevo lote o como solicitudes directas.
Errores comunes
- Reintenta en un modelo diferente. Reenviar una solicitud rechazada al mismo modelo generalmente obtiene otro rechazo. Dirige el reintento al modelo de fallback.
- Presupuesta los reintentos por solicitud, no por turno ni por sesión. Un solo turno puede producir varios rechazos, por ejemplo un agente más sus subagentes.
- Configura el fallback en cada ruta de solicitud. Los manejadores de reintento, las ramas de recuperación de errores y los workers en segundo plano lo necesitan. Un manejador que vuelve a emitir una solicitud sin fallback pierde la protección exactamente en las solicitudes que más probablemente la necesiten.
- Da a las llamadas de subagentes su propio fallback. El parámetro
fallbacksno se propaga a las llamadas a modelos realizadas desde dentro de la ejecución de herramientas. - Haz del fallback una propiedad de la solicitud, no del estado ambiental. Una bandera compartida, un valor de configuración en caché o un interruptor global pueden desincronizarse y dejar silenciosamente una solicitud sin protección. Cuando no puedas confirmar que el fallback está activo, configúralo en lugar de asumir que está activado.
- Instrumenta los rechazos como su propia señal. Un rechazo es un HTTP 200, por lo que el monitoreo basado en tasas de error o respuestas 5xx nunca lo ve. Emite un evento por rechazo y uno por respuesta atendida mediante fallback (la entrada
fallback_messageenusage.iterationsmarca esta última), y luego alerta sobre la diferencia entre los dos conteos. - Ramifica según
stop_reasonostop_details.type, no segúncontentni los campos internos destop_details. El objetostop_detailssiempre está presente en un rechazo, pero sus camposcategoryyexplanationpueden sernull. Verifica directamente questop_reasonsea igual a"refusal".
Próximos pasos
Evita pagar dos veces el costo de la caché de prompts cuando construyes el reintento tú mismo.
Cada valor de stop_reason y cómo manejarlo.
Cómo funciona el middleware del SDK, incluido el asistente de fallback ante rechazos.
Migra una aplicación existente a Claude Fable 5.1.
Was this page helpful?