How to Build an AI Agent
How to Build an AI Agent
s10

Protocolos de Equipo

Colaboración

Shared Communication Rules

419 LOC12 herramientasrequest_id correlation for two protocols
One request-response pattern drives all team negotiation

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

"Los compañeros necesitan reglas de comunicación compartidas" -- un patrón solicitud-respuesta impulsa toda negociación.

Problema

En s09, los compañeros trabajan y comunican pero carecen de coordinación estructurada:

Apagado: Matar un thread deja archivos a medio escribir y config.json obsoleto. Necesitas un handshake: el lead solicita, el compañero aprueba (terminar y salir) o rechaza (continuar trabajando).

Aprobación de plan: Cuando el lead dice "refactorizar el módulo auth", el compañero comienza inmediatamente. Para cambios de alto riesgo, el lead debería revisar el plan primero.

Ambos comparten la misma estructura: un lado envía una solicitud con un ID único, el otro responde referenciando ese ID.

Solución

Protocolo de Apagado        Protocolo de Aprobación de Plan
==================           ======================

Lead             Compañero    Compañero           Lead
  |                 |           |                 |
  |--shutdown_req-->|           |--plan_req------>|
  | {req_id:"abc"}  |           | {req_id:"xyz"}  |
  |                 |           |                 |
  |<--shutdown_resp-|           |<--plan_resp-----|
  | {req_id:"abc",  |           | {req_id:"xyz",  |
  |  approve:true}  |           |  approve:true}  |

FSM compartido:
  [pending] --approve--> [approved]
  [pending] --reject---> [rejected]

Trackers:
  shutdown_requests = {req_id: {target, status}}
  plan_requests     = {req_id: {from, plan, status}}

Cómo Funciona

  1. El lead inicia el apagado generando un request_id y enviando a través de la bandeja de entrada.
shutdown_requests = {}

def handle_shutdown_request(teammate: str) -> str:
    req_id = str(uuid.uuid4())[:8]
    shutdown_requests[req_id] = {"target": teammate, "status": "pending"}
    BUS.send("lead", teammate, "Please shut down gracefully.",
             "shutdown_request", {"request_id": req_id})
    return f"Shutdown request {req_id} sent (status: pending)"
  1. El compañero recibe la solicitud y responde con approve/reject.
if tool_name == "shutdown_response":
    req_id = args["request_id"]
    approve = args["approve"]
    shutdown_requests[req_id]["status"] = "approved" if approve else "rejected"
    BUS.send(sender, "lead", args.get("reason", ""),
             "shutdown_response",
             {"request_id": req_id, "approve": approve})
  1. La aprobación de plan sigue el patrón idéntico. El compañero somete un plan (generando un request_id), el lead revisa (referenciando el mismo request_id).
plan_requests = {}

def handle_plan_review(request_id, approve, feedback=""):
    req = plan_requests[request_id]
    req["status"] = "approved" if approve else "rejected"
    BUS.send("lead", req["from"], feedback,
             "plan_approval_response",
             {"request_id": request_id,, "approve": approve})

Una FSM, dos aplicaciones. La misma máquina de estados pending -> approved | rejected maneja cualquier protocolo solicitud-respuesta.

Qué Cambió Respecto a s09

ComponenteAntes (s09)Después (s10)
Herramientas912 (+shutdown_req/resp +plan)
ApagadoSolo salida naturalHandshake solicitud-respuesta
Aprobación de planNoneSometer/revisar con aprobación
CorrelaciónNonerequest_id por solicitud
FSMNonepending -> approved/rejected

Pruébalo

python agents/s10_team_protocols.py
  1. Generar alice como codificador. Luego solicitar su apagado.
  2. Listar compañeros para ver el estado de alice después de la aprobación del apagado
  3. Generar bob con una tarea de refactoring riesgosa. Revisar y rechazar su plan.
  4. Generar charlie, hacer que someta un plan, luego aprobarlo.
  5. Escribir /team para monitorear estados