learn claude code S10 团队协议详解笔记
S10 团队协议详解笔记
基于
s10_team_protocols.py源码逐行分析,配合s10-team-protocols.md设计思路。
一、问题:队友之间需要结构化的握手
s09 的队友可以发消息了,但所有消息都是 msg_type: "message"——非结构化的自由文本。这在实际协作中不够。
想象这个场景:Lead 想让 Alice 停下来(她的任务已经被 Bob 完成了),Lead 发了一条 “请停止工作”。Alice 的 LLM 怎么理解这条消息?
- 它可能当成闲聊忽略掉
- 它可能理解成"检查一下工作质量"
- 它可能直接继续干活
自由文本不适合传递指令。指令需要结构、确认、追踪。
s10 引入了两个结构化握手协议:Shutdown(关闭)和 Plan Approval(计划审批)。两者共享同一个 request_id 关联模式。
二、解决方案:请求-响应 + request_id 关联
两个协议都遵循同样的模式:
发起方 接收方
+---------------------+ +---------------------+
| 发送 request | | |
| {request_id: abc} | -------> | 收到 request |
+---------------------+ | 决定: approve? |
+---------------------+
|
+---------------------+ +-------v-------------+
| 收到 response | <------- | 发送 response |
| 匹配 request_id | | {request_id: abc} |
| 状态: approved | | {approve: true} |
+---------------------+ +---------------------+
request_id 是桥接请求和响应的关键:发起方保存 {request_id: status},接收方在响应中带回同一个 request_id,发起方据此更新状态。
三、和 s09 相比,多了什么?
| 组件 | s09 | s10 |
|---|---|---|
| 消息类型 | message, broadcast |
+ shutdown_request, shutdown_response, plan_approval_response |
| 握手协议 | 无 | Shutdown + Plan Approval |
| 请求追踪 | 无 | shutdown_requests / plan_requests 字典 |
| 队友工具 | 6 个 | 8 个(+ shutdown_response, plan_approval) |
| Lead 工具 | 9 个 | 12 个(+ shutdown_request, shutdown_response[查询], plan_approval) |
四、协议一:Shutdown — 优雅关闭
4.1 状态机
pending → approved | rejected
Lead 发起关闭请求,teammate 可以同意或拒绝。
4.2 Lead 侧:发起请求
def handle_shutdown_request(teammate: str) -> str:
req_id = str(uuid.uuid4())[:8] # 生成唯一请求 ID
with _tracker_lock:
shutdown_requests[req_id] = {"target": teammate, "status": "pending"}
BUS.send(
"lead", teammate,
"Please shut down gracefully.",
"shutdown_request", # 消息类型
{"request_id": req_id}, # extra 字段
)
return f"Shutdown request {req_id} sent to '{teammate}'"
发送的消息结构:
{
"type": "shutdown_request",
"from": "lead",
"content": "Please shut down gracefully.",
"request_id": "a1b2c3d4"
}
4.3 Teammate 侧:响应请求
Teammate 在自己的 agent_loop 中读到 inbox,看到 shutdown_request。它调用 shutdown_response 工具:
# TeammateManager._exec 中的处理
if tool_name == "shutdown_response":
req_id = args["request_id"]
approve = args["approve"]
with _tracker_lock:
if req_id in shutdown_requests:
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})
return f"Shutdown {'approved' if approve else 'rejected'}"
如果 approve: true,队友循环中的 should_exit 标志被设为 True,循环退出,状态切为 shutdown。
4.4 Lead 侧:查询状态
# Lead 工具:
"shutdown_response": lambda **kw: _check_shutdown_status(kw.get("request_id", "")),
Lead 可以传 request_id 查询请求状态,看 teammate 是否同意了关闭。
注意语义上的微妙:Lead 的 shutdown_response 和 teammate 的 shutdown_response 是不同的工具,虽然同名。Lead 侧是"查询请求状态",teammate 侧是"同意/拒绝关闭请求"。在 dispatch map 中它们映射到不同的 handler。
五、协议二:Plan Approval — 执行前审批
5.1 动机
Teammate 在做一个高风险操作前(如"删除 production 数据库"),先提交计划给 Lead 审批。只有获批后才执行。这是 “human-in-the-loop” 或 “lead-in-the-loop” 的简化实现。
5.2 Teammate 侧:提交计划
if tool_name == "plan_approval":
plan_text = args.get("plan", "")
req_id = str(uuid.uuid4())[:8]
with _tracker_lock:
plan_requests[req_id] = {"from": sender, "plan": plan_text, "status": "pending"}
BUS.send(sender, "lead", plan_text, "plan_approval_response",
{"request_id": req_id, "plan": plan_text})
return f"Plan submitted (request_id={req_id}). Waiting for lead approval."
Teammate 调用 plan_approval(plan="删除 production 数据库的所有记录") → 计划发给 lead,状态 pending。此时 teammate 暂停执行(等待响应)。
5.3 Lead 侧:审批计划
Lead 在 inbox 中看到计划,调用 plan_approval 工具:
def handle_plan_review(request_id: str, approve: bool, feedback: str = ""):
with _tracker_lock:
req = plan_requests.get(request_id)
if not req:
return f"Error: Unknown plan request_id '{request_id}'"
with _tracker_lock:
req["status"] = "approved" if approve else "rejected"
BUS.send("lead", req["from"], feedback, "plan_approval_response",
{"request_id": request_id, "approve": approve, "feedback": feedback})
return f"Plan {req['status']} for '{req['from']}'"
如果 approve: false,Lead 可以附带 feedback: "分批删除,每次不超过 1000 条"。Teammate 收到反馈后修改计划,重新提交。
六、Teammate 循环中的协议集成
def _teammate_loop(self, name: str, role: str, prompt: str):
sys_prompt = (
f"You are '{name}', role: {role}. "
f"Submit plans via plan_approval before major work. "
f"Respond to shutdown_request with shutdown_response."
)
should_exit = False
for _ in range(50):
inbox = BUS.read_inbox(name)
for msg in inbox:
messages.append(...)
if should_exit: # shutdown_response 设置的
break
# ...agent loop...
# 检查是否发了 shutdown_response
for block in response.content:
if block.name == "shutdown_response" and block.input.get("approve"):
should_exit = True
# 结束时更新状态
member["status"] = "shutdown" if should_exit else "idle"
七、设计洞察
7.1 request_id 是分布式系统的基石
两个协议共用一个 request_id 关联模式——这个模式在分布式系统中无处不在(HTTP 的 X-Request-Id、消息队列的 correlation_id、OpenTelemetry 的 trace_id)。s10 在 30 行代码里展示了这个模式的核心:生成唯一 ID → 随请求发送 → 在响应中带回 → 匹配并更新状态。
7.2 消息类型的演进
s09: message, broadcast ← 非结构化
s10: + shutdown_request/response, plan_approval_response ← 结构化握手
消息类型从"随便说"到"有格式的契约"。这不是随意的添加——每种新消息类型代表一种新的人机/机机交互模式。shutdown_request 是"终止",plan_approval 是"审批"。未来可以扩展更多(code_review_request、deploy_approval…),模式不变。
7.3 协议是 Harness 的职责
shutdown 和 plan approval 都不是 LLM 发明的——是 Harness 层定义的结构。模型只是"使用"这些协议(调用相应的工具),但协议的存在、状态追踪、超时处理、响应匹配——全是 Harness 代码的责任。这回到了这个系列的核心哲学:Harness 提供结构和约束,模型提供推理和决策。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)