O handshake entre dois agents
Agents também precisam "assinar contratos". O request_id é o número do contrato.
Por que precisamos de protocolos?
No s09, o send_message podia transmitir qualquer conteúdo. Mas quando dois agents precisam chegar a um consenso sobre algo (por exemplo, "posso encerrar agora?"), só enviar uma string não basta — você precisa de:
- Identidade clara no request (request_id), para que a resposta possa ser correlacionada.
- Máquina de estados: pending → approved | rejected, com consequências claras para cada transição.
- Campos consistentes: ambos os lados sabem o que
approve: truesignifica.
É por isso que existem shutdown_request / shutdown_response / plan_approval / plan_approval_response.
Fluxo completo do protocolo de shutdown
O lead quer que alice encerre:
lead: # envia shutdown_request, o servidor registra request_id req_id = uuid4()[:8] shutdown_requests[req_id] = {"target": "alice", "status": "pending"} send("alice", "shutdown_request", extra={"request_id": req_id}) alice: # próximo loop lê a inbox, vê shutdown_request # decide: termina o que está fazendo e aprova tool_use("shutdown_response", request_id=req_id, approve=True) lead: # recebe shutdown_response, atualiza tracker para approved shutdown_requests[req_id]["status"] = "approved" # thread de alice detecta o shutdown aceito, define status=shutdown e sai do loop
Visualização do FSM de shutdown
Acompanhe a máquina de estados passo a passo. Alice também pode rejeitar — dizendo "estou em trabalho crítico, não posso parar agora".
Plan Approval · o mesmo padrão, domínio diferente
Antes de uma ação de grande impacto, o teammate submete um plano para aprovação do lead:
alice: tool_use("plan_approval", plan="Vou reescrever o módulo auth inteiro com JWT") # alice fica idle aguardando o lead lead: # vê o pedido de plan_approval_response de alice tool_use("plan_approval", request_id="...", approve=False, feedback="Não mexa no auth ainda, vamos fazer um refactor geral no próximo mês")
Se você olhar o código do s10, vai perceber: os dois protocolos usam exatamente o mesmo padrão de rastreamento com request_id — apenas com nomes de dicionários diferentes (shutdown_requests vs plan_requests). É "um padrão, dois domínios".
Por que não abstrair uma classe base Protocol? O s10 deliberadamente não abstrai. Motivo: com apenas dois protocolos, o ganho da abstração não compensa; cada um pode ser entendido de forma independente. Quando houver um quarto ou quinto protocolo, aí sim vale refatorar (regra dos três).