How to Build an AI Agent
How to Build an AI Agent
s04

Subagentes

Planificación y Coordinación

Clean Context Per Subtask

151 LOC5 herramientasSubagent spawn with isolated messages[]
Subagents use independent messages[], keeping the main conversation clean

s01 > s02 > s03 > [ s04 ] s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12

"Divide las tareas grandes; cada subtarea obtiene un contexto limpio" -- los subagentes usan mensajes[] independientes, manteniendo la conversación principal limpia.

Problema

A medida que el agente trabaja, su array de mensajes crece. Cada lectura de archivo, cada salida bash permanece en el contexto permanentemente. "¿Qué framework de testing usa este proyecto?" podría requerir leer 5 archivos, pero el padre solo necesita la respuesta: "pytest."

Solución

Agente padre                     Subagente
+------------------+             +------------------+
| messages=[...]   |             | messages=[]      | <-- fresh
|                  |  dispatch   |                  |
| tool: task       | ----------> | while tool_use:  |
|   prompt="..."   |             |   call tools     |
|                  |  summary    |   append results |
|   result = "..." | <---------- | return last text |
+------------------+             +------------------+

El contexto padre permanece limpio. El contexto subagente se descarta.

Cómo Funciona

  1. El padre obtiene una herramienta task. El hijo obtiene todas las herramientas base excepto task (sin generación recursiva).
PARENT_TOOLS = CHILD_TOOLS + [
    {"name": "task",
     "description": "Spawn a subagent with fresh context.",
     "input_schema": {
         "type": "object",
         "properties": {"prompt": {"type": "string"}},
         "required": ["prompt"],
     }},
]
  1. El subagente comienza con messages=[] y ejecuta su propia boucle. Solo el texto final vuelve al padre.
def run_subagent(prompt: str) -> str:
    sub_messages = [{"role": "user", "content": prompt}]
    for _ in range(30):  # safety limit
        response = client.messages.create(
            model=MODEL, system=SUBAGENT_SYSTEM,
            messages=sub_messages,
            tools=CHILD_TOOLS, max_tokens=8000,
        )
        sub_messages.append({"role": "assistant",
                             "content": response.content})
        if response.stop_reason != "tool_use":
            break
        results = []
        for block in response.content:
            if block.type == "tool_use":
                handler = TOOL_HANDLERS.get(block.name)
                output = handler(**block.input)
                results.append({"type": "tool_result",
                    "tool_use_id": block.id,
                    "content": str(output)[:50000]})
        sub_messages.append({"role": "user", "content": results})
    return "".join(
        b.text for b in response.content if hasattr(b, "text")
    ) or "(no summary)"

El historial completo de mensajes del hijo (posiblemente 30+ llamadas de herramientas) se descarta. El padre recibe un resumen de un párrafo como un tool_result normal.

Qué Cambió Respecto a s03

ComponenteAntes (s03)Después (s04)
Herramientas55 (base) + task (padre)
ContextoCompartido únicoAislamiento padre + hijo
SubagenteNonefunción run_subagent()
Valor retornoN/ASolo texto de resumen

Pruébalo

python agents/s04_subagent.py
  1. Usar una subtarea para encontrar qué framework de testing usa este proyecto
  2. Delegar: leer todos los archivos .py y resumir lo que hace cada uno
  3. Usar una task para crear un nuevo módulo, luego verificarlo desde aquí