Clasificadores refusals y zonas de falsos positivos

Resumen

Tu servidor devuelve HTTP 200, tu dashboard de errores está limpio y tu pipeline sigue procesando. Pero el modelo no respondió nada. El campo content llegó vacío y nadie se enteró. Así se ve un refusal en Fable 5 cuando entiendes cómo manejar rechazos del modelo en producción.

¿Por qué un rechazo de Fable 5 parece un HTTP 200 exitoso?

Cuando el modelo decide no responder tu request, no obtienes un 403 ni un 500. Recibes un 200 limpio con stop_reason igual a refusal, content como array vacío y un usage que muestra tokens de input consumidos pero cero tokens de output [0:10].

Tu código que verifica status codes ve un éxito. Tu lógica que ramifica sobre content vacío por otras razones sigue adelante sin alarma. Y en Message Batches la trampa se duplica: un ítem rechazado llega como result.type: succeeded con stop_reason: refusal [0:46].

¿Cómo detecto un refusal en la API de Claude? Lee response.stop_reason. Si es igual a refusal, maneja el rechazo. Cualquier otra cosa, lee content. Sin atajos.

Hay un detalle que confunde: stop_details puede tener category null, explanation null, o ambos null al mismo tiempo. Eso es comportamiento normal. Nunca ramifiques tu lógica sobre stop_details [1:00].

¿Qué decide si un request pasa o lo bloquean los clasificadores de safety?

Los clasificadores de safety no son regex ni listas de palabras prohibidas. Son modelos de IA separados que corren encima de cada request, inspeccionan el input y el contexto completo, y deciden si la generación procede [1:25].

Vigilan cuatro áreas concretas:

  • Ciberseguridad, con exploits, malware, movimiento lateral y reconocimiento.
  • Biología y química de uso dual.
  • Destilación, etiquetada como frontier_llm, que detecta intentos de extraer capacidades para entrenar competidores.
  • reasoning_extraction, que se dispara cuando le pides al modelo que muestre su razonamiento interno [2:00].

Y aquí viene lo interesante para tu factura. Si el clasificador dispara antes de generar output, content está vacío, no te cobran y el request no cuenta contra rate limits. Pero si dispara a mitad de generación, los tokens ya producidos se cobran a tarifa normal y ese output parcial hay que descartarlo. La tasa promedio documentada es menos del 5% de sesiones [2:30].

¿Por qué los clasificadores generan tantos falsos positivos en producción?

Los clasificadores son pattern matchers, no jueces de intención. No entienden tu propósito: ven vocabulario. Imagina un perro guardián que no distingue al cartero del ladrón porque ambos se acercan a la puerta [2:51].

La zona más documentada es ciberseguridad defensiva. Un pipeline de penetration testing donde haces grep sobre output de exploit-db se ve idéntico a desarrollo de exploits para el clasificador. Security code review aparece listado explícitamente como ejemplo de falso positivo [3:12]. Decompilación y reverse engineering comparten vocabulario con malware. Hasta un físico médico reportó que preguntas de dinámica de fluidos disparaban refusals [3:34].

El factor agravante: el clasificador ve tu workspace completo. Tu archivo CLAUDE.md, el contexto del repositorio, nombres de directorios y git status. Un repositorio llamado security-scanner puede disparar un flag antes de que preguntes nada [3:48].

¿Cómo reduzco falsos positivos en Fable 5? Inicia sesión nueva, sé explícito sobre el propósito defensivo en el prompt, rutea cargas sensibles directo a Opus 4.8, y aplica al Cyber Verification Program si haces pentesting o red-teaming [4:00].

Para cargas de ciencia y seguridad, análisis independientes midieron tasas de refusal del 8 al 9%, muy por encima del promedio general [4:33].

¿En qué se diferencian Fable 5 y Mythos 5 si comparten el mismo modelo base?

Mismos pesos. Misma ventana de un millón de tokens. Mismo precio. Mismo tokenizer. Mismo adaptive thinking. La diferencia es exactamente una: Fable 5 tiene clasificadores activos. Mythos 5 no [4:58].

Esto explica los benchmarks con asterisco. ExploitBench, BioMysteryBench y ProgramBench fueron corridos sobre Mythos 5, sin la capa de clasificadores. El modelo base es idéntico, pero la experiencia en producción es radicalmente distinta. Mythos 5 solo está disponible bajo Project Glasswing [5:31].

¿Qué rutas de fallback usar cuando llega un refusal?

Tu código contra Fable 5 necesita manejar refusals. Tienes tres rutas ordenadas por preferencia:

  1. Server-side fallbacks: agregas un parámetro fallbacks con hasta tres modelos. Si Fable 5 rechaza, el servidor intenta el siguiente automáticamente. Un request, una respuesta. Requiere el header beta server-side-fallback-2026-06-01, disponible en Claude API y Claude Platform on AWS [5:52].
  2. Middleware de SDK: lo registras al construir el cliente. Intercepta cada respuesta, verifica stop_reason y si es refusal reintenta con tu modelo fallback. En streaming, empalma los eventos del fallback sobre el stream abierto. Disponible en TypeScript, Python, Go, Java y C# [6:22].
  3. Patrón manual con escalera de rechazo para Ruby, PHP o HTTP raw: usas un fallback credit token para que el retry no refacture tu prefix de cache como escritura fría [6:40].

Un detalle crítico en streaming: stop_reason es null en message_start. Llega en message_delta. Si tu listener solo lee message_start, nunca detecta el refusal [7:00].

¿Qué edge cases debo manejar al implementar fallbacks?

Tu código de producción debe contemplar tres situaciones particulares:

  • Sticky routing: tras un fallback, los requests siguientes en la misma conversación van directo al fallback durante aproximadamente una hora, sin fallback content block. La única detección es response.model [7:13].
  • Declines a mitad de streaming: el content block se cierra, aparece un fallback block y el segundo modelo continúa desde donde el primero paró, sin reconexión [7:27].
  • Echo block-by-block: cuando continúas una conversación multi-modelo, debes eliminar thinking blocks y tool use sin resultado antes del último fallback block, o recibes un 400 [7:37].

En la siguiente clase vas a conectar esto con la pregunta organizacional más grande: retención de datos, Project Glasswing y cómo decidir si Fable 5 es viable para tu contexto o si necesitas argumentar otra ruta ante tu equipo. ¿Ya instrumentaste stop_reason en cada path de tu API? Cuéntame en los comentarios qué patrón te ha funcionado mejor.