--- name: multi-agent-design description: 设计或评审多 Agent 系统、判断该用单 Agent 还是多 Agent 时使用——选择对等/管理者/去中心化协作拓扑、决定上下文是否共享、设计 Agent 间通信与共享文件系统、诊断多 Agent 失败模式(并发冲突、错误级联、同质趋同、互相扯皮、循环失控)。覆盖协作架构选择依据、多 Agent 优于单 Agent 的新信息判据、控制平面四原语与虚拟文件系统四类区域的设计检查表。 --- # 多 Agent 协作设计 ## 何时使用 - 要搭建多 Agent 系统,或评审一个已有架构("该用几个 Agent?谁指挥谁?") - 纠结"这个任务拆成多个 Agent 是否真的更好",需要可判定的依据 - 决定 Agent 之间是共享上下文、还是各自独立上下文 - 设计 Agent 间通信机制(工具参数 / 共享文件系统 / 消息总线)与文件系统布局 - 决定角色切换应替换 system prompt,还是加载 Skill - 多 Agent 系统出问题:文件互相覆盖、结论越传越歪、多个 Agent 不约而同做同一件事、互相扯皮、子 Agent 数量爆炸 ## 核心原则 - **新信息判据(唯一实质判据)。** 多 Agent 优于单 Agent,当且仅当协作过程引入了单个 Agent 在生成时无法获得的新信息。同一模型重新读自己的输出、多个 Agent 辩论同一段文本,都不引入新信息——等计算量下单 Agent 持平甚至更好;而用测试执行结果、渲染截图、外部工具输出来审查,则显著提升。学术研究说"多 Agent 无效"与工程实践"多 Agent 更好"并不矛盾:前者比较的是"看着同一段上下文讨论",后者包含外部反馈环路。 - **两个维度先定,再谈实现。** 维度一:上下文是否共享(继承式 vs 进程隔离式);维度二:协作拓扑(对等 / 管理者 / 去中心化)。二者共同决定架构。 - **成本必须被收益覆盖。** 并行探索与反复迭代要烧数倍乃至一个数量级的 token。收益不够大时,一个调校得当的单 Agent 更划算。 - **步骤预算不是越多越好。** 单纯给 Agent 更多步骤/工具调用次数不保证性能提升——Agent 缺乏预算意识会很快"饱和"。Manager 应按子任务复杂度动态分配预算,并引导子 Agent"先规划、再实现、再测试、再改进"。 - **最强的模型给 Manager。** Plan-and-Act 的实证结论:弱规划者是系统最关键的瓶颈;规划错了,后续所有执行都建立在错误前提上。不要把资源平均分给所有 Agent。 - **Agent 的故障是拜占庭式的。** 它很少径直停止,而是继续给出看似可信的错误结论,且错误不会声明自己是错误。因此交叉验证与多数表决是必需手段,而非可选优化。 - **上下文隔离优先。** Manager 上下文中只放任务描述、计划、调用记录与文件索引;完整产物写入文件系统,Agent 间传递轻量路径字符串而非把内容载入上下文。 - **handoff 不暴露私有轨迹。** 对等移交只应传递明确的任务包和产物引用。 ## 实践模式 ### 1. 拓扑选择决策树 | 任务特征 | 选择 | |---|---| | 2-3 个角色,需要互相反馈、多轮迭代提质 | 对等协作(起草者/评论者、提议者/审核者) | | 子任务多、需要动态调度、子任务间有复杂依赖 | 管理者模式(Manager 规划 + 子 Agent 执行) | | 需职责对等的角色自主决定与谁沟通,或管理者不能成为单点故障 | 去中心化模式(handoff / 消息池订阅) | | 开放搜索空间,需要广覆盖与多样化发现路径 | 多 Agent 并行(用更高 token 预算换覆盖) | 对等协作实现复杂度最低:定义好两个 Agent 的角色、通信机制和迭代终止条件即可跑起来。 ### 2. 共享上下文 vs 不共享上下文 - **共享上下文**:每阶段是独立 Agent(自己的 system prompt 与工具集),但继承前序完整轨迹。优势是信息不丢失;挑战是上下文快速膨胀,当前 Agent 容易被历史干扰。 - **不共享上下文**:每个 Agent 有独立上下文与轨迹,彼此看不到对方的"思考过程"。模块化、隔离性、可扩展性更好,可真正并发;代价是信息同步与调试困难,接口规范与数据格式变得至关重要。 - **通信机制就三种,且都落在经典 IPC 范式内**:工具调用参数(同步消息传递)、共享文件系统(共享内存)、消息总线(异步消息传递)。Agent 数量少且拓扑固定用点对点;数量多且需异步并行改消息总线——点对点连接数随 Agent 数平方增长且要求双方同时在线。 ### 3. 角色切换:替换 system prompt 还是加载 Skill? | | `transfer_to_agent` / 替换 system prompt | Skill | |---|---|---| | 工具可见性 | 只暴露当前角色工具 | 通常固定暴露全集 | | 前缀缓存 | 每次切换改变请求前缀,缓存从变化点起失效 | 静态前缀不变,Skill 内容追加到末尾轨迹,前缀可复用 | | 约束能力 | 强:越界工具在 schema 层不可见 | 弱:Skill 是行为指令,硬权限仍需 Harness 门 | 判据:角色差异主要来自**知识、流程、写作风格** → 用 Skill;涉及**权限、工具隔离、合规边界、需运行时强制禁止某类动作** → 用独立 Agent 或 `transfer_to_agent`,并在 Harness 层用代码限制。 ### 4. 虚拟文件系统:四类区域(布局设计的检查表) | 区域 | 可见性 | 生命周期 | 读写 | 并发控制 | |---|---|---|---|---| | Agent 专属工作区(Scratchpad) | 仅该 Agent | 随实例销毁 | 读写 | 不需要 | | 多 Agent 共享空间(Shared Workspace) | 所有协作 Agent + 用户 | 随任务持续,需持久化 | 读写 | 需要(乐观锁 / worktree) | | 外部挂载资源 | 视外部授权而定 | 由外部源决定 | 多为只读,写需谨慎 | 由外部源负责 | | 系统内置资源(Skills 等) | 所有 Agent | 跨会话稳定 | 只读 | 不需要 | 要点:隔离 scratchpad 既避免临时文件互相覆盖,也保持主上下文精简(子 Agent 只把最终产物提交到共享空间);外部挂载需显式处理权限约束、弱一致性与"按需只读";相当一部分并发冲突与信息泄露源于把本应隔离的区域混置。 ### 5. 控制平面四原语 - **消息传递**:无论点对点还是经总线,消息都带结构化信封(发送者 ID、目标、消息类型 `task_assigned`/`status_update`/`result`/`terminate`、JSON 负载)。统一信封使链路可追溯——这是多 Agent 调试的关键。 - **状态查询**:不要用拉取式 `get_status`。更自然的是消息传递(问一句"进展如何")或共享文件系统(约定 `progress.md`,子 Agent 每完成一项更新一次)。用 `progress.md` 最后修改时间超过 N 分钟无变化来判定卡住并触发超时兜底。轨迹持久化(JSONL)适合读全貌,但不宜作为主要传递方式——数万 token 还得自己提炼。 - **执行终止**:优雅终止(`terminate` 信号,子 Agent 在安全点清理资源后 ack)为首选,强制终止为兜底。终止沿创建关系向下级联,杜绝孤儿 Agent;确需长期后台 Agent 则从新的生命周期树起步。 - **资源与调度**:启动时设定步数/token 预算,超限即止;困难任务给强模型,机械任务给低成本模型;设并发上限避免耗尽 API 配额;高优先级任务到来时可抢占。 ### 6. 管理者模式的两种协调形态 - **顺序**:Manager 依次调用专门 Agent,线性控制流,适合子任务有清晰先后依赖。 - **并行**:多个 Agent 同时工作,需消息总线做实时监控;Manager 在 Agent 成功/失败时做全局决策。 - **结算点定义**:并行管理器要定义"第一个**已验证**成功"而非"第一个声称成功"——结果到达后先跑隐藏校验,通过后再用幂等的锁/事务认领胜者并广播取消其余 worker;两个几乎同时到达的成功事件不能触发两次汇总。 - 进阶做法:Manager 先把 Agent 工作流写成代码交给确定性运行时执行,自己不必每步都待在循环里。 ### 7. 去中心化 handoff 最小协议 ```python handoff = {task_id, sender, recipient, goal, constraints, accepted_facts, artifact_refs, remaining_budget, visited_agents} ``` 接收方读任务包和引用、按需取证;预算、访问链与环检测由运行时保留,任何 Agent 不能自行删除。recipient 已在 `visited_agents` 中则拒绝(防 A→B→A 空转),预算耗尽则停止并上报。 ### 8. 对等协作如何获得真正的多样性 "多个实例"不等于"多种思路"。模型、上下文、脚手架高度相似时,不同 Agent 会做出相同选择。要获得多样性需主动区分**模型、上下文、工具、可见证据或职责**,并让各 Agent 先独立判断、再汇总结果。 ## 常见陷阱 - **共享文件系统并发冲突**:简单冲突是同一文件后写覆盖前写(用乐观锁:读时记录版本号,写入时校验,失败则重读重做);跨文件语义冲突更隐蔽——Agent A 重编图片编号、Agent B 引用旧编号,文件层毫无冲突但逻辑全错。并发改同一代码库时主流做法是工作副本隔离(每人独立 Git 分支/worktree),把冲突推迟到合并点。 - **错误的级联放大**:Agent 间传递的是语义,每转述一次都是有损重新编码。打断手段是交叉验证——某个 Agent 以独立视角只看原始证据与最终结论是否一致,不看前序思考过程。 - **同质趋同**:共因失效。同一模型、相似上下文生成的多个审核意见不能自动视为相互独立证据。需引入模型/上下文/数据来源差异,并用命名空间、资源配额和速率限制防止相同决策同时冲击共享资源。 - **互相扯皮**:目标互斥时 Agent 会把对方操作理解为蓄意阻挠。运行时必须预先定义目标优先级、资源所有权和权限边界;冲突无法按可验证规则解决时暂停执行、交人工裁决。 - **循环失控**:与"过早终止"相反的一极——失控 Agent 生成数千个子 Agent 浪费大量 token。对自主性强的 Agent 用独立 API key。 - **理解债与认知投降**:Agent 交付越快,工程师对系统实际实现的理解落后越远;习惯了代劳就放弃独立审查。可以外包思考,不能外包理解。 ## 配套代码 - `chapter10/multi-role-transfer/` — 同一共享轨迹下"替换 system prompt"与"加载 Skill"两种角色切换的受控对比 - `chapter10/staged-system-prompt/` — 分阶段切换 system prompt + 工具集的归档实验(需求→实现→评审回环) - `chapter10/book-translation/` — 管理者模式四 Agent(Glossary/Translation/Proofreading/Manager),验证 Manager 上下文不随书厚增长 - `chapter10/parallel-web-research/` — Manager 动态启动 N 个同构 worker、消息总线、第一个已验证命中的级联终止与资源清理 - `chapter10/autonomous-phone-registration/` — 电话 + 电脑双 Agent 点对点协作,模型自主决定是否派生 Phone Agent - `chapter10/talkact-reproduction/` — 固定拓扑快慢双 Agent 与单模型基线的对照 - `chapter10/voice-werewolf/` — 多 Agent 语音狼人杀:私有/公共记忆隔离与代码驱动的只读 Judge - `chapter10/generative-agents/` — 25 角色斯坦福 AI 小镇复现,反思机制与信息扩散的对照实验 ## 深度阅读 - `book/chapter10.md`「多 Agent 协作的分类框架」 - `book/chapter10.md`「多 Agent 何时真正优于单 Agent」 - `book/chapter10.md`「共享上下文的多 Agent 协作」 - `book/chapter10.md`「不共享上下文的多 Agent 协作」 - `book/chapter10.md`「多 Agent 协作的失败模式」