Crea un agente autónomo con Claude Sonnet 5: tool use, el loop agéntico y autoverificación — Cesar Ayala
← Todos los artículos

Crea un agente autónomo con Claude Sonnet 5: tool use, el loop agéntico y autoverificación

Claude Sonnet 5 (id claude-sonnet-5) es el Sonnet más agéntico hasta hoy: planea, usa herramientas y revisa su propia salida. Define tus tools como JSON Schema, corre un loop agéntico (de tool_use a tool_result hasta stop_reason end_turn), usa adaptive thinking con effort, agrega un paso de autoverificación y cachea el prefijo system+tools. Con el precio intro de $2/$10 hasta el 31 ago 2026, correr agentes reales sale barato.

En esta página 11 secciones
  1. Acaba de salir Claude Sonnet 5 — y viene hecho para agentes
  2. Por qué Sonnet 5 cambia las cuentas de los agentes
  3. Cómo funciona de verdad el loop agéntico
  4. Por qué la jugada cambia con el precio
  5. Define tus herramientas (JSON Schema con descripciones prescriptivas)
  6. Escribe el loop: entra tool_use, sale tool_result
  7. Deja que revise su propio trabajo (autoverificación)
  8. El tool runner del SDK vs el loop manual — cuál usar
  9. Migrar un agente que ya tienes en Sonnet 4.6
  10. Preguntas frecuentes
  11. A producción

Acaba de salir Claude Sonnet 5 — y viene hecho para agentes

Hoy, 30 de junio de 2026, Anthropic lanzó Claude Sonnet 5. Ya está vivo en todas las apps de Claude y en la Claude Platform/API, y según el anuncio es desde hoy el modelo por defecto en Free y Pro, además de estar disponible para Max, Team y Enterprise.

La frase oficial de Anthropic es directa: “the best combination of speed and intelligence” y “the most agentic Sonnet yet”. En corto: planea, usa herramientas (navegadores, terminales) y corre de forma autónoma a un nivel que hace unos meses exigía modelos mucho más grandes y caros. Es un salto sólido sobre Sonnet 4.6 en razonamiento, tool use, código y trabajo de conocimiento, con un rendimiento cercano a Opus 4.8 a un precio más bajo.

El id del modelo es claude-sonnet-5 — un id sin fecha, formato pinned-snapshot, que sirve tanto como id de API como de alias. No le agregues sufijo de fecha. En Bedrock es anthropic.claude-sonnet-5 y en Google Cloud claude-sonnet-5.

Pero este post no es cobertura de día de lanzamiento. Es un build. Vamos a armar un agente autónomo de verdad — que usa herramientas y revisa su propia salida — sobre la Messages API. Si todavía no tienes claro el concepto, lee primero qué es un agente de IA. Las fuentes oficiales: Anthropic — Introducing Claude Sonnet 5 y Models overview.

Por qué Sonnet 5 cambia las cuentas de los agentes

Mi opinión, etiquetada como tal: el titular para builders es COSTO × AGENCIA. Puedes correr agentes autónomos, que usan herramientas y se autoverifican, a precio de Sonnet.

Los números, como están al lanzamiento (confirma el precio vigente antes de presupuestar): el precio estándar es $3 por MTok de input y $15 por MTok de output. Hay un precio introductorio de $2 / $10 por MTok hasta el 31 de agosto de 2026, y después regresa a $3/$15. A precio estándar, eso es alrededor de 60% más barato por token que Opus 4.8 ($5/$25).

Ahora, seamos honestos con la brecha frente a Opus. En una evaluación de coding agéntico, Sonnet 5 anda en ~63.2% contra ~69.2% de Opus 4.8 y ~58.1% de Sonnet 4.6. Son cifras reportadas por Anthropic — revisa el anuncio para los nombres exactos de los evals. La lectura: Sonnet 5 cierra la mayor parte de la distancia a Opus 4.8 a una fracción del costo, pero Opus 4.8 sigue mandando en el coding agéntico más difícil.

Mi veredicto operativo: elige Sonnet 5 para cargas agénticas a escala; Opus 4.8 cuando necesites lo absolutamente top; y Haiku 4.5 ($1/$5) para las llamadas simples más baratas y rápidas. Sonnet 5 es el punto dulce de la gama de valor, no la frontera absoluta.

Specs que importan para agentes: contexto de 1M de tokens, 128k de output máximo (hasta 300k en la Batch API con el beta header output-300k-2026-03-24), knowledge cutoff confiable de enero de 2026 y latencia “Fast”. Para más fundamentos, /es/agentes-de-ia/.

Cómo funciona de verdad el loop agéntico

Antes de tocar código, quitemos la magia. El contrato es este: llega una tarea del usuario → Sonnet 5 planea → emite un bloque tool_use (con un nombre de herramienta, un input y un id único de tool_use) → tu código corre la herramienta real → tú agregas un bloque tool_result que referencia ese mismo tool_use_id → mandas todo de regreso → y el loop se repite.

La señal que vigilas es stop_reason. Mientras valga "tool_use", sigues iterando. Cuando cambie a "end_turn", el modelo ya tiene su respuesta final y te detienes.

Detalle clave de seguridad y control: el modelo nunca corre tus herramientas, solo las pide. Tú eres el runtime. Esa separación es toda la historia de control — tú decides qué se ejecuta, con qué permisos y con qué validación.

La diferencia con un prompt de una sola pasada: ahí obtienes una respuesta y ya. En el loop agéntico el modelo planea → usa herramientas → verifica → termina. Eso cuesta varias llamadas, y justo por eso el precio bajo de Sonnet 5 importa: hace que correr el loop multi-paso repetidamente salga barato. Y como esta superficie trae adaptive thinking, el razonamiento se intercala con la planeación entre llamadas a herramientas.

Tarea del usuarioLlega la petición; defines tools[] + system
Sonnet 5 planea y emite tool_usestop_reason = tool_use, con tool_use_id único
Tu código corre la herramientaTú eres el runtime; el modelo nunca ejecuta
Devuelves tool_resultMismo tool_use_id; lo agregas a messages
Loop hasta end_turnstop_reason = end_turn → respuesta final

Por qué la jugada cambia con el precio

Prompt de una pasada

  • Una sola llamada, una respuesta
  • Sin herramientas reales ni verificación
  • Barato pero limitado a lo que ya sabe el modelo
  • Bien para Q&A simple

Loop agéntico

  • Planea → usa herramientas → verifica → termina
  • Varias llamadas por tarea (más tokens)
  • Acciones reales: datos, búsquedas, escrituras
  • Viable a escala por el intro de $2/$10 (al lanzamiento)

Define tus herramientas (JSON Schema con descripciones prescriptivas)

Cada herramienta necesita tres cosas: un name, una descripción prescriptiva (arranca con “Llama a esta herramienta cuando…” — la descripción es tu volante de dirección) y un input_schema en JSON Schema con propiedades tipadas y campos required.

La calidad de la descripción importa más que el schema. Dile al modelo la situación exacta que debe disparar la llamada y para qué no usarla.

import anthropic

client = anthropic.Anthropic()

# Las tools y el system se mantienen ESTABLES entre turnos.
# Más adelante cacheamos este prefijo para abaratar el loop.
tools = [
    {
        "name": "get_exchange_rate",
        "description": (
            "Llama a esta herramienta cuando el usuario pida convertir "
            "un monto entre dos monedas o pregunte el tipo de cambio actual. "
            "NO la uses para precios históricos ni para criptomonedas."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "from_currency": {
                    "type": "string",
                    "description": "Código ISO 4217 de origen, ej. 'USD'.",
                },
                "to_currency": {
                    "type": "string",
                    "description": "Código ISO 4217 destino, ej. 'MXN'.",
                },
                "amount": {
                    "type": "number",
                    "description": "Monto a convertir en la moneda de origen.",
                },
            },
            "required": ["from_currency", "to_currency", "amount"],
        },
    },
    {
        "name": "lookup_invoice",
        "description": (
            "Llama a esta herramienta cuando el usuario referencie una "
            "factura por folio para consultar su estatus o total. "
            "NO la uses para crear ni modificar facturas."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "folio": {
                    "type": "string",
                    "description": "Folio de la factura, ej. 'F-2026-0042'.",
                }
            },
            "required": ["folio"],
        },
    },
]

Si quieres que estas herramientas hablen con sistemas reales (tu base de datos, tu ERP, un proveedor de pagos), el camino limpio es MCP: conecta tu agente a tus datos vía MCP. Y fija el modelo explícito: model="claude-sonnet-5".

Escribe el loop: entra tool_use, sale tool_result

Aquí está el corazón. El loop manual completo, ejecutable, con el contrato de ids al frente: el tool_use_id de tu tool_result tiene que coincidir con el id del bloque tool_use que emitió el modelo, o la API lo rechaza.

import json


def run_tool(name, tool_input):
    # Despacha por nombre a tu handler real.
    # Hazlos IDEMPOTENTES: un re-plan o reintento puede llamar dos veces.
    if name == "get_exchange_rate":
        # ...llamada real a tu fuente de tipo de cambio...
        return {"rate": 17.05, "result": tool_input["amount"] * 17.05}
    if name == "lookup_invoice":
        return {"folio": tool_input["folio"], "status": "pagada", "total": 4200.0}
    return {"error": f"herramienta desconocida: {name}"}


messages = [
    {"role": "user", "content": "¿Cuánto son 250 USD en MXN hoy?"}
]

MAX_ITERS = 8  # guarda anti-loop-infinito
for _ in range(MAX_ITERS):
    response = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=2048,
        system="Eres un agente operativo. Verifica tu resultado antes de terminar.",
        tools=tools,
        messages=messages,
        thinking={"type": "adaptive"},          # adaptive only; NO budget_tokens
        output_config={"effort": "medium"},      # default es "high"; bájalo si es simple
        # SIN temperature / top_p / top_k: no se usan en esta superficie.
    )

    # Maneja pause_turn: el modelo pausó una operación larga; reanuda.
    if response.stop_reason == "pause_turn":
        messages.append({"role": "assistant", "content": response.content})
        continue

    # Para el resto de finales, agrega el turno del assistant
    # (incluye los bloques tool_use). La rama pause_turn ya hizo su append y salió.
    messages.append({"role": "assistant", "content": response.content})

    if response.stop_reason != "tool_use":
        # end_turn (u otro final): el agente terminó.
        final_text = "".join(
            b.text for b in response.content if b.type == "text"
        )
        print(final_text)
        break

    # Ejecuta cada tool_use y construye los tool_result con el id que coincide.
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            output = run_tool(block.name, block.input)
            tool_results.append({
                "type": "tool_result",
                "tool_use_id": block.id,                       # <- DEBE coincidir
                "content": json.dumps(output, ensure_ascii=False),  # JSON válido
            })

    # El turno del usuario lleva los tool_result; el orden y los ids deben cuadrar.
    # (content también acepta una lista de bloques de contenido, no solo string.)
    messages.append({"role": "user", "content": tool_results})
else:
    print("Se alcanzó MAX_ITERS sin end_turn — revisa el agente.")

Tres cosas que no debes saltarte. Una: la guarda de max-iterations, para que un agente que se porta mal no itere para siempre. Dos: idempotencia en los handlers con efectos secundarios — usa dedup keys o check-before-write, porque tus herramientas pueden llamarse más veces de las que esperas (reintentos, re-planes). Tres: effort arranca en "high" por defecto en la Claude API y en Claude Code; bájalo a medium/low para despacho de herramientas más barato y rápido cuando la tarea es simple. Si vienes armando esto desde cero, mi guía base es cómo construir un agente de IA con Python.

  1. Define tus toolsname + descripción 'llama a esta cuando…' + input_schema (JSON Schema)
  2. Escribe el loopmessages.create con tools[], thinking adaptive, effort explícito
  3. Ejecuta y devuelvecorre cada tool_use; tool_result con tool_use_id que coincide
  4. Deja que se autoverifiqueque revise su salida contra los criterios de éxito antes de cerrar
  5. Detente en end_turnloop mientras stop_reason sea tool_use; guarda de max-iters

Deja que revise su propio trabajo (autoverificación)

Los partners de acceso temprano reportan que Sonnet 5 termina tareas donde Sonnets anteriores se quedaban cortos, y que revisa su propia salida sin que se lo pidas. Hagamos de eso una feature, no suerte.

Agrega un paso explícito de autoverificación: antes de aceptar end_turn, haz que el modelo (o una herramienta dedicada) revalide su resultado contra los criterios de éxito de la tarea y o confirme o vuelva a iterar para corregir.

Hay dos patrones. Uno: una instrucción en el system prompt que le ordene verificar antes de terminar (es lo que puse arriba). Dos: una herramienta verify_result que el agente debe llamar y que regresa pass/fail con razones.

verify_tool = {
    "name": "verify_result",
    "description": (
        "Llama a esta herramienta SIEMPRE antes de dar tu respuesta final. "
        "Revisa tu resultado contra los criterios de éxito de la tarea. "
        "Devuelve pass/fail con las razones."
    ),
    "input_schema": {
        "type": "object",
        "properties": {
            "claim": {"type": "string", "description": "El resultado a verificar."},
            "criteria_met": {"type": "boolean"},
            "reasons": {"type": "string"},
        },
        "required": ["claim", "criteria_met", "reasons"],
    },
}

Y como doble seguro, usa structured outputs con output_config.format para que la respuesta final regrese en un schema que valides en tu código, no solo en la cabeza del modelo. effort y format viven como llaves hermanas dentro de output_config:

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    messages=messages,
    output_config={
        "effort": "medium",
        "format": {
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "amount_mxn": {"type": "number"},
                    "rate_used": {"type": "number"},
                    "verified": {"type": "boolean"},
                },
                "required": ["amount_mxn", "rate_used", "verified"],
            },
        },
    },
)

La advertencia honesta: la autoverificación reduce errores, no los elimina. Mantén tus propias aserciones sobre cualquier acción con efectos secundarios.

El tool runner del SDK vs el loop manual — cuál usar

Hay dos caminos y conviene elegir a propósito.

El tool runner del SDK es el camino fácil: registras tus funciones de herramienta y el SDK maneja el loop tool_use → tool_result por ti. Menos código, más rápido para salir a producción. Es un helper en beta: en Python usas client.beta.messages.tool_runner junto con el decorador @beta_tool (el equivalente en el SDK de TypeScript se llama toolRunner).

El loop manual es para control: lógica custom de reintentos/idempotencia, observabilidad y logging en cada llamada a herramienta, aprobaciones human-in-the-loop, o despacho no estándar.

Mi take: arranca con el tool runner del SDK para prototipar, y baja al loop manual cuando necesites instrumentar o poner compuertas en el loop. De cualquier forma el contrato de abajo es idéntico — stop_reason, tool_use_id que coincide, end_turn — así que lo que aprendiste aquí se transfiere.

La palanca de costo aplica a ambos: prompt caching con cache_control sobre el prefijo estable de system + tools. El array tools[] y el system prompt se repiten en cada turno del loop; cachéalos para no pagar input completo en cada iteración. En corridas multi-paso largas el ahorro es real, además del intro de $2/$10. Tengo una guía dedicada: cachea el prefijo system+tools para bajar costos.

Modeloclaude-sonnet-5 (id sin fecha, sin sufijo)
Toolstools[] con input_schema + 'llama a esta cuando…'
Loopitera mientras stop_reason sea tool_use
Thinkingadaptive + effort explícito (default high)
Verificaciónpaso de autoverificación antes de end_turn
Costocachea el prefijo system+tools; intro $2/$10 al lanzamiento

Migrar un agente que ya tienes en Sonnet 4.6

Si ya corres un agente, la migración es corta:

  • Cambia el string del modelo a claude-sonnet-5.
  • Si usabas extended thinking con budget_tokens, cámbiate a adaptive thinking: thinking={"type": "adaptive"}. budget_tokens no está soportado.
  • Re-afina effort: Sonnet 5 trae "high" por defecto, que puede costar más o correr más lento de lo que quieres para despacho simple de herramientas. Ponlo explícito.
  • Quita cualquier temperature/top_p/top_k: no se usan en esta superficie.
  • Confirma los breaking changes exactos contra la guía de migración de Anthropic antes de ir a producción — no confíes en esta lista a ciegas.

Preguntas frecuentes

¿Cuál es el id exacto del modelo? claude-sonnet-5 — pinned snapshot sin fecha, usado como id de API y como alias. Sin sufijo de fecha.

¿Cuánto cuesta? Estándar $3/$15 por MTok; intro $2/$10 hasta el 31 de agosto de 2026, luego regresa a $3/$15. Confirma el precio vigente al momento, ya que esto está recién salido.

¿Puedo fijar un budget de thinking? No — solo adaptive thinking (thinking={"type": "adaptive"}). Controlas la profundidad con output_config.effort, no con budget_tokens.

¿Es tan bueno como Opus 4.8? Cerca en tareas agénticas (~63.2% vs ~69.2% en un eval de coding agéntico — cifras reportadas por Anthropic; revisa el anuncio para los nombres exactos), pero Opus 4.8 sigue liderando en el coding agéntico más difícil. Sonnet 5 es la gama de valor.

¿Cómo evito que el loop corra para siempre? Pon una guarda de max-iterations y detente en stop_reason == "end_turn".

¿Qué tan grande es el contexto / output? Contexto de 1M de tokens y 128k de output máximo (hasta 300k en la Batch API con el beta header output-300k-2026-03-24).

A producción

La receta entera de un jalón: modelo claude-sonnet-5, tools[] con JSON Schema y descripciones “llama a esta cuando…”, loop sobre stop_reason igual a tool_use, adaptive thinking más effort, un paso de autoverificación, y cachea el prefijo system + tools.

Sonnet 5 hace que correr agentes autónomos que se autorrevisan salga barato — especialmente durante la ventana intro de $2/$10 hasta el 31 de agosto de 2026. Confirma siempre los ids de modelo, los precios y los campos de API contra la documentación de precios de Anthropic antes de mandar a producción. Esto está recién salido y se mueve rápido.

Sigue leyendo