【与我学 ClaudeCode】协作篇 之 Team Protocols :结构化请求 - 响应协作协议

作者:逆境不可逃

技术永无止境

希望我的内容可以帮助到你!!!!!


大家吼 ! 我是 逆境不可逃 今天给大家带来文章《【与我学 ClaudeCode】协作篇 之 Team Protocols :结构化请求 - 响应协作协议》.

Learn-Claude-Code 官方地址 : shareAI-lab/learn-claude-code: Bash is all you need - A nano claude code--like 「agent harness」, built from 0 to 1

上一篇文章:

【与我学 ClaudeCode】协作篇 之Agent Teams :持久化队友与文件邮箱-CSDN博客

Team Protocols 是迭代的第 10 个版本(s10),核心解决 多 Agent 团队协作中无结构化通信的混乱问题 。它在 s09 文件邮箱的基础上,构建了基于 request_id 关联的请求 - 响应协议框架,实现了优雅关机和计划审批两种关键协作流程,让队友之间的沟通有了统一的 "规矩"。


一、问题根源:为什么无结构化通信撑不起团队协作?

s09 中队友能干活、能通信,但缺少结构化协调,导致两个关键场景存在风险:

  1. 关机混乱 :直接杀线程会留下写了一半的文件和过期的 config.json,队友无法优雅收尾,数据完整性无法保证
  2. 计划失控:队友收到指令后立刻开干,高风险变更(如重构核心模块)没有审批流程,容易导致不可逆的错误

这两个场景本质上都是「请求 - 响应」模式:一方发起请求,另一方处理并返回结果。没有统一的协议框架,通信就像 "无信号的对讲机",容易出现请求丢失、响应错配、状态不一致等问题。


二、三大核心设计决策

Team Protocols 通过三个关键设计,构建了一个简单、可靠、可扩展的多 Agent 通信协议体系。

1. JSONL 收件箱文件而非共享内存

核心设计:每个队友都有自己的收件箱文件(团队目录中的 JSONL 文件)。发送消息意味着向接收者的收件箱文件追加一行 JSON;读取消息意味着读取收件箱文件并追踪上次读到的行。JSONL 天然是仅追加的,这意味着并发写入不会破坏彼此的数据(追加到不同的文件位置)。它在无需共享内存、互斥锁或 IPC 机制的情况下跨进程工作,也是崩溃安全的:如果写入者在追加中途崩溃,最坏情况是一行不完整的数据,读取者可以跳过。

替代方案的致命缺陷

共享内存(如 Python multiprocessing.Queue)速度更快,但无法在独立启动的进程中工作;消息代理(Redis、RabbitMQ)提供健壮的发布 / 订阅功能,但会增加基础设施依赖;Unix 域套接字可以工作,但难以调试(没有人类可读的消息日志)。JSONL 文件是最简单的提供持久化、跨进程通信和可调试性的方法。

2. 恰好五种消息类型覆盖所有协调模式

核心设计:消息系统支持五种类型,映射到基本协调模式:

  1. message:两个 Agent 间的点对点通信
  2. broadcast:全团队公告
  3. shutdown_request:优雅终止请求
  4. shutdown_response:终止确认响应
  5. plan_approval_response:组长审批或拒绝队友的计划

这五种类型覆盖了直接通信、广播、生命周期管理和审批流程,每种类型都有清晰明确的用途。

替代方案的致命缺陷

单个通用消息类型(带元数据字段)会更灵活,但难以强制协议正确性;更多类型(10+)会提供更细粒度的语义,但会增加模型的决策负担。五种类型是兼顾灵活性和清晰度的平衡点。

3. 每次 LLM 调用前检查收件箱

核心设计:队友在每次 Agent 循环迭代的顶部、调用 LLM API 之前检查收件箱文件。这确保了对传入消息的最大响应性:一个终止请求会在一个循环迭代内被看到(通常几秒钟),而非在当前任务完成后(可能数分钟)。收件箱检查成本很低(读取小文件,检查是否有新行),相比 LLM 调用(秒级延迟、数千 token)微不足道。这个位置还意味着传入消息可以影响下一次 LLM 调用 ------ 一条 "停止 X,转去做 Y" 的消息会立即生效。

替代方案的致命缺陷

在每次工具执行后检查收件箱响应性更好,但会给每个工具调用增加开销;单独的观察器线程可以持续监控收件箱,但会增加线程复杂度。每次 LLM 调用前检查是务实的平衡点:足够响应性以满足协调需求,又足够便宜不影响性能。


三、系统整体架构与工作原理

1. 核心协议框架:请求 - 响应模式

两种关键协议共享相同的 request_id 关联模式:

复制代码
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}  |
  • 发起方生成唯一 request_id,发送请求消息
  • 接收方处理请求,返回带相同 request_id 的响应消息
  • 发起方通过 request_id 关联请求和响应,更新状态机

2. 共享状态机(FSM)

两种协议使用相同的状态机:

复制代码
[pending] --approve--> [approved]
[pending] --reject---> [rejected]
  • pending:请求已发送,等待响应
  • approved:请求被同意,执行对应操作(如关机、执行计划)
  • rejected:请求被拒绝,放弃对应操作

3. 关键组件与实现细节

(1) 请求跟踪器:关联请求与响应
复制代码
# 全局请求跟踪器,线程安全
shutdown_requests = {}
plan_requests = {}
_tracker_lock = threading.Lock()
  • shutdown_requests:存储关机请求,键为 request_id,值包含目标队友和状态
  • plan_requests:存储计划审批请求,键为 request_id,值包含发起队友、计划内容和状态
(2) 优雅关机协议实现

组长发起关机请求

复制代码
def handle_shutdown_request(teammate: str) -> str:
    req_id = str(uuid.uuid4())[:8]
    with _tracker_lock:
        shutdown_requests[req_id] = {"target": teammate, "status": "pending"}
    # 发送 shutdown_request 消息给队友
    BUS.send(
        "lead", teammate, "Please shut down gracefully.",
        "shutdown_request", {"request_id": req_id},
    )
    return f"Shutdown request {req_id} sent to '{teammate}' (status: pending)"

队友处理关机请求并响应

复制代码
# 队友的 shutdown_response 工具处理
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"
    # 发送 shutdown_response 消息给组长
    BUS.send(
        sender, "lead", args.get("reason", ""),
        "shutdown_response", {"request_id": req_id, "approve": approve},
    )
    return f"Shutdown {'approved' if approve else 'rejected'}"

队友根据响应决定是否退出

复制代码
def _teammate_loop(self, name: str, role: str, prompt: str):
    # ...
    should_exit = False
    for _ in range(50):
        # ... 处理收件箱和工具调用 ...
        if block.name == "shutdown_response" and block.input.get("approve"):
            should_exit = True
    # 循环结束后更新状态
    member = self._find_member(name)
    if member:
        member["status"] = "shutdown" if should_exit else "idle"
        self._save_config()
(3) 计划审批协议实现

队友提交计划审批请求

复制代码
# 队友的 plan_approval 工具处理
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"}
    # 发送 plan_approval_response 消息给组长
    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."

组长审批计划

复制代码
def handle_plan_review(request_id: str, approve: bool, feedback: str = "") -> 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"
    # 发送 plan_approval_response 消息给队友
    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']}'"
(4) 队友工具集扩展
复制代码
def _teammate_tools(self) -> list:
    return [
        # 基础工具(bash、read_file等)
        {"name": "bash", ...},
        {"name": "read_file", ...},
        {"name": "write_file", ...},
        {"name": "edit_file", ...},
        # 通信工具
        {"name": "send_message", ...},
        {"name": "read_inbox", ...},
        # 新增协议工具
        {"name": "shutdown_response", 
         "description": "Respond to a shutdown request. Approve to shut down, reject to keep working.",
         "input_schema": {"type": "object", "properties": {"request_id": {"type": "string"}, "approve": {"type": "boolean"}, "reason": {"type": "string"}}, "required": ["request_id", "approve"]}},
        {"name": "plan_approval", 
         "description": "Submit a plan for lead approval. Provide plan text.",
         "input_schema": {"type": "object", "properties": {"plan": {"type": "string"}}, "required": ["plan"]}},
    ]
(5) 执行流程

四、与 Agent Teams(s09)的关键变更对比

组件 之前(s09 Agent Teams) 之后(s10 Team Protocols)
工具集 9 个工具 12 个工具(新增 shutdown_request/responseplan_approval
关机机制 仅自然退出或强制杀线程 请求 - 响应握手,优雅关机
计划审批 提交 / 审查与审批流程
消息关联 无(纯文本消息) 每个请求一个 request_id,关联请求与响应
状态机 pending -> approved/rejected 共享 FSM
通信模式 纯文本点对点 / 广播 结构化请求 - 响应协议

五、核心优势与创新点

  1. 结构化通信,避免混乱 :基于 request_id 的关联模式,确保请求和响应一一对应,解决了无结构化通信的错配问题
  2. 优雅关机,数据安全:关机请求需要队友确认,队友可以在退出前完成收尾工作(如关闭文件、保存状态),避免数据损坏
  3. 计划审批,风险可控:高风险变更需要组长审批,防止队友擅自执行不可逆操作,提升团队协作的安全性
  4. 统一协议框架,可扩展:同一个请求 - 响应模式可以套用到更多协作场景(如资源申请、任务移交),为后续扩展打下基础
  5. 低侵入式实现,兼容旧系统:基于 JSONL 文件邮箱实现,无需修改 s09 的通信基础,仅新增消息类型和工具即可实现协议

六、运行示例

场景 1:优雅关机流程

  1. 组长判断任务完成,调用 shutdown_request(teammate="coder"),生成 request_id="abc123"
  2. 队友 coder 收到 shutdown_request 消息,决定是否批准关机(如任务已完成则批准,如正在处理关键文件则拒绝)
  3. 队友调用 shutdown_response(request_id="abc123", approve=True),发送响应消息
  4. 组长收到响应,更新 shutdown_requests["abc123"] 状态为 approved
  5. 队友在循环结束后,将状态更新为 shutdown,线程安全退出

场景 2:计划审批流程

  1. 队友 coder 需要重构认证模块,调用 plan_approval(plan="重构认证模块,步骤1: 修改auth.py,步骤2: 更新测试用例"),生成 request_id="xyz789"
  2. 组长收到 plan_approval_response 消息,审查计划是否合理、是否符合项目规范
  3. 组长调用 plan_approval(request_id="xyz789", approve=True, feedback="计划合理,按步骤执行即可"),发送审批响应
  4. 队友收到批准消息,开始执行重构计划

七、可扩展方向

  • 更多协议类型:扩展协议框架,实现任务移交、资源申请、错误报告等请求 - 响应流程
  • 协议超时与重试:为请求添加超时机制,未收到响应时自动重试或标记为失败
  • 协议日志与审计:将所有协议消息单独归档,便于事后审计和问题排查
  • 协议权限控制:为不同角色的 Agent 分配不同的协议权限(如普通队友不能发起关机请求)
  • 协议自动生成:基于配置文件自动生成协议工具和状态机,降低新增协议的开发成本
相关推荐
a11177613 小时前
【无标题】
前端·开源·html
晓得迷路了13 小时前
栗子前端技术周刊第 130 期 - Angular 22 RC、Rolldown 1.0.1、pnpm 11.2...
前端·javascript·react.js
审判长烧鸡13 小时前
【AI问答/前端】前端瞒天过海局(三)
前端·vue·html5·js
桔筐13 小时前
【无标题】
前端·vue.js
星栈独行13 小时前
别让 API 跳去登录页:我在 Axum 里做了认证失败双通道
前端·后端·rust·开源·github·个人开发
এ慕ོ冬℘゜13 小时前
原生 JS 手写日期选择器|完整可复用日历组件实战
前端·javascript·css
Maimai1080813 小时前
用 TanStack Table、React Query 和 shadcn/ui 搭一个可维护的数据表格架构
前端·javascript·react.js·ui·架构·前端框架·reactjs
yqcoder13 小时前
Web 世界的基石:深入解析 HTTP/1.1 的六大核心特点
前端·网络协议·http
转型AI的宏达13 小时前
解除autoclaw白名单审批机制
java·服务器·前端