Skip to content

第十课:团队协议 — 结构化握手

"队友之间要有统一的沟通规矩" — 用 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]

追踪器:

python
shutdown_requests = {req_id: {"target": ..., "status": ...}}
plan_requests     = {req_id: {"from": ..., "plan": ..., "status": ...}}

核心抽象

这两个协议可以抽象为一个通用的 Request 数据模型:

python
@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,记录到追踪器,然后通过收件箱工具发送给队友:

python
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_idapprove 布尔值:

python
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:计划审批(同一模式)

队友想要执行高风险变更时,先提交计划:

python
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/rejectapprove/reject + feedback
ID 关联request_idrequest_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)
Tools912(+shutdown_req/resp +plan)
关机仅自然退出请求-响应握手
计划门控提交/审查与审批
关联每个请求一个 request_id
FSMpending -> approved/rejected

动手练习

sh
cd learn-claude-code
python agents/s10_team_protocols.py

练习 Prompt(英文对 LLM 效果更好,中文也可):

  1. 关机握手Spawn alice as a coder. Then request her shutdown.
  2. 监控状态List teammates to see alice's status after shutdown approval
  3. 拒绝计划Spawn bob with a risky refactoring task. Review and reject his plan.
  4. 批准计划Spawn charlie, have him submit a plan, then approve it.
  5. 查看全局:输入 /team 监控所有队友状态

小結

  • 协议 = request_id + FSM:任何需要双方确认的操作都可以用这个模式表达
  • 先握手,再动手:关机要等批准,计划要过审查
  • 一个模式通吃pending -> approved/rejected 的状态机可以复用于任何请求-响应场景。无论是关机、计划审批、资源申请还是数据同步,底层都是同一套机制
  • 接口数量微增,协作质量跃升:从 s09 到 s10 只增加了 3 个 tool,但团队从"野蛮生长"变成了"有序协作"。协议是廉价但高杠杆的投资
  • 下一课预告:有了协议还不够——队友需要 environmentinteractive 两个新工具来感知外部世界,这就是 [[s11 环境工具|第十一课:环境感知工具]] 的主题。

基于 Learn Claude Code 项目改编