Rechazos de Claude Fable 5: guía de fallback para devs — Cesar Ayala
← Todos los artículos

Rechazos de Claude Fable 5: guía de fallback para devs

El 1 de julio de 2026 Claude Fable 5 se re-despliega con nuevos clasificadores de seguridad que marcan más peticiones de código benignas. En las superficies de Anthropic un bloqueo se rutea solo a Opus 4.8; en la API cruda no: devuelve un stop_reason "refusal". Detéctalo, haz el fallback a Opus 4.8 tú mismo y regístralo.

El contexto en 60 segundos: Claude Fable 5 vuelve el 1 de julio con nuevos clasificadores de seguridad

El 1 de julio de 2026 Claude Fable 5 (claude-fable-5) se redespliega globalmente con un nuevo conjunto de clasificadores de seguridad que marcan más peticiones de código benignas de lo que hacían antes. Si construyes sobre la API cruda de Claude, esto te importa por una razón concreta: en las superficies de consumo de Anthropic un bloqueo del clasificador se rutea solo a Opus 4.8, pero en tu integración por API tienes tres opciones —nombrar un modelo de fallback y dejar que la API reintente del lado del servidor, usar el middleware oficial del SDK, o detectar el rechazo tú mismo—. Un bloqueo llega como un 200 con stop_reason de refusal, no como un crash. La respuesta corta: configura el fallback a Opus 4.8 y regístralo.

El resto de este post es el patrón exacto para hacerlo, con código que puedes pegar. Si aún no tienes contexto de qué es Fable 5, arranca por Claude Fable 5, explicado y luego regresa aquí.

En la API el fallback lo configuras tú: las superficies de consumo rutean solo, tu código se suscribe

Vale la pena ser preciso con quién hace qué. Según el anuncio de Anthropic, en Claude.ai, Claude Code y Claude Cowork el comportamiento es automático: “se notifica al usuario si una petición a Fable 5 es bloqueada, y la petición se envía en su lugar a Opus 4.8”. Es un fallback administrado; no tienes que escribir nada.

En la API cruda ese ruteo no está prendido por defecto, pero sí existe. Tú llamas a claude-fable-5, el clasificador se dispara, y la respuesta que recibes es un 200 con stop_reason de refusal. No hay redirección mágica a menos que la pidas. Tienes tres caminos documentados: suscribirte al fallback del lado del servidor nombrando un modelo en fallbacks, usar el middleware del SDK que envuelve la misma lógica, o detectar el rechazo y reintentar tú mismo. Si tu código asume que “una respuesta llegó” significa “una respuesta útil llegó” y no hace ninguna de las tres, vas a servirle a tu usuario una salida vacía o un mensaje de disculpa en lugar de código.

Quién hace el fallback

Superficies de Anthropic

  • Claude.ai, Claude Code, Cowork
  • Bloqueo → ruteo automático a Opus 4.8
  • Se notifica al usuario
  • No escribes nada

API cruda (tu integración)

  • Tu servidor llama a la API
  • Bloqueo → stop_reason: refusal
  • No hay ruteo por defecto, lo configuras
  • El fallback y el registro son tuyos
El mismo bloqueo del clasificador, dos comportamientos distintos según la superficie.

Este es el mismo principio que ya cubrimos para los rechazos en producción con Sonnet 5 en producción: en la API, manejar los stop_reason que no son end_turn es parte de tu contrato. Para el panorama completo de qué cambió en el redespliegue, revisa Fable 5 vuelve: qué cambia.

Cómo llega un bloqueo del clasificador a tu código: un rechazo, no un crash (stop_reason “refusal”)

Un bloqueo del clasificador no te lanza una excepción HTTP 4xx ni 5xx. La petición tiene éxito a nivel de transporte: recibes un 200, un objeto Message bien formado, y dentro de él el campo stop_reason viene con el valor refusal. Cuando el bloqueo ocurre antes de cualquier salida, el arreglo content viene vacío.

Así se ve una respuesta bloqueada, recortada:

{
  "id": "msg_01AbC...",
  "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 }
}

Dos cosas que leer aquí. Primero, stop_details.category nombra el área de política —"cyber" para el clasificador de ciberseguridad, y también existen valores como "bio" o "reasoning_extraction"—. El trabajo benigno de ciberseguridad puede disparar la categoría "cyber", que es justo el caso de falso positivo. Ambos campos son null cuando el rechazo no mapea a ninguna categoría, así que ramifica en stop_reason, nunca en stop_details. Segundo, facturación: un rechazo que llega antes de cualquier salida no se cobra —los conteos aparecen en usage pero no pagas, y no cuenta contra tus límites de tasa—. El modelo mental de “pagas doble en un rechazo” es incorrecto: pagas solo por el modelo que de verdad sirve el turno.

Y para ser claros sobre el alcance editorial de este post: aquí solo explicamos disponibilidad de modelos, clasificadores de seguridad y ruteo. El clasificador bloquea la técnica reportada de ciberseguridad en más del 99% de los casos; no describimos ni especulamos sobre esa técnica. Todo el marco es defensivo e informativo.

El recorrido de un bloqueo en la API

Llamas a Fable 5petición normal por API
El clasificador bloqueastop_reason: refusal, HTTP 200
Detectas el refusalinspeccionas stop_reason en el camino normal
Fallback a Opus 4.8reenvías la misma petición y registras
Con el fallback configurado, el reintento aterriza en Opus 4.8: del lado del servidor, por middleware del SDK, o en tu propio código.

El arreglo más simple: fallback del lado del servidor (nombras un modelo, la API reintenta)

La opción con menos código es dejar que la API haga el reintento dentro de una sola llamada. Agregas el header beta server-side-fallback-2026-06-01 y una lista fallbacks que nombra a Opus 4.8. Cuando el clasificador de Fable 5 rechaza, la API corre el fallback sobre la misma petición y devuelve una respuesta que nombra al modelo que respondió.

from anthropic import Anthropic

client = Anthropic()

resp = client.beta.messages.create(
    model="claude-fable-5",
    max_tokens=2048,
    messages=[{"role": "user", "content": "Refactor this auth middleware..."}],
    fallbacks=[{"model": "claude-opus-4-8"}],
    betas=["server-side-fallback-2026-06-01"],
)

print(resp.model)  # "claude-fable-5" o "claude-opus-4-8"

En TypeScript el SDK toma los mismos parámetros:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const resp = await client.beta.messages.create({
  model: "claude-fable-5",
  max_tokens: 2048,
  messages: [{ role: "user", content: "Refactor this auth middleware..." }],
  fallbacks: [{ model: "claude-opus-4-8" }],
  betas: ["server-side-fallback-2026-06-01"],
});

El fallback del lado del servidor está en beta en la API de Claude y en Claude Platform on AWS. No está disponible en Amazon Bedrock, Google Cloud, Microsoft Foundry ni en la Message Batches API; ahí usa el middleware del SDK o el patrón manual de abajo. Los SDKs de Anthropic también traen un BetaRefusalFallbackMiddleware oficial (con un BetaFallbackState compartido) que envuelve el mismo reintento en cualquier plataforma. Ambos aplican crédito de fallback, así que el reintento no vuelve a pagar el costo de caché del prompt.

Cuando el reintento es tuyo: detecta el rechazo y reenvía a Opus 4.8

En Ruby, PHP, HTTP crudo o cualquier lugar donde quieras control total, implementas el patrón que envuelve el middleware. La detección es una sola comparación —no hagas match sobre la prosa del modelo (“no puedo ayudarte con eso”), que es frágil y se dispara con respuestas legítimas—. Lee stop_reason.

import logging
from anthropic import Anthropic

client = Anthropic()
log = logging.getLogger("claude.routing")

PRIMARY = "claude-fable-5"
FALLBACK = "claude-opus-4-8"

def create_with_fallback(**kwargs):
    resp = client.messages.create(model=PRIMARY, **kwargs)

    if resp.stop_reason == "refusal":
        category = getattr(resp.stop_details, "category", None)
        log.warning(
            "classifier_refusal id=%s category=%s falling_back_to=%s",
            resp.id, category, FALLBACK,
        )
        resp = client.messages.create(model=FALLBACK, **kwargs)

    return resp

message = create_with_fallback(
    max_tokens=2048,
    messages=[{"role": "user", "content": "Refactor this auth middleware..."}],
)

En TypeScript, la misma forma:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();
const PRIMARY = "claude-fable-5";
const FALLBACK = "claude-opus-4-8";

async function createWithFallback(
  params: Omit<Anthropic.MessageCreateParamsNonStreaming, "model">,
) {
  let resp = await client.messages.create({ model: PRIMARY, ...params });

  if (resp.stop_reason === "refusal") {
    const category = resp.stop_details?.category ?? null;
    console.warn(`classifier_refusal id=${resp.id} category=${category} fallback=${FALLBACK}`);
    resp = await client.messages.create({ model: FALLBACK, ...params });
  }
  return resp;
}

Tres detalles que importan. Uno: reenvía la petición idéntica; no la reescribas para “esquivar” el clasificador, solo cambias qué modelo responde. Dos: stop_reason también toma valores como end_turn, max_tokens y tool_use; ramifica en refusal específicamente y deja que el resto siga tu manejo normal. Tres: si usas streaming, stop_reason llega en el message_delta final, así que acumula el turno y revísalo antes de comprometer la salida. Si quieres profundizar en ruteo y costo, lo trabajamos a fondo en ajustar Sonnet 5.

Por qué Opus 4.8 es el default pragmático para código hoy: menos falsos positivos, mitad de precio

Aquí va mi opinión de ingeniería, y es la parte que más ahorra dinero. Si Opus 4.8 es donde terminas en un rechazo de todas formas, ¿por qué arrancar en Fable 5 para código ordinario? Para código y depuración rutinarios ahora mismo, invierte el default: pon Opus 4.8 como primario y reserva Fable 5 para lo que de verdad lo necesita.

Dos razones concretas. La primera es que Opus 4.8 no arrastra el nuevo clasificador que genera esos falsos positivos en tareas de código, así que ves menos rechazos espurios. La segunda es puro presupuesto: Opus 4.8 cuesta $5 / $25 por millón de tokens de entrada/salida, contra los $10 / $50 de Fable 5. Es literalmente la mitad de precio, con el mismo contexto de 1M de tokens y 128k de salida máxima, y es el nivel Opus más capaz para razonamiento y código agéntico.

Precio por millón de tokens (entrada / salida)

Fable 5 · entrada$10
Fable 5 · salida$50
Opus 4.8 · entrada$5
Opus 4.8 · salida$25
Opus 4.8 cuesta la mitad que Fable 5 y trae menos falsos positivos del clasificador en tareas de código.

Fable 5 sigue siendo el modelo más capaz de Anthropic ampliamente disponible (GA desde el 9 de junio de 2026), y para el razonamiento más exigente o el trabajo agéntico de horizonte largo es la elección correcta. Pero pagar el doble por cada refactor trivial, y encima cargar con más falsos positivos, no es la jugada. Si estás decidiendo, lee ¿vale la pena Claude Fable 5?.

Una tabla de decisión mínima: Fable 5 vs Opus 4.8 vs Sonnet 5 / Haiku

No necesitas una matriz de diez ejes. Necesitas tres cubetas.

Qué modelo para qué trabajo

  1. Fable 5 (claude-fable-5)El razonamiento más difícil y el trabajo agéntico de horizonte largo. $10/$50. Envuélvelo con fallback.
  2. Opus 4.8 (claude-opus-4-8)Tu default para código y agéntico rutinario: menos falsos positivos, $5/$25, mismo contexto de 1M.
  3. Sonnet 5 / HaikuTodo lo demás: alto volumen, latencia baja, clasificación, extracción, chat sencillo.
Regla práctica para ruteo por API hoy. Todos los IDs y precios según los docs de Anthropic.

La lógica de ruteo puede ser tan simple como una función que mapea la dificultad de la tarea a un model id antes de llamar a create_with_fallback. No sobre-ingenierices esto: empieza con Opus 4.8 de default, sube a Fable 5 solo donde midas que hace falta, y baja a Sonnet 5 o Haiku donde el trabajo sea barato. El tutorial de la API de Claude tiene el esqueleto de cliente si arrancas de cero.

Monitorear los rechazos del clasificador para atrapar falsos positivos

El registro de una línea del patrón manual se vuelve útil cuando lo agregas. Un rechazo es un 200, así que el monitoreo basado en tasas de error o respuestas 5xx nunca lo ve: tienes que emitir el evento tú. Emite una métrica cada vez que ocurre un fallback, con la dimensión suficiente para investigar después:

import json, time

def emit_refusal_metric(prompt_kind: str, category: str):
    print(json.dumps({
        "event": "classifier_refusal",
        "ts": int(time.time()),
        "primary": "claude-fable-5",
        "fallback": "claude-opus-4-8",
        "category": category,          # p.ej. "cyber"
        "prompt_kind": prompt_kind,    # p.ej. "code_refactor", "debug"
    }))

Lo que quieres vigilar: la tasa de rechazos por tipo de prompt y por category. Si tu categoría code_refactor de pronto dispara rechazos "cyber", casi seguro es un falso positivo del clasificador nuevo, no un uso indebido. Guarda esos ejemplos benignos; son exactamente el tipo de caso que Anthropic dice que va a usar para afinar. Un tablero simple de “rechazos por día por categoría” te dice en horas si un cambio del clasificador te está pegando.

La advertencia honesta: esto es un blanco móvil por las próximas semanas

No te vendo esto como estable. Anthropic dijo explícitamente que refinará los clasificadores en las próximas semanas para reducir falsos positivos y distinguir mejor el mal uso genuino de las peticiones legítimas. Eso significa que la tasa de rechazos que midas hoy va a moverse, con suerte a la baja.

Un par de fechas que conviene tener en el calendario: en planes de pago, Fable 5 está incluido para hasta el 50% de tus límites semanales de uso hasta el 7 de julio de 2026, y después requiere créditos de uso. Los proveedores de nube (AWS, Google Cloud, Microsoft) lo rehabilitan “tan rápido como sea posible”. El redespliegue vive dentro de un esfuerzo de seguridad más amplio —acceso ampliado a Glasswing y, aparte, un marco de consenso de la industria para calificar la gravedad de los jailbreaks, más una colaboración reforzada con el gobierno de EE. UU.—, pero para tu código las únicas piezas móviles son la disponibilidad, el clasificador y tu fallback. Diseña tu ruteo para que un cambio de default sea una línea de config, no una refactorización.

Trabaja conmigo: integraciones resilientes con la API de Claude

Construir sobre modelos de frontera significa construir para el día en que un modelo dice que no. El patrón es siempre el mismo: configura un fallback a claude-opus-4-8 —del lado del servidor, por middleware, o detectando stop_reason == "refusal" tú mismo—, registra el evento con su category y monitorea la tasa. Si quieres una integración con la API de Claude que no se caiga cuando cambia un clasificador —con ruteo de modelos, fallback y observabilidad de verdad— platícame tu caso. Eso es exactamente el tipo de trabajo que hago.

Fuentes oficiales: Anthropic — Redeploying Fable 5 · Claude Platform — Models overview · Refusals and fallback