Sin bucle no hay agent
Todo el secreto de Claude Code cabe en una línea: while stop_reason == "tool_use"
¿Qué hace exactamente un agent?
Cuando ejecutas Claude Code en la terminal y le pides «organiza todos los comentarios TODO en una lista», lo que ves es: decide por sí solo hacer primero grep, luego cat varios archivos y finalmente generar Markdown. El modelo no ejecuta código por sí mismo — solo solicita que se ejecute. Lo que realmente lo hace parecer «autónomo» son las ~30 líneas de código de pegamento que lo envuelven.
Esta lección desmonta ese código de pegamento. Se llama agent loop, y su estructura es:
while response.stop_reason == "tool_use": response = LLM(messages, tools) # 1. ask the model execute_tools(response.tool_calls) # 2. run what it asked for messages.append(tool_results) # 3. feed results back
Eso es todo. Claude Code de producción añade permisos, hooks, subagents, aislamiento de worktree y compresión de memoria encima de esto, pero el núcleo siguen siendo estas cuatro líneas.
Intuición clave: cada vez que el modelo responde, o bien dice «quiero llamar una herramienta» o bien «ya terminé». Mientras esté en el primer estado, el bucle continúa; en cuanto entra en el segundo, el bucle sale. El criterio es el campo stop_reason de la respuesta.
Ver cómo crece messages[] paso a paso
El siguiente simulador recorre la tarea: «¿Qué archivos hay en el directorio actual? Luego lee package.json». Pulsa Step; cada pulsación avanza una acción dentro del bucle. A la izquierda, los mensajes en formato conversacional; a la derecha, el array messages[] real que recibe el modelo — observa cómo crece.
Los resultados de herramientas deben volver al historial
El error más común en principiantes es tratar «ejecutar la herramienta» como un efecto secundario — se ejecutó, listo. Pero el modelo solo puede ver messages[] en la siguiente ronda de inferencia; lo que no esté ahí, para él no ocurrió. Si falta ese append, todo el bucle falla.
Los fallos no son todos iguales. Dos casos habituales:
- Olvidar el append: el modelo no verá el resultado en la siguiente vuelta y volverá a pedir la misma herramienta — bucle infinito garantizado.
- Append sin
tool_use_id: la API de Anthropic devuelve directamentetool_result must have tool_use_idy el bucle explota en la llamada a la API.
La misma tarea: «cuenta cuántos archivos Python hay en el proyecto». Dos versiones en paralelo — compara los resultados.
Entender stop_reason
Cada respuesta del modelo incluye un campo stop_reason. La decisión de continuar o salir del bucle depende de este valor:
tool_use— el modelo quiere llamar una herramienta; continúa el bucle.end_turn— el modelo considera que terminó; sale del bucle.max_tokens— la generación fue truncada por el límite de tokens; sale del bucle (trátalo como error e informa al usuario de que la salida está incompleta).stop_sequence— se encontró una secuencia de parada personalizada; sale del bucle.
Escribir erróneamente «continúa mientras no haya tool_use», o ignorar max_tokens tratándolo como un fin normal, son bugs frecuentes.
Pruébalo en local
Clona shareAI-lab/learn-claude-code:
git clone https://github.com/shareAI-lab/learn-claude-code cd learn-claude-code pip install -r requirements.txt cp .env.example .env # fill in ANTHROPIC_API_KEY python agents/s01_agent_loop.py
Pídele algo concreto: Cuenta cuántos archivos .py hay en este repositorio. Verás cómo envía un ls -R, lee la salida, lanza un find . -name "*.py" | wc -l y finalmente te da la respuesta. Todo ese proceso es el bucle en acción.