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

Протоколы команды

Коллаборация

Shared Communication Rules

419 LOC12 инструментовrequest_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

"Товарищам нужны общие правила коммуникации" -- один паттерн запрос-ответ управляет всей координацией.

Проблема

В s09 товарищи работают и общаются, но не имеют структурированной координации:

Shutdown: Убийство потока оставляет файлы наполовину записанными и config.json устаревшим. Нужно рукопожатие: lead запрашивает, товарищ одобряет (завершить и выйти) или отклоняет (продолжать работу).

Утверждение плана: Когда lead говорит "рефакторить модуль auth", товарищ начинает сразу. Для рискованных изменений lead должен сначала просмотреть план.

Оба имеют одинаковую структуру: одна сторона отправляет запрос с уникальным ID, другая отвечает, ссылаясь на этот ID.

Решение

Shutdown Protocol            Plan Approval Protocol
==================           ======================

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}  |

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

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

Как Это Работает

  1. Lead инициирует shutdown, генерируя request_id и отправляя через почтовый ящик.
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. Товарищ получает запрос и отвечает 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. Утверждение плана следует идентичному паттерну. Товарищ отправляет план (генерируя request_id), lead просматривает (ссылаясь на тот же 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})

Один FSM, два применения. Одна и та же машина состояний pending -> approved | rejected обрабатывает любой протокол запрос-ответ.

Что Изменилось с s09

КомпонентДо (s09)После (s10)
Инструменты912 (+shutdown_req/resp +plan)
ShutdownТолько естественный выходРукопожатие запрос-ответ
Планирование gatingНетОтправка/просмотр с утверждением
КорреляцияНетrequest_id на запрос
FSMНетpending -> approved/rejected

Попробуйте

python agents/s10_team_protocols.py
  1. Создать alice как кодера. Затем запросить её shutdown.
  2. Перечислить товарищей, чтобы увидеть статус alice после утверждения shutdown
  3. Создать bob с рискованной задачей рефакторинга. Просмотреть и отклонить его план.
  4. Создать charlie, попросить его отправить план, затем утвердить его.
  5. Введите /team для мониторинга статусов