Appearance
多 Agent 协调
单 Agent 的问题是串行。Plan → Act → Observe 一次只走一步,如果任务可以拆开来同时推进,单 Agent 就是瓶颈。
多 Agent 系统的思路很直接:让多个 Agent 分工,把可以并行的部分真的并行起来。
本章目标
- 理解多 Agent 系统比单 Agent 多了什么,代价是什么
- 掌握 Coordinator + Worker 这一核心架构模式
- 知道任务什么时候适合并行、什么时候必须串行
- 能说出多 Agent 系统最容易失控的地方
从单 Agent 到多 Agent
假设你要重构一个大型代码库:
- 先要读懂现有代码结构(探索)
- 再制定重构方案(规划)
- 然后在多个文件上做修改(实现)
- 最后验证改动是否正确(验证)
这四个阶段在单 Agent 下只能依次走,总耗时是所有步骤之和。但「探索不同模块」这件事完全可以并行——三个 Agent 同时读三个模块,探索速度是原来的三倍。
这就是多 Agent 的核心价值:把可以并行的工作真的并行起来。
Coordinator + Worker 架构
最主流的多 Agent 模式是两层结构:
用户 → Coordinator Agent
↓ ↓ ↓
Worker A Worker B Worker C
↓ ↓ ↓
结果 A 结果 B 结果 C
↓
Coordinator 汇总 → 用户Coordinator(协调者):
- 接收用户的完整目标
- 拆分任务,判断哪些子任务可以并行
- 派发给 Worker,监听结果
- 汇总结果,决策下一步
- 和用户沟通进展
Worker(执行者):
- 接收一个具体的、自包含的子任务
- 独立执行,不依赖其他 Worker 的实时状态
- 完成后向 Coordinator 汇报
Coordinator 的核心职责不是派活,而是读懂 Worker 的结果,再决策下一步。
并行与串行的边界
多 Agent 的关键设计决策:哪些任务可以并行,哪些必须串行?
可以并行的情况(读操作、独立子任务):
- 同时探索代码库的不同模块
- 同时搜索多个主题的资料
- 同时对不同文件做只读分析
必须串行的情况(有依赖关系、写操作):
- 实现依赖探索的结果——必须先探索完才能实现
- 多个 Worker 写同一批文件——会产生冲突
- 验证依赖实现完成——不能提前跑
乱用并行的后果:Worker 拿到脏数据,结果互相覆盖,Coordinator 无法汇总。并行是效率工具,不是默认选项。
上下文隔离问题
多 Agent 系统的一个关键工程挑战是:每个 Worker 的上下文是隔离的。
Worker 只知道 Coordinator 给它的那段 prompt,看不到用户的完整对话历史,也看不到其他 Worker 正在做什么或已经做了什么。
这要求 Coordinator 在派发任务时必须做到:
- 自包含:每个 Worker 的 prompt 里包含它完成任务所需的全部信息
- 不依赖共享上下文:不能写"根据刚才讨论的方案去实现"——Worker 没看过那段讨论
- 明确的完成标准:让 Worker 知道什么算「做完了」
一个反例:「根据你的发现去修复这个 bug」——这种 prompt 没有给 Worker 具体的文件路径、错误信息和修改方向,Worker 只能盲猜,结果大概率跑偏。
Worker 重试时的幂等性
多 Agent 系统里,Worker 失败后重试很常见。问题是:如果 Worker 已经执行了一半,Coordinator 只看到"失败",下一次重试可能会把副作用再执行一遍。
举个具体场景:一个 Worker 负责"给 100 个用户发送通知邮件"。它执行到第 60 个时网络断了,Coordinator 收到失败状态后重新派发任务。如果 Worker 没有幂等设计,前 60 个用户可能会收到第二封邮件。
工程上不要把"重试"简单理解成重新调用一次模型。只要 Worker 会写文件、发请求、改数据库、发消息,就要先设计幂等边界。常见做法有几种:
- 给每个子任务生成稳定的
task_id,所有外部写入都带上这个 id - 对有副作用的操作记录执行状态,例如
pending / running / completed / failed - 写入前检查同一个
task_id是否已经完成,完成过就直接返回已有结果 - 把 Worker 输出拆成"计划"和"执行"两步,先由 Coordinator 审查计划,再允许执行副作用
一个简化版的状态记录可以长这样:
python
from dataclasses import dataclass
@dataclass
class TaskRecord:
task_id: str
status: str
result: str | None = None
class TaskStore:
def __init__(self):
self.records: dict[str, TaskRecord] = {}
def start_once(self, task_id: str) -> bool:
record = self.records.get(task_id)
if record and record.status == "completed":
return False
self.records[task_id] = TaskRecord(task_id=task_id, status="running")
return True
def complete(self, task_id: str, result: str) -> None:
self.records[task_id] = TaskRecord(
task_id=task_id,
status="completed",
result=result,
)这段代码不适合直接上生产,生产里要换成数据库事务或队列系统的去重能力。它想说明的是一个原则:Coordinator 不能只记"派出去过",还要记"这个副作用是否已经成功发生过"。
子 Agent 的权限边界
多个 Worker 共用一批工具时,真正危险的不是 Worker "不听话",而是系统把它不该拥有的能力给了它。
比如一个 Worker 只负责读取公开文档,却拿到了数据库写入工具;另一个 Worker 只负责总结搜索结果,却能读取其他用户的会话状态。你可以在 prompt 里写"不要访问无关数据",但更可靠的做法是:它根本拿不到那个工具。
权限边界通常可以从三层做:
- 工具列表隔离:只把当前任务需要的工具交给 Worker
- 参数范围限制:即使能调用工具,也只能访问允许的路径、集合或用户空间
- 结果返回过滤:Worker 结果回到 Coordinator 前,先过滤掉密钥、内部日志和不该暴露的中间状态
如果把 Worker 当成"带工具的函数调用",权限设计会清楚很多。函数只接收必要参数,只返回约定结果,不应该随手拿到全局状态。
会话隔离
还有一个容易晚发现的问题:不同用户的 Coordinator 实例之间不能共享临时状态。
假设你把 Worker 中间结果存在一个全局字典里,key 只用 task_id。两个用户同时发起任务时,只要 task_id 生成规则不够稳,A 用户的 Worker 结果就可能被 B 用户的 Coordinator 读到。这个 bug 不一定马上暴露,但一旦发生就是数据隔离事故。
最小可用的做法是把所有运行态 key 都带上 session_id 或 user_id:
python
def state_key(session_id: str, task_id: str) -> str:
return f"{session_id}:{task_id}"更稳的做法是让 Coordinator、Worker、工具调用日志都显式携带同一个 session_id,日志查询、状态读取、结果汇总都只能在这个会话范围内发生。多 Agent 系统一旦接入真实用户,隔离问题就不再是架构洁癖,而是安全底线。
从 Claude Code 源码看真实的多 Agent 实现
Claude Code v2.1.88 内置了一套完整的多 Agent 架构,是观察这套模式工程落地的好案例。
Coordinator 的职责边界
Claude Code 在 Coordinator 模式(coordinator/coordinatorMode.ts)下运行时,系统提示词明确规定了它的角色:
"你是协调者(coordinator)。你的工作是:帮用户实现目标、指导 Worker 研究和实现代码、汇总结果并与用户沟通。能直接回答的问题直接回答——不要把自己能处理的工作委派出去。"
Coordinator 不是只负责调度的机器,它本身有判断能力,简单的事情自己处理,不要无脑地把所有事情都转包出去。
专用 Worker 的设计
Claude Code 内置了几类专门化的 Worker,每类有固定的权限边界:
Explore Agent(探索专员):
- 专门负责搜索和读取代码库
- 严格只读:系统提示词里有
=== CRITICAL: READ-ONLY MODE ===,列出了所有禁止操作——不能创建文件、不能修改文件、不能删除文件,不能用重定向符写文件 - 工具层面也做了限制:
FileEditTool、FileWriteTool从可用工具列表中移除 - 目的:让 Coordinator 可以放心地并行派发多个探索任务,不用担心探索 Agent 误改代码
Verification Agent(验证专员):
- 专门验证实现结果是否正确
- 设计原则:用全新视角审查,不带实现过程的先入为主
- 和实现 Worker 隔离上下文,就是为了让验证独立有效
工具权限是任务边界的工程化表达。探索不该改文件,就从工具层面禁掉写操作,而不是只靠 prompt 里写"请不要修改文件"。
Worker 结果的传递方式
Coordinator 和 Worker 之间的通信通过结构化消息进行。Worker 完成后,结果以 <task-notification> XML 格式传回给 Coordinator,包含任务 ID、状态(completed / failed / killed)、摘要和具体结果。
这个设计让 Coordinator 可以:
- 同时跟踪多个 Worker 的状态
- 区分「任务完成」和「任务失败」
- 根据 task_id 决定是继续已有 Worker 还是启动新 Worker
Coordinator 可以「续接」已完成 Worker(保留之前的上下文),也可以新建 Worker(从空白上下文开始)。选哪种取决于新任务和上一个任务的上下文重叠度:重叠高就续接,重叠低就新建。
并行是刻意设计的
Claude Code 的 Coordinator 系统提示词里有一句话很直白:
"并行是你的超能力。Worker 是异步的。只要有机会,就并行启动独立的 Worker,不要把可以同时做的事情串行化。"
这是架构决策。Agent 系统的速度瓶颈通常在等待(等模型响应、等工具执行),能并行就并行,等待时间重叠,总时长才能压缩。
多 Agent 系统的失控点
多 Agent 比单 Agent 更难控制,主要在三个地方:
1. Coordinator 的任务分解质量
Coordinator 拆出来的子任务如果粒度不对——太粗了 Worker 不知道怎么做,太细了 Worker 花大量时间做无用功——整个系统效率就会崩塌。拆任务是多 Agent 系统中技术要求最高的环节。
2. Worker 之间的隐性依赖
并行运行的 Worker 如果存在依赖(Worker A 的结果是 Worker B 的输入),但 Coordinator 没有感知到,就会出现数据竞争或结果不一致。单次测试通常不会暴露,任务复杂了才会炸。
3. 成本和轮次的指数级增长
每个 Worker 都在独立消耗 Token。Coordinator 无节制地并行派发,成本比单 Agent 快速翻倍。多 Agent 系统必须有更严格的预算和轮次控制,不能沿用单 Agent 的阈值。
什么任务适合多 Agent
适合:
- 任务可以被清晰拆解成独立子任务
- 子任务之间真正可以并行(不存在实时依赖)
- 单 Agent 串行完成会太慢(耗时是主要问题)
- 有明确的汇总点(所有结果最终需要整合)
不适合:
- 任务本身就是线性的、无法拆分
- 子任务之间依赖紧密、必须串行
- 任务规模小(Coordinator 的调度开销比任务本身还大)
- 上下文需要完全共享(各 Worker 需要看到彼此的实时决策)
先用单 Agent 做。确认单 Agent 真的是速度瓶颈之后,再引入多 Agent。很多开发者把本该写死步骤的流程硬上多 Agent,反而更复杂、更难调试。
和其他章节的关系
- Agent 基础原理:多 Agent 建立在单 Agent 循环的基础上,Coordinator 和 Worker 本质上都是在跑各自的 Agent Loop。先把单 Agent 的状态管理和终止机制理解清楚,再看多 Agent 的调度才不会迷失。
- Tool Calling:Worker 的权限边界通过工具列表来控制,理解工具权限系统有助于设计专用化 Worker。
- AI 应用系统设计:多 Agent 在完整系统里怎么落地,涉及任务调度、状态持久化、日志追踪,这些在系统设计章节有进一步展开。
常见面试考点
多 Agent 的问题经常考得很工程化:不是“多个 Agent 更强”,而是多个执行单元并行以后,系统怎么不乱。
- 子 Agent 边界:Worker 的输入、权限、可写范围和输出格式都要明确,不能让它靠共享上下文猜任务。
- Coordinator 角色:Coordinator 不只是派活,还要判断是否值得拆分、跟踪 Worker 状态、汇总结果并决定下一步。
- 并行与串行判断:读操作和互不依赖的子任务适合并行;共享写文件、有前后依赖或需要统一决策的任务必须串行。
- 幂等性设计:Worker 重试时要避免重复副作用,常见手段包括稳定 task_id、执行状态记录和写入前去重。
- 会话隔离:多用户或多任务并行时,状态 key、日志和 Worker 结果必须带 session_id 或用户边界,避免串数据。
- 成本控制:多 Agent 会放大 token、工具调用和等待成本,不能无节制地把小任务拆给多个 Worker。
下一章:持久化记忆系统——多 Agent 解决任务怎么分工,记忆系统解决跨轮次、跨会话的信息怎么留下来。