Протокол рукопожатия между двумя агентами
Агенты тоже «подписывают контракты». request_id — это номер контракта.
Зачем нужен протокол?
В s09 через send_message можно передать любой текст. Но когда два агента должны договориться о чём-то конкретном (например, «я хочу завершить работу, можно?»), просто строки недостаточно — нужны:
- Идентификатор запроса (request_id), чтобы ответ можно было сопоставить с запросом.
- Конечный автомат (FSM): pending → approved | rejected, последствия каждого состояния чётко определены.
- Согласованные поля: обе стороны знают, что означает
approve: true.
Именно для этого существуют shutdown_request / shutdown_response / plan_approval / plan_approval_response.
Полный сценарий протокола shutdown
Lead хочет завершить работу alice:
lead: # отправляем shutdown_request, сервер записывает request_id req_id = uuid4()[:8] shutdown_requests[req_id] = {"target": "alice", "status": "pending"} send("alice", "shutdown_request", extra={"request_id": req_id}) alice: # в следующем цикле loop читает inbox, видит shutdown_request # решает: закончить текущую работу и ответить согласием tool_use("shutdown_response", request_id=req_id, approve=True) lead: # получает shutdown_response, обновляет tracker до approved shutdown_requests[req_id]["status"] = "approved" # поток alice обнаруживает подтверждение, устанавливает status=shutdown и выходит из цикла
Визуализация FSM протокола shutdown
Наблюдайте за конечным автоматом шаг за шагом. Alice также может отклонить запрос — сказать «я в середине важной работы, сейчас не могу остановиться».
Plan Approval · тот же паттерн, другая область
Teammate отправляет plan на согласование lead перед крупными изменениями:
alice: tool_use("plan_approval", plan="Собираюсь полностью переписать auth-модуль на JWT") # alice ждёт в idle, пока lead не ответит lead: # видит запрос plan_approval_response от alice tool_use("plan_approval", request_id="...", approve=False, feedback="Пока не трогай auth — в следующем месяце будет полный рефакторинг")
В исходниках s10 заметно: оба протокола используют абсолютно одинаковый паттерн трекинга request_id — отличаются только имена словарей (shutdown_requests vs plan_requests). Один паттерн — две области применения.
Почему не вынести в базовый класс Protocol? В s10 намеренно избегают абстракции. Причина: сейчас только два протокола, выгода от абстракции неочевидна; явное написание двух отдельных версий легче понять. Когда появятся четвёртый и пятый — тогда и рефакторинг (rule of three).