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

Protocolli di Team

Collaborazione

Shared Communication Rules

419 LOC12 strumentirequest_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

"I compagni hanno bisogno di regole di comunicazione condivise" -- un pattern richiesta-risposta guida tutta la negoziazione.

Problema

In s09, i compagni lavorano e comunicano ma mancano di coordinamento strutturato:

Shutdown: Uccidere un thread lascia i file a metà scritti e config.json obsoleto. Hai bisogno di un handshake: il lead richiede, il compagno approva (finisce ed esce) o rifiuta (continua a lavorare).

Approvazione piano: Quando il lead dice "refattorizza il modulo auth", il compagno inizia immediatamente. Per cambiamenti ad alto rischio, il lead dovrebbe prima rivedere il piano.

Entrambi condividono la stessa struttura: una parte invia una richiesta con un ID univoco, l'altra risponde riferendo a quel ID.

Soluzione

Protocollo Shutdown         Protocollo Approvazione Piano
===================         ======================

Lead             Teammate    Teammate           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 condivisa:
  [pending] --approve--> [approved]
  [pending] --reject---> [rejected]

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

Come Funziona

  1. Il lead avvia lo shutdown generando un request_id e inviando tramite l'inbox.
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. Il compagno riceve la richiesta e risponde 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. L'approvazione piano segue lo stesso identico pattern. Il compagno sottopone un piano (generando un request_id), il lead rivede (riferendo allo stesso 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, due applicazioni. La stessa macchina a stati pending -> approved | rejected gestisce qualsiasi protocollo richiesta-risposta.

Cosa è Cambiato da s09

ComponentePrima (s09)Dopo (s10)
Strumenti912 (+shutdown_req/resp +plan)
ShutdownSolo uscita naturaleHandshake richiesta-risposta
Gate pianoNessunoSottometti/rivedi con approvazione
CorrelazioneNessunarequest_id per richiesta
FSMNessunopending -> approved/rejected

Provalo

python agents/s10_team_protocols.py
  1. Spawn alice come coder. Poi richiedi il suo shutdown.
  2. Elenca i compagni per vedere lo stato di alice dopo l'approvazione dello shutdown
  3. Spawn bob con un task di refactoring rischioso. Rivedi e rifiuta il suo piano.
  4. Spawn charlie, falli sottomettere un piano, poi approvalo.
  5. Digita /team per monitorare gli stati