Ajusta Claude Sonnet 5 para costo y calidad: effort, caché de prompts y la Batch API — Cesar Ayala
← Todos los artículos

Ajusta Claude Sonnet 5 para costo y calidad: effort, caché de prompts y la Batch API

Sonnet 5 es la gama de valor a $3/$15 ($2/$10 de intro hasta el 31 de agosto de 2026). El effort viene en high por defecto: bájalo por ruta. Cachea el prefijo estable de system+tools (lecturas ~0.1x), batchea los trabajos offline (−50%) y rutea lo difícil a Opus 4.8 y lo trivial a Haiku 4.5. Modela tu cuenta al precio estándar.

La cuenta que nadie modela: la economía real de Sonnet 5

Llevo años metiendo agentes de Claude en producción, y el error que más veo no es de código: es de modelado de costo. La gente integra el modelo nuevo, lo ve funcionar, y nunca abre la calculadora. Con Claude Sonnet 5 ese error sale caro por una razón sencilla: trae varias palancas de costo activas por defecto en el modo más caro.

Primero, seamos honestos sobre qué es Sonnet 5. Es la gama de valor: cerca de Opus 4.8 en calidad a un precio mucho menor, pero NO es la frontera absoluta. Si tu tarea es de las difíciles de verdad, sigue siendo Opus 4.8. Sonnet 5 es el caballo de batalla para el 80% de las rutas.

Los datos duros que necesitas para modelar (confirma siempre los actuales en la doc, el modelo es nuevo):

  • El model id es exactamente claude-sonnet-5 — formato pinned-snapshot sin sufijo de fecha. Un typo aquí te da un 404, no un fallback silencioso.
  • Contexto de 1M de tokens; salida máxima de 128k (hasta 300k en la Batch API con el beta header output-300k-2026-03-24).
  • Precio estándar: $3 / $15 por MTok (input / output). Precio introductorio de $2 / $10 hasta el 31 de agosto de 2026.

Aquí está la trampa: el precio intro es temporal. Pilotea hoy aprovechándolo, pero modela tu cuenta de producción al precio estándar $3/$15, porque cuando llegue septiembre tu factura no te va a avisar, simplemente va a subir 50%. Y según la doc de modelos de Anthropic, el parámetro effort viene en high por defecto en la Claude API y en Claude Code — o sea que la integración ingenua gasta de más en cada llamada sin que te enteres.

Lo bueno: hay cuatro palancas (effort, caché de prompts, Batch API y ruteo) que apilan ahorro. No eliges una, las usas todas. Vamos por ellas.

effortviene en high por defecto — bájalo por ruta
caché de promptslecturas a ~0.1x del precio de input
Batch API−50% en trabajos offline
precio$2/$10 intro hasta 31 ago 2026, luego $3/$15
ruteoOpus 4.8 lo difícil · Haiku 4.5 lo trivial

El mapa de palancas: a dónde se van tus pesos de verdad

Antes de entrarle a cada una, quédate con el mapa completo. Son cuatro palancas independientes que se apilan:

  1. effort — viene en high; bájalo donde puedas.
  2. Caché de prompts — las lecturas cuestan ~0.1x del precio de input.
  3. Batch API — 50% de descuento para trabajos offline.
  4. Ruteo por tarea — Sonnet 5 por defecto, escalas a Opus 4.8, bajas a Haiku 4.5.

Encima de las cuatro va la realidad temporal del precio: $2/$10 ahora, $3/$15 después del 31 de agosto. Y la regla de oro: re-tunea cada palanca por ruta, no una sola vez en global. Un clasificador de chat y un loop agéntico no deberían compartir configuración.

Un detalle que cambia toda tu estrategia: input y output NO pesan igual. El output a $15/MTok es donde explotan las cuentas. Por eso las rutas que generan mucho texto (resúmenes largos, generación de código, agentes que parlotean) son las que más escrutinio merecen. Ahí es donde bajar el effort o batchear te ahorra de verdad.

Input a precio completo (1.0x)100
Lectura de caché (~0.1x)10
Batch API (−50%)50
Output intro vs estándar ($10 vs $15)67

Las barras son ilustrativas del costo relativo de cada palanca sobre una carga estable — no son un benchmark. Confirma los multiplicadores actuales en la doc.

Palanca 1 — el parámetro effort: deja de quedarte en high

output_config.effort toma cuatro valores — low, medium, high, max — y en Sonnet 5 viene en high en la Claude API y en Claude Code. Más effort significa más razonamiento, más llamadas a herramientas y más tokens: más calidad, sí, pero también más costo y más latencia. Menos effort es más terso, más barato, más rápido, con menos tool calls.

Un punto clave de Sonnet 5: usa adaptive thinking únicamente. La configuración es thinking: {"type": "adaptive"} — no hay budget_tokens, y tampoco acepta temperature, top_p ni top_k; mandarlos produce un error 400 invalid_request_error. La profundidad la controlas con effort, punto.

Para una ruta de clasificación o extracción —donde no necesitas que el modelo se ponga filosófico— bájale a low:

from anthropic import Anthropic

client = Anthropic()

# Ruta de extracción: tarea trivial, no necesita razonamiento profundo.
# Recuerda: effort viene en "high" por defecto, así que aquí lo bajamos a propósito.
resp = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=512,
    output_config={"effort": "low"},
    system="Extrae el monto y la moneda. Responde solo JSON.",
    messages=[{"role": "user", "content": "El cliente pagó MXN 1,499.00 por el plan anual."}],
)
print(resp.content[0].text)

Reserva max para cuando la correctitud importa más que el costo (un cálculo fiscal, una decisión que no puedes equivocar). Para rutas triviales o sensibles a latencia, low o medium. Y otra vez: tunea el effort por ruta.

effort: low

  • Más barato y más rápido
  • Respuestas más tersas
  • Menos llamadas a herramientas
  • Ideal para clasificar, extraer, rutear

effort: high (default)

  • Más exhaustivo y autoverificador
  • Más tokens de razonamiento
  • Más tool calls en loops agénticos
  • Resérvalo (o sube a max) cuando la correctitud manda

Palanca 2 — cachea el prefijo estable (lecturas a ~0.1x)

Si tu system prompt y tus herramientas se repiten llamada tras llamada —y en un agente casi siempre se repiten— estás pagando ese prefijo completo cada vez sin necesidad. La caché de prompts lo arregla: pones cache_control: {"type": "ephemeral"} al final del prefijo estable.

El orden de render es tools -> system -> messages, así que un breakpoint en el último bloque de system cachea tools+system juntos. Tienes máximo 4 breakpoints. Una lectura de caché cuesta ~0.1x del precio de input; una escritura cuesta 1.25x (TTL de 5 minutos) o 2x (TTL de 1 hora, con "ttl": "1h").

Un detalle que la gente olvida: el mínimo cacheable depende del modelo (del orden de 1k a 4k tokens según el modelo y la plataforma). NO lo des por hecho para Sonnet 5: confírmalo en la doc antes de asumir, porque el modelo es nuevo. Esto importa muchísimo, porque si tu prefijo no llega al mínimo, no se cachea y no te avisa con error — simplemente pagas precio completo. Lo desgloso a fondo en la caché de prompts para bajar costos de tokens.

resp = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "Eres el asistente de soporte de Nixbly. [...instrucciones largas y estables...]",
            # Breakpoint al FINAL del prefijo estable: cachea tools+system.
            "cache_control": {"type": "ephemeral"},
        }
    ],
    messages=[{"role": "user", "content": "¿Cómo configuro un webhook de Stripe?"}],
)

# Verifica que SÍ está cacheando. usage.cache_read_input_tokens es lecturas;
# usage.cache_creation_input_tokens es escrituras. Si la lectura sale 0 en
# peticiones repetidas con el mismo prefijo, algo lo está invalidando en silencio.
print("cache_read:", resp.usage.cache_read_input_tokens)
print("cache_creation:", resp.usage.cache_creation_input_tokens)

La regla de oro de operación: revisa usage.cache_read_input_tokens. Si sale cero entre peticiones con prefijo idéntico, tienes un invalidador silencioso — un datetime.now() metido en el system, un JSON sin ordenar, un set de herramientas que cambia de orden. Congela el system prompt, mantén las herramientas determinísticas y empuja TODO lo volátil (timestamps, IDs por petición, la pregunta del usuario) después del último breakpoint.

Palanca 3 — la Batch API para trabajos offline (−50%)

Esta es plata gratis que la gente deja en la mesa. Cualquier trabajo que el usuario NO esté esperando en tiempo real —enriquecimiento nocturno, clasificación masiva, backfills, reprocesar histórico— corre en la Message Batches API al 50% del precio estándar de tokens.

Los límites: hasta 100k requests o 256 MB por batch, resultados disponibles ~29 días, la mayoría termina en menos de una hora (máximo 24h). Y como bono, desbloquea hasta 300k tokens de salida con el beta header output-300k-2026-03-24 (contra 128k del modo síncrono).

batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": "factura-001",
            "params": {
                "model": "claude-sonnet-5",
                "max_tokens": 512,
                # effort low DENTRO del batch: trabajo masivo y barato.
                "output_config": {"effort": "low"},
                "messages": [{"role": "user", "content": "Clasifica: 'Pago recurrente SaaS USD'"}],
            },
        },
        # ...hasta 100k requests aquí.
    ],
)
print(batch.id, batch.processing_status)

# Después, haces poll hasta que termine y lees resultados:
# done = client.messages.batches.retrieve(batch.id)
# for r in client.messages.batches.results(batch.id):
#     print(r.custom_id, r.result)

La regla de decisión es brutal de simple: si el usuario no está esperando la respuesta en vivo, va en batch. Punto. Y el batch se apila con las otras palancas — fíjate que metí effort: low adentro de los params. Un Haiku 4.5 a effort low, dentro de un batch, con prefijo cacheado, es literalmente el piso de la curva de costo.

Palanca 4 — rutea por tarea: Sonnet 5 por defecto, escala, baja de marcha

El ruteo es la palanca de mayor apalancamiento de todas, y la que más gente ignora. Un pipeline 100% Opus está pagando precio de frontera por trabajo de gama de valor. La estrategia:

  • Sonnet 5 (claude-sonnet-5) por defecto — tu caballo de batalla.
  • Escala a Opus 4.8 (claude-opus-4-8) solo las tareas más difíciles.
  • Baja a Haiku 4.5 (claude-haiku-4-5) lo trivial — clasificar, rutear, extraer.
def elegir_modelo(dificultad: str):
    # Rutea modelo + effort por una señal de dificultad de la tarea.
    if dificultad == "alta":
        return "claude-opus-4-8", "high"      # correctitud crítica
    if dificultad == "baja":
        return "claude-haiku-4-5", "low"      # piso de costo
    return "claude-sonnet-5", "medium"        # el caballo de batalla

model, effort = elegir_modelo("media")
resp = client.messages.create(
    model=model,
    max_tokens=1024,
    output_config={"effort": effort},
    messages=[{"role": "user", "content": "Resume este ticket de soporte."}],
)

Un caveat que te va a morder si no lo sabes: cambiar de modelo a medio camino invalida la caché de prompts — las cachés están atadas al modelo. Si tu loop salta de Sonnet a Opus y de regreso, tiras tu caché cada vez. La solución: un modelo por loop, y si necesitas una subtarea más barata, lanza un subagente con su propio modelo en lugar de intercambiar a media conversación.

Nota honesta: no te pases de ruteo. Mide antes de asumir que una tarea necesita Opus. Muchas veces Sonnet 5 a medium ya la resuelve, y te ahorraste el salto de precio. Si quieres el panorama completo de cuánto cuesta meter IA, lo desarrollo en cuánto cuesta integrar IA en tu app, y la migración específica a Sonnet 5 en qué cambia y cómo migrar.

  1. Fija el effort por rutaNo te quedes en el default; reserva max para correctitud crítica
  2. Cachea el prefijo system+toolsBreakpoint al final del bloque estable; verifica cache_read_input_tokens
  3. Batchea los trabajos offline−50% en todo lo que el usuario no espera en vivo
  4. Rutea: difícil -> Opus 4.8, trivial -> Haiku 4.5Sonnet 5 por defecto; un modelo por loop para no tirar la caché
  5. Modela la economía a $3/$15 estándarEl intro de $2/$10 termina el 31 ago 2026

Ops en producción: reintentos, streaming e idempotencia para que el ahorro aguante

Un pipeline barato que se cae no sirve de nada. Estos son los detalles operativos que los posts de lanzamiento se saltan.

Streaming. Cualquier petición que pueda generar salida larga, stréamala. La salida de 128k de Sonnet 5 prácticamente lo exige: sin streaming, las peticiones de salida larga arriesgan timeouts de HTTP, y Anthropic recomienda streaming para max_tokens altos. Usa client.messages.stream(...) y .get_final_message() para el mensaje completo. Los detalles los cubre la doc de streaming de Anthropic.

Ramifica por stop_reason. No leas el contenido a ciegas:

  • end_turn — terminó.
  • tool_use — corre la herramienta y continúa.
  • max_tokens — sube el límite o stréamalo.
  • pause_turn — herramienta de servidor; reenvía para reanudar.
  • refusal — declinación de seguridad; manéjala, no leas el contenido como si nada.

Excepciones tipadas, nunca string-matching. Usa las clases (anthropic.RateLimitError, anthropic.APIError), que exponen .status y .type. Los SDKs oficiales autoreintentan 429 y 5xx con backoff exponencial (max_retries=2 por defecto). Qué es reintentable y qué no:

  • Reintentable: 429 rate_limit_error (sí, honra el header retry-after), 500 api_error, 529 overloaded_error.
  • NO reintentable: 400, 401, 403, 404, 413. Ejemplo clásico: un claude-sonnet-5 mal escrito te da 404 not_found_error y reintentar no lo arregla.

Idempotencia. Pasa un Idempotency-Key en peticiones que un agente podría reenviar tras un timeout, para no duplicar trabajo ni duplicar cargos. Y a escala, diseña para 429 con una cola y jitter, aunque el SDK ya haga backoff por su cuenta. Más sobre correr esto en serio en LLM en producción.

Preguntas frecuentes

¿Pilote ya al precio intro de $2/$10? Sí, pilotea ya. Pero modela tu cuenta de producción a $3/$15 estándar: el intro termina el 31 de agosto de 2026 y tu factura subirá sola.

¿Por qué mi cache_read_input_tokens siempre sale cero? Un invalidador silencioso en el prefijo: un timestamp, un JSON sin ordenar, un set de herramientas variable. Diffea los bytes del prompt renderizado. Y confirma que tu prefijo pase el mínimo cacheable del modelo (depende del modelo y la plataforma, del orden de 1k a 4k tokens; verifica el de Sonnet 5 en la doc) — por debajo no cachea.

¿Puedo poner un presupuesto de thinking? No. Sonnet 5 es adaptive thinking únicamente; budget_tokens y temperature no se aceptan. La profundidad la controlas con output_config.effort.

¿Sonnet 5 es tan bueno como Opus 4.8? Es la gama de valor: cerca, a menor costo, pero no la frontera. Rutea lo más difícil a Opus 4.8.

¿Batch o caché para un trabajo offline grande? Las dos. Batch por el −50%, caché por el prefijo compartido. Se apilan.

¿Cuál es la llamada más barata posible? Haiku 4.5, effort low, dentro de un batch, con prefijo cacheado. Ese es el piso.

Cierre: ajústalo por ruta

La ganancia no está en una sola configuración mágica. Está en tunear las cuatro palancas —effort, caché, batch y ruteo— por ruta. Sonnet 5 por defecto, baja el effort donde puedas, cachea el prefijo estable, batchea lo offline, y escala a Opus 4.8 solo cuando la correctitud lo exija.

Modela la cuenta al precio estándar $3/$15 y el ahorro es real de cualquier forma — si el intro sigue activo, mejor todavía. Si quieres seguir por aquí, tengo más guías de agentes de IA.