Claude Fable 5 incluye clasificadores de seguridad que pueden rechazar 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 desarrolles con Claude Fable 5 y quieras que las solicitudes rechazadas 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: nombra un modelo de fallback en la solicitud y la API se encarga del reintento.
client = Anthropic()
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-06-01"],
)Las secciones siguientes 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 el rechazo:
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 facilitar daño cibernético, como desarrollo de malware o exploits. El trabajo benigno de ciberseguridad también puede activar esta categoría. |
"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. |
"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 forma estructurada, usa adaptive thinking. |
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, los recuentos de tokens aparecen en usage pero no se cobran, y la solicitud no cuenta contra los límites de velocidad. Un rechazo a mitad del stream factura los tokens de entrada y la salida ya transmitida a las 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é |
|---|---|---|
| Claude API o Claude Platform en AWS, configuración más simple | Fallback del lado del servidor | Una solicitud, una respuesta. La API se encarga del reintento. |
| Cualquier plataforma, con el SDK de TypeScript, Python, Go, Java o C# | El middleware del SDK | Configura una vez en el cliente. Los reintentos ocurren automáticamente. |
| Ruby, PHP, 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. Nombras hasta tres modelos de fallback, y cuando Claude Fable 5 rechaza, la API ejecuta el siguiente modelo de la cadena con la misma solicitud. 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.
El fallback del lado del servidor está en beta en la Claude API y Claude Platform en AWS. El parámetro fallbacks se rechaza en la API de Message Batches y no está disponible en Amazon Bedrock, Google Cloud ni Microsoft Foundry. En esas plataformas, usa el middleware del SDK en su lugar.
Nombra los modelos de fallback en el parámetro fallbacks y envía el encabezado beta server-side-fallback-2026-06-01.
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-06-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 generó 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,
}
)
)Se aplican algunas reglas a la lista fallbacks:
allowed_fallback_models en la entrada del modelo en la API de Modelos.model y puede sobrescribir max_tokens y thinking solo para ese intento.El encabezado beta debe llevar exactamente la fecha 2026-06-01. Bajo cualquier otro valor server-side-fallback-*, el parámetro fallbacks se rechaza con un error 400. Si desarrollaste 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.
La respuesta se ve como cualquier otro mensaje, con dos adiciones:
model de nivel superior informa 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 a la del siguiente: {"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}.
from.model repite la cadena de modelo que enviaste cuando el salto que rechaza 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:
{
"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 array usage.iterations registra cada intento. Un modelo que rechazó 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 rechazan, 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 tal como lo recibiste. Después de un fallback a mitad de la salida, content puede incluir tipos de bloque que el modelo que rechazó produjo antes del traspaso; la tabla siguiente 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 que usan 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 el rechazo.
Cuando el rechazo 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 rechazado.Cuando el rechazo 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 el usage.iterations del message_delta final.En una solicitud sin streaming, un rechazo a mitad de la salida se comporta de manera diferente: la respuesta omite la salida parcial del modelo rechazado, y el modelo de fallback responde desde cero. El resultado se ve como un rechazo antes de cualquier salida, con el bloque fallback primero. El intento rechazado y sus tokens de salida aún aparecen en usage.iterations.
Rechazos después de que se ejecutan herramientas del servidor: cuando un rechazo se activa después de que las herramientas del servidor (por ejemplo, búsqueda web o ejecución de código) ya se han ejecutado dentro de una solicitud, la API devuelve el rechazo en lugar de avanzar a un modelo de fallback. Si el encabezado fallback-credit-2026-06-01 también está configurado, ese rechazo lleva un token de crédito canjeable al continuar la respuesta parcial, de modo que el trabajo de herramientas completado no se pierde. Esto aplica solo a herramientas del servidor que iteran dentro de una sola solicitud. Las conversaciones que usan herramientas del lado del cliente hacen fallback normalmente.
Los SDK de TypeScript, Python, Go, Java y C# incluyen 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 luego reintentan automáticamente las solicitudes rechazadas, en cualquier plataforma. El middleware también envía el encabezado beta fallback-credit-2026-06-01 en cada solicitud que maneja, de modo que los reintentos se reprecian sin configuración por solicitud.
El helper de middleware de fallback por rechazo aún no está disponible en los SDK de Ruby y PHP. En esos SDK, implementa el patrón de detectar y reintentar directamente.
Pasa el middleware al constructor del cliente y comparte una instancia de BetaFallbackState entre las solicitudes de una conversación.
# Ante un rechazo, el middleware reintenta con el modelo de respaldo indicado y
# envía automáticamente el encabezado beta de crédito de respaldo en cada solicitud que gestiona.
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 event in stream:
if event.type == "text":
print(event.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 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, 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ó.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". El campo stop_details puede ser null en los resultados de batch, así que detecta los rechazos verificando stop_reason directamente.
El fallback del lado del servidor no está disponible para batches (una solicitud de batch que incluye fallbacks produce un resultado con error por elemento). Para reintentar elementos de batch rechazados:
fallbacks no se propaga a las llamadas de modelo realizadas desde dentro de la ejecución de herramientas.fallback_message en usage.iterations marca esta última), luego alerta sobre la brecha entre los dos recuentos.stop_reason, no según stop_details ni content. stop_details es informativo y puede ser null en un rechazo. Verifica que stop_reason sea igual a "refusal" directamente.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 helper de fallback por rechazo.
Migra una aplicación existente a Claude Fable 5.
Was this page helpful?