Lección 01 · Base

Sin bucles no hay agente

Todo el secreto de Claude Code se puede escribir en una línea: while stop_reason == "tool_use"

⏱ ~10 min · 📝 3 widgets interactivos · 🧑‍💻 Basado en shareAI-lab · s01_agent_loop.py

¿Qué hace exactamente un agente?

Cuando ejecutas Claude Code en la terminal y le permites "organizar todos los comentarios TODO en una lista", lo que ves es: decide por sí solo primero grep, luego cat algunos archivos y luego genera Markdown. El modelo no ejecuta el código por sí mismo; solo solicita que se ejecute. Lo que realmente hace que parezca "con manos y pies" son las aproximadamente 30 líneas de código de pegamento que lo rodean.

Esta lección consiste en desmontar el círculo de pegamento y ver con claridad. Se llama bucle de agente (bucle de agente), y su estructura es:

mientras respuesta.stop_reason == "tool_use":
    respuesta = LLM(mensajes, herramientas) # 1. pregunta al modelo
    ejecutar_tools(response.tool_calls) # 2. ejecuta lo que solicitó
    message.append(tool_results) # 3. retroalimentar los resultados

Eso es todo. No más. El Código de producción de Claude tiene permisos, enlaces, subagentes, aislamiento del árbol de trabajo y compresión de memoria apilados encima de esto, pero el núcleo siguen siendo estas cuatro líneas.

Intuición clave: Cada vez que el modelo responde, es "Quiero ajustar la herramienta" o "Ya terminé". El bucle continúa mientras se encuentre en el estado anterior; una vez que entra en este último estado, el bucle sale. El criterio es el campo stop_reason en la respuesta.

Ver mensajes[] crecer paso a paso

La tarea de la siguiente simulación de bucle es: "¿Qué archivos hay en el directorio actual? Luego lea package.json". Haga clic en Paso. Cada vez que lo presionas, avanzas una acción en el ciclo. A la izquierda está el bocadillo visto por humanos, a la derecha está la matriz messages[] real insertada en el modelo; observe cómo crece.

Los resultados de la herramienta deben volver a ingresarse en el historial de mensajes.

El error más fácil para los principiantes es considerar la "herramienta de ejecución" como un efecto secundario: una vez ejecutada, ya está. Sin embargo, el modelo solo puede ver mensajes[] en la siguiente ronda de inferencia y no sabe que han sucedido cosas que no están en él. Sin el paso de agregar, todo el ciclo sería incorrecto.

No todos los errores son iguales. Dos tipos comunes:

  • Olvídate de agregar: el modelo no verá los resultados la próxima vez, solicitará la misma herramienta nuevamente y obtendrás un bucle infinito.
  • Agregar pero perder tool_use_id: Anthropic API informará directamente un error tool_result must have tool_use_id y el bucle colapsará en el paso de llamada de la API.

La misma tarea: "Cuenta cuántos archivos Python hay en el proyecto". Ejecute las dos versiones una al lado de la otra para ver la diferencia en los finales.

Comprender stop_reason

Cada vez que el modelo regrese, traerá un stop_reason. Para decidir si continuar el ciclo, basta con mirar este campo:

  • tool_use: el modelo quiere ajustar la herramienta, continuar con el bucle.
  • end_turn: el modelo siente que ha terminado y sale del bucle.
  • max_tokens: cuando se genera el límite superior de tokens, se trunca y sale del bucle (generalmente se maneja como una excepción para avisar al usuario que la salida está incompleta).
  • stop_sequence: cuando se encuentra una secuencia de parada personalizada, salga del bucle.

Escribir incorrectamente como "continuar mientras no haya tool_use", o ignorar max_tokens y tratarlo directamente como un final normal, son errores comunes.

Toma acción y corre

Clon local shareAI-lab/learn-claude-code:

clon de git https://github.com/shareAI-lab/learn-claude-code
cd aprender-claude-código
instalación de pip -r requisitos.txt
cp .env.example .env # complete ANTHROPIC_API_KEY
agentes de Python/s01_agent_loop.py

Entonces deja que haga algo real: Ayúdame a contar cuántos archivos .py hay en este repositorio. Verá que envía un ls -R, verá el resultado y enviará otro find. -nombre "*.py" | wc -l y luego te diré la respuesta. Todo el proceso es este bucle.

Interactivo

Widget 1 · Loop Stepper · mensajes[] crecimiento

Comprenda: los resultados de la herramienta se vuelven a incluir en mensajes en un formato especial (bloque tool_result, con tool_use_id); esta es la única manera de que el modelo sepa que "la herramienta se ha ejecutado y el resultado es X" en la siguiente ronda de inferencia.

对话视图未开始
点 Step 开始 →
messages[] JSONlength: 0
[]
stop_reason:
Interactivo

Widget 2 · Romper el bucle · Corregir vs Olvidé agregar

Comprenda: mientras falte una línea messages.append(tool_results), todo el agente ya no es un agente: se convierte en una máquina de lectura que olvida el anterior en cada ronda.

while True:
    resp = LLM(msgs, tools)
    msgs.append({"role":"assistant",
                 "content": resp.content})
    if resp.stop_reason != "tool_use":
        return
    results = execute(resp.tool_uses)
    msgs.append({"role":"user",
                 "content": results})
模拟运行
while True:
    resp = LLM(msgs, tools)
    msgs.append({"role":"assistant",
                 "content": resp.content})
    if resp.stop_reason != "tool_use":
        return
    results = execute(resp.tool_uses)
    # BUG: forgot to append results
    # msgs.append(...)
模拟运行
Interactivo

Widget 3 · Encuentra la razón_detención · Juzga 4 respuestas verdaderas

Cada uno es un fragmento de un posible modelo de respuesta real. Haga clic en "Continuar" o "Salir" para ver si tiene razón o no.

答对 0 / 4