Claude Platform Docs
MessagesConstruir con Claude

Rechazos y fallback

Cómo los modelos Claude Fable y Claude Opus devuelven rechazos del clasificador y cómo reintentar las solicitudes rechazadas en un modelo de fallback.

Claude Fable 5.1, 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". Su stop_details.category nombra 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 Claude. Esta página te muestra cómo reconocer un "refusal" (rechazo) y cómo configurar ese reintento mediante "fallback" (respaldo).

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:

La configuración más simple, en beta en la Claude API: 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.

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 establecen fallbacks (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 es null en caso contrario. Es una sugerencia, no una garantía.
  • category y explanation son ambos 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 todos los motivos de parada distintos de refusal.
categoryQué significa
"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.
"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 una forma estructurada, usa el pensamiento adaptativo.
"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.

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.

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ónUsaPor qué
Claude API, configuración más simpleFallback del lado del servidorUna solicitud, una respuesta. La API maneja el reintento.
Cualquier plataforma, usando un SDK de AnthropicEl middleware del SDKConfigúralo una vez en el cliente. Los reintentos ocurren automáticamente.
HTTP directo o lógica de reintento personalizadaUn reintento manual con crédito de fallbackControl 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.

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_models en la entrada del modelo en la Models API.
  • Cada entrada nombra un model y puede sobrescribir max_tokens, thinking, output_config y speed solo para ese intento.
  • La solicitud debe ser válida como solicitud directa a cada modelo nombrado. Si un modelo de fallback no admite una función que la solicitud usa, la API rechaza la solicitud de antemano.
  • Al igual que en el modo predeterminado, 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.
  • Si un modelo de fallback alcanzó su límite de velocidad o está sobrecargado, el intento de fallback no se realiza y en su lugar se devuelve el rechazo precedente. El stop_details.recommended_model del rechazo entonces nombra un modelo para reintentar directamente. Dimensiona los límites de velocidad del modelo de fallback para el volumen de rechazos que esperas, o los fallbacks se degradan 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 model de nivel superior reporta el modelo que produjo el mensaje devuelto, ya sea el modelo solicitado o un fallback.
  • Un bloque de contenido 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 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 bloqueEn el siguiente turno
fallbackConsé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.
textConservar.
Cualquier bloque después del bloque fallback finalConservar.
thinking, redacted_thinking o connector_text antes del bloque fallback finalDescartar.
tool_use del lado del cliente antes del bloque fallback finalDescartar.
server_tool_use antes del bloque fallback finalConservar 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_start nombra el modelo de fallback, y el bloque fallback es el primer bloque de contenido.
  • Debido a que 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:

  • El bloque de contenido abierto se cierra, y el bloque fallback (un par ordinario de content_block_start y content_block_stop sin deltas) marca el límite.
  • El modelo de fallback continúa desde la salida parcial. Solo los bloques text de la salida parcial se pasan al modelo de fallback como contexto. Los demás 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.

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

Un intento que declinó antes de producir cualquier salida no se factura: sus tokens se reportan en su entrada de usage.iterations pero no se cobran. Cada intento que produjo salida, incluido uno que declinó a mitad de su respuesta, se factura por separado a las tarifas del modelo que lo ejecutó. 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

Cada SDK de Anthropic 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 entonces reintentan automáticamente las solicitudes rechazadas, 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 reajustan de precio sin configuración por solicitud.

Configurarlo

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 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 fallback en orden. Un modelo de fallback que a su vez rechaza pasa la solicitud a la siguiente entrada.
  • Cuando todos los modelos de la lista han declinado, el middleware devuelve el rechazo final (la respuesta de rechazo del último modelo) en lugar de lanzar un error.
  • Los bloques de pensamiento de Claude Fable 5.1 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 fallback que él mismo agregó. El modelo de fallback no puede leer los bloques de Claude Fable 5.1, que se conservan solo para ese modelo o uno más nuevo, por lo que la API los descarta.
  • Las respuestas atendidas a través del middleware incluyen un bloque de contenido fallback en cada límite entre modelos, igual que las respuestas de fallback 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:

  1. Detecta el rechazo

    Revisa la respuesta en busca de stop_reason: "refusal".

  2. Reenvía en un modelo de fallback

    Envía la misma solicitud con model establecido en un modelo de fallback, como Claude Opus 4.8. Otro modelo normalmente puede atender una solicitud que Claude Fable 5.1 o Claude Fable 5 declina. Cómo manejas el historial de la conversación depende de si canjeas un crédito de fallback:

    • Sin canjear un crédito: puedes dejar los bloques thinking y redacted_thinking anteriores en su lugar o eliminarlos para ahorrar tokens de entrada. El modelo de fallback no puede usarlos de ninguna forma: ignora los bloques de Claude Fable 5, y los bloques de Claude Fable 5.1 se conservan solo para ese modelo o uno más nuevo, por lo que la API los descarta.
    • 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).
  3. Permanece en el modelo de fallback

    Para conversaciones de varios turnos, sigue usando el modelo de fallback en los turnos subsiguientes en lugar de volver a cambiar.

Un reintento manual escribe la caché de prompts del modelo de fallback desde cero, lo que 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.

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:

  1. Recopila los elementos rechazados de los resultados.
  2. Elimina los bloques de pensamiento de Claude Fable 5.1 o Claude Fable 5 de cualquier historial de varios turnos.
  3. 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 fallbacks no 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_message en usage.iterations marca esta última), y luego alerta sobre la diferencia entre los dos conteos.
  • Ramifica según stop_reason o stop_details.type, no según 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".

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?