这一节只讲相对 S15 新增的内容:
团队消息不只是普通聊天,还需要 request_id、类型和状态机来保证请求与响应能对上。
ProtocolState:协议请求状态。pending_requests:等待响应的请求表。new_request_id():生成请求 ID。match_response():把响应关联回原始请求。consume_lead_inbox():统一消费 Lead 收件箱并路由协议消息。submit_plan:队友提交计划。request_shutdown:Lead 请求队友关闭。request_plan:Lead 要求队友提交计划。review_plan:Lead 审批队友计划。S15 的消息只有普通字段:
{
"from": "lead",
"to": "worker",
"content": "你好",
"type": "message",
"ts": 1720000000.0
}
S16 增加了 metadata:
{
"from": "worker",
"to": "lead",
"content": "这是我的计划",
"type": "plan_approval_request",
"ts": 1720000000.0,
"metadata": {
"request_id": "req_123456"
}
}
request_id 是协议的关键。
ProtocolStateProtocolState 是:
@dataclass
class ProtocolState:
request_id: str
type: str
sender: str
target: str
status: str
payload: str
created_at: float
一条请求状态大概是:
{
"request_id": "req_123456",
"type": "plan_approval",
"sender": "worker",
"target": "lead",
"status": "pending",
"payload": "计划内容",
"created_at": 1720000000.0
}
pending_requestspending_requests 是:
pending_requests: dict[str, ProtocolState]
结构:
{
"req_123456": ProtocolState(...)
}
它用来记住:
哪个请求还在等待响应
这个请求是谁发的
目标是谁
现在是 pending / approved / rejected
match_response()作用:收到响应后,根据 request_id 找回原始请求。
流程:
从 pending_requests 找 request_id
检查响应类型是否匹配
检查请求是否仍是 pending
更新状态为 approved 或 rejected
如果没有 request_id,Lead 就不知道这个响应对应哪一个请求。
队友提交计划:
submit_plan(plan)
内部会:
生成 request_id
写入 pending_requests
发送 plan_approval_request 给 lead
Lead 审批:
review_plan(request_id, approve=True, feedback="")
内部会:
更新 pending_requests[request_id].status
发送 plan_approval_response 给队友
Lead 发起:
request_shutdown(teammate)
队友收到:
shutdown_request
队友回复:
shutdown_response
Lead 通过 request_id 把响应匹配回原请求。
多 Agent 协作不能只靠自然语言消息。
需要协议层:
message type 区分消息种类
request_id 关联请求和响应
pending_requests 记录状态
match_response 更新状态机
这就是从“聊天协作”走向“可控协作”的关键。