第十课:团队协议 — 结构化握手
"队友之间要有统一的沟通规矩" — 用 request-response 模式驱动所有协商。
Harness 层: 协议 (Protocol) — 模型之间的结构化握手。
[[s09 队友协作|上一课]] 中队友之间已经能干活能通信,但缺少结构化协调。本课引入 请求-响应协议,为团队协作加上正式的握手规则。
缘起:为什么需要协议?
s09 的队友系统有两个明显的缺口:
关机没有握手
想象一个场景:领导决定结束任务,直接杀掉队友进程。这时队友可能正在写文件、更新缓存、或执行一个重要的状态变更。突然死亡留下的是:
- 写了一半的文件 —— 数据损坏
- 过期的
config.json—— 不一致的状态 - 未释放的资源 —— 内存泄漏、文件句柄泄露
解决方案:领导先发关机请求,队友收到后完成收尾工作,然后批准请求。如果队友正在执行关键任务,也可以拒绝——这就是握手。
计划没有审批
另一个场景:领导说"重构认证模块",队友立刻开干。如果重构涉及面广、风险高,应该先过审:
- 队友提交计划(包含 scope、步骤、风险)
- 领导审查,批准或退回
- 批准后才执行
两者的结构完全一样:一方发请求(带唯一 ID),另一方引用同一 ID 响应。
核心模式:Request-Response 协议
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} |共享的状态机 (FSM):
[pending] ──approve──> [approved]
[pending] ──reject───> [rejected]追踪器:
shutdown_requests = {req_id: {"target": ..., "status": ...}}
plan_requests = {req_id: {"from": ..., "plan": ..., "status": ...}}核心抽象
这两个协议可以抽象为一个通用的 Request 数据模型:
@dataclass
class ProtocolRequest:
req_id: str # 唯一标识
sender: str # 谁发的
target: str # 发给谁
req_type: str # shutdown / plan_approval
payload: dict # 具体内容
status: str # pending | approved | rejected
created_at: float # 时间戳,便于超时管理有了这个抽象,任何需要双方确认的操作都可以复用同一套基础设施:生成 ID、发送请求、等待响应、更新状态。
工作原理
Step 1:领导发起关机请求
领导先生成一个唯一 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)"这里的关键细节:
uuid.uuid4()[:8]生成短 ID,便于日志查看和手动输入- 状态初始化为
pending,表示请求已发出但未处理 - 消息类型 (
shutdown_request) 让接收方能正确路由
Step 2:队友响应批准或拒绝
队友收到请求后,决定是否批准。工具函数接收 request_id 和 approve 布尔值:
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})注意:响应时必须引用同一个 request_id。这是协议的核心约束——发送和响应通过 ID 关联,而不是靠顺序或隐式上下文。
Step 3:计划审批(同一模式)
队友想要执行高风险变更时,先提交计划:
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})流程完全对称:
| 角色 | 关机协议 | 计划审批协议 |
|---|---|---|
| 发起者 | 领导 | 队友 |
| 请求内容 | 关闭请求 | 变更计划 |
| 审批者 | 队友 | 领导 |
| 响应 | approve/reject | approve/reject + feedback |
| ID 关联 | request_id | request_id |
一个 FSM,两种用途。同样的 pending -> approved | rejected 状态机可以套用到任何请求-响应协议上。
🔍 Deep Dive:协议设计的通用性
这个模式不只是关机和计划审批专用——它是 Agent 间通信的最小可行协议。为什么说它通用?
三个关键设计决策
| 决策 | 为什么 |
|---|---|
request_id 作为关联键 | 允许异步、乱序处理;日志可追溯;支持重试 |
pending -> approved/rejected 的 FSM | 状态可枚举、可监控、可恢复、可审计 |
| 同一模式套两种协议 | 减少系统复杂度;队友只用学一种通信范式 |
扩展方向
超时自动拒绝:请求带上 timeout 字段,队友在时间内未响应则自动进入 rejected 状态。防止队友失联导致系统阻塞。
重试语义:领导可以重发请求(用新的 request_id),或对已拒绝的请求进行"上诉"。
回调链:批准后自动执行后续动作。比如计划审批通过后,自动触发执行。
多级审批:某些高风险计划可能需要多个领导同时批准,引入 approvers 列表和计数规则。
对比无协议方案的差异
| 维度 | 无协议 (s09) | 有协议 (s10) |
|---|---|---|
| 可靠性 | 靠运气 | 靠机制 |
| 可追溯性 | 无 | 每个请求有完整日志 |
| 可恢复性 | 无法恢复 | 可以重试/回滚 |
| 复杂度 | 低 | 中(增加 3 个 tool) |
| 协作质量 | 松耦合混乱 | 结构化有序 |
相对 s09 的变更
| 组件 | 之前 (s09) | 之后 (s10) |
|---|---|---|
| Tools | 9 | 12(+shutdown_req/resp +plan) |
| 关机 | 仅自然退出 | 请求-响应握手 |
| 计划门控 | 无 | 提交/审查与审批 |
| 关联 | 无 | 每个请求一个 request_id |
| FSM | 无 | pending -> approved/rejected |
动手练习
cd learn-claude-code
python agents/s10_team_protocols.py练习 Prompt(英文对 LLM 效果更好,中文也可):
- 关机握手:
Spawn alice as a coder. Then request her shutdown. - 监控状态:
List teammates to see alice's status after shutdown approval - 拒绝计划:
Spawn bob with a risky refactoring task. Review and reject his plan. - 批准计划:
Spawn charlie, have him submit a plan, then approve it. - 查看全局:输入
/team监控所有队友状态
小結
- 协议 = request_id + FSM:任何需要双方确认的操作都可以用这个模式表达
- 先握手,再动手:关机要等批准,计划要过审查
- 一个模式通吃:
pending -> approved/rejected的状态机可以复用于任何请求-响应场景。无论是关机、计划审批、资源申请还是数据同步,底层都是同一套机制 - 接口数量微增,协作质量跃升:从 s09 到 s10 只增加了 3 个 tool,但团队从"野蛮生长"变成了"有序协作"。协议是廉价但高杠杆的投资
- 下一课预告:有了协议还不够——队友需要
environment和interactive两个新工具来感知外部世界,这就是 [[s11 环境工具|第十一课:环境感知工具]] 的主题。