老板怎么带团队?从 Claude Code 源码学 Multi-Agent 的“派活”艺术

老板怎么带团队?从 Claude Code 源码学 Multi-Agent 的"派活"艺术

一个优秀的老板,从不事必躬亲,而是把合适的人放在合适的位置,让他们各自发挥所长,自己只负责看方向、做决策。

这句话放在 Multi-Agent 系统里,同样成立。

前段时间 Claude Code 源码泄漏,里面关于多 Agent 的设计堪称教科书级别的「带团队范本」。它不是什么花哨的学术框架,而是一套经过了工业级验证的「派活」方法论。

今天这篇文章就用 「老板带团队」 这个视角,把 Claude Code 的多 Agent 机制彻底讲明白。看完你会搞懂三件事:

  1. 老板怎么分工:架构怎么设计,每个员工(Agent)的职责怎么划清。
  2. 老板怎么协调:员工之间怎么通信,怎么并行干活不打架。
  3. 老板怎么降本增效:怎么用 Fork 机制省成本,怎么用 Coordinator 模式并发拉满。

准备好了吗?我们从一个最朴素的问题开始。

一、为什么老板不能一个人干所有活?

先别急着看代码,我们想想现实中的老板。

如果一个小公司只有一个老板,他既要做市场调研、又要写代码、还要做测试、最后自己去评审。结果会怎样?

  • 脑子装不下:调研阶段的几十份文档、实现阶段的代码细节、评审阶段的挑错清单,全塞在他脑袋里,最后什么都记不清。
  • 角色混乱:他一边调研一边开始写代码,写到一半又回头查文档,效率极低。
  • 没法并行:他在调研的时候,代码和测试只能干等着。

这不就是单一 Agent 的困境吗?------上下文爆炸、职责混乱、没法并发

Claude Code 的解法很简单:别当光杆司令,去当团队老板

老板的工作不是自己一头扎进代码,而是:

  1. 拆解任务:把一个大的目标(比如「调研 React 18 新特性 + 在项目里实现一个 useTransition + 代码评审」)拆成几块。
  2. 派给专家:研究员去调研,工程师去实现,评审员去挑错。
  3. 收结果、做决策:老板自己只负责看大方向,收中间结果,最后拍板。

这就是 Multi-Agent 的核心思想:一个老板 Agent + 一堆专家 Subagent = 高效团队

Claude Code 源码里,这种「老板带团队」的模式一共有三种,由浅入深:

  • 常规 Subagent:老板临时派一个员工干完就回来(父子型)。
  • Fork Subagent:派一个「分身」出去,用老板的同款脑子干活,省钱又省时。
  • Coordinator 模式:老板彻底不干活了,专门当项目经理,带一大帮人并行冲锋。

下面我们一个个拆解。

二、常规 Subagent:老板如何给员工「发工具箱」和「划隔离区」?

老板要派一个员工出去干活,第一件事是:给他明确的工具和权限,但不能让他乱碰老板的东西

Claude Code 里,主 Agent(老板)派一个 Subagent(员工)时,做了两件关键的隔离。

1. 给员工发定制工具箱(工具隔离)

老板自己有几十种工具(读文件、写文件、执行命令、派新员工、问用户问题......),但你不能把这些全丢给一个刚来的实习生。为什么?

  • 如果实习生也能「派新员工」,他就会派子子员工,子子又派子子子......层层嵌套,最后整个公司的管理费(Token 成本)爆炸。
  • 如果实习生也能「问用户问题」,他可能在你跟客户开会时突然弹出对话框,场面失控。

所以 Claude Code 的老板会按员工身份给他配不同的工具箱,有三道关卡:

  • 第一关:全员禁用名单。所有员工都不能用的工具:派新员工、主动问用户、切换规划模式、停止其他任务------这些都是老板的特权。
  • 第二关:自定义员工再加严。如果是用户自己定义的 Agent(不是官方内置的),再多禁几个工具,防止乱来。
  • 第三关:后台员工走白名单。那些在后台静默跑的员工(比如自动生成 PR 描述),只能用一个极小范围的白名单工具(读文件、搜代码、执行命令,不能写全局状态)。

三道门走下来,每个员工拿到的工具箱都是刚好够用,绝不多给

对应到源码,就是一个过滤函数:

ts 复制代码
export function filterToolsForAgent({ tools, isBuiltIn, isAsync, permissionMode }): Tools {
  return tools.filter(tool => {
    if (ALL_AGENT_DISALLOWED_TOOLS.has(tool.name)) return false      // 第一关
    if (!isBuiltIn && CUSTOM_AGENT_DISALLOWED_TOOLS.has(tool.name)) return false // 第二关
    if (isAsync && !ASYNC_AGENT_ALLOWED_TOOLS.has(tool.name)) return false      // 第三关
    return true
  })
}

2. 给员工划独立的工作区(上下文隔离)

工具箱给完了,还有个大问题:老板正在看一份文件(读到第 100 行),派出去的员工也去看同一个文件,看到第 200 行------老板这边的「读到哪里了」就被污染了,下次老板以为自己已经读到 200 行,直接跳过,数据就错了

反过来,如果把员工完全隔离成一个全新的空环境,也不行:老板按 Ctrl+C 想中止整个任务,员工收不到信号,还在后台自顾自跑。

怎么解?Claude Code 的老板很聪明:不搞一刀切,而是按每个状态字段单独决策

四个关键决策:

状态字段 处理方式 为什么
读文件的缓存 克隆一份给员工 员工怎么读都不影响老板的文件视图
写全局状态(UI 状态) 直接关闭,改为空操作 防止两个 Agent 同时改 UI 导致界面错乱
注册后台任务的通路 保留一个小口子 员工自己起的后台进程需要登记,否则变孤儿
Agent 深度计数 独立 ID + 深度+1 方便追踪嵌套层数,超过阈值就报警

对应到源码:

ts 复制代码
export function createSubagentContext(parentContext, overrides): ToolUseContext {
  return {
    readFileState: cloneFileStateCache(parentContext.readFileState), // 克隆缓存
    setAppState: () => {},                                            // 关闭写全局
    setAppStateForTasks: parentContext.setAppStateForTasks ?? parentContext.setAppState, // 保留任务通路
    agentId: overrides?.agentId ?? createAgentId(),                   // 独立 ID
    queryTracking: {
      depth: (parentContext.queryTracking?.depth ?? -1) + 1,          // 深度 +1
    },
  }
}

小结:当好老板的第一步,是给员工划清边界------工具不能越权,状态不能污染。

三、老板和员工怎么沟通?------不打电话,只留「信箱」

员工派出去之后,老板怎么给他布置新任务?员工干完了怎么汇报?

你可能会想:老板直接打个电话(调用函数),等员工回来不就行了?

但仔细想想:如果员工要跑 5 分钟,那这 5 分钟老板只能干等着,用户跟老板说话也没反应。这就是同步阻塞。而且如果老板想同时派 5 个员工并行调研,打电话的方案直接崩溃。

所以 Claude Code 的老板选择了一种更聪明的沟通方式:员工信箱 + 字条

老板 → 员工:扔字条到信箱

每个员工都有一个 「信箱」pendingMessages 数组)。老板要给他布置活,就调一个 SendMessage 工具,往这个信箱里追加一条消息,然后立刻走人,绝不等着。

员工在自己的每一轮工作循环结束时,会主动去看看信箱。如果有新字条,就把它当作「用户新消息」塞进自己的对话历史,然后继续干活。

整个过程是异步的,老板从不阻塞。

更妙的是:如果员工已经干完活休息了(completed 状态),老板发消息会自动唤醒他------从磁盘恢复他的完整对话历史,塞进新消息,让他继续跑。员工不是一次性的,随叫随到。

源码里就是简单的数组追加:

ts 复制代码
export function queuePendingMessage(taskId, msg, setAppState): void {
  updateTaskState(taskId, setAppState, task => ({ 
    ...task, 
    pendingMessages: [...task.pendingMessages, msg] 
  }));
}

员工 → 老板:把完成报告伪装成「用户消息」

员工干完了,怎么告诉老板?

最直接的想法是:给老板发一个「工具返回」事件。但 Claude Code 玩得更优雅------把完成通知包装成一段 XML,然后伪装成一条普通用户消息,塞进老板的对话历史里

老板那边看到的就像用户自己发了一条新消息:

xml 复制代码
<task-notification>
  <task-id>agent-a1b/tmp/xxx.txt completed</task-id>
  <status>completed</status>
  <summary>Found null pointer in src/auth/validate.ts:42...</summary>
</task-notification>

这样做有三个好处:

  1. LLM 对 XML 天然友好:Claude 训练时就强调 XML 结构,不用额外教。
  2. 纯文本直接塞对话历史:不需要额外的结构化对象,流程简单。
  3. 天然复用 Agentic Loop:老板就像收到普通用户输入一样处理,不需要额外的状态机去「等通知」。

源码就是拼字符串:

ts 复制代码
const message = `<${TASK_NOTIFICATION_TAG}>
  <${TASK_ID_TAG}>${taskId}${TASK_ID_TAG}>
  <${STATUS_TAG}>${status}${STATUS_TAG}>
  <${SUMMARY_TAG}>${summary}${SUMMARY_TAG}>
${TASK_NOTIFICATION_TAG}>`;
enqueuePendingNotification({ value: message, mode: 'task-notification' });

小结:好的沟通机制,是「异步 + 消息」。老板不阻塞,员工不打扰,所有交流通过共享的信箱和对话历史完成。

四、Fork Subagent:派一个「克隆老板」出去干活,省钱又省时

常规 Subagent 已经很好用了,但 Claude Code 还有一个隐藏大招:Fork Subagent

我先问你两个问题:

  1. Claude Code 的 System Prompt 大概多长?------上万 Token
  2. 每派一个常规 Subagent,API 那边对这段 System Prompt 是重新算一遍,还是能复用?

答案是:默认重新算。这就好比老板每次派一个员工出去,都要把公司的全套规章制度、文化手册、项目背景重新给员工背一遍------上万字的文档,每派一个人就从头背一次,成本(钱)和延迟(时间)线性放大。

但 Anthropic 的 API 提供了一个 Prompt 缓存 机制:如果两次请求的 前缀字节完全一致,第二次就不用重新算,价格只要 10%,延迟也大幅降低。

问题是:缓存命中的要求极其严格------字节级别完全相同。 哪怕 System Prompt 里多一个空格、工具列表顺序变一下,缓存直接失效。

怎么办?

Claude Code 的巧妙思路:派一个「克隆老板」出去 ------这个 Subagent 的 System Prompt、工具池、对话前缀等所有影响缓存的东西,都和老板字节级一模一样。这样 API 一看:「哦,这个前缀我熟」,直接命中缓存,成本降到 10%。

这个员工就是 Fork Subagent。它和常规 Subagent 最大的区别是:

  • 常规 Subagent 有自己的定制 System Prompt(比如 Explore 专门做搜索)。
  • Fork Subagent 的 System Prompt 是直接复用老板已经渲染好的那份字节 ,甚至它的 getSystemPrompt 函数直接返回空串------因为不走生成流程,而是拿老板的现成结果。
ts 复制代码
export const FORK_AGENT = {
  getSystemPrompt: () => '',  // 返回空串,不走生成,直接复用老板的
  // 其他配置继承老板
} satisfies BuiltInAgentDefinition

什么时候用 Fork?------当你希望这个员工拥有老板的完整上下文和权限,只是「派个分身去试试另一条路」。比如「生成 PR 描述」「做 post-turn 总结」。

什么时候不用?------如果任务需要专业分工(比如专门搜代码的 Agent),就用常规 Subagent,因为它们的定制 prompt 无法复用缓存。

小结:成本优化本身就是一种能力。Fork Subagent 通过「字节级复用」,把派活的边际成本打到极低,让你可以更大胆地并发。

五、Coordinator 模式:老板彻底放手,当项目经理带大团队

前面讲的 Subagent 再厉害,本质还是 「老板 + 临时工」 的父子结构。但如果任务大到需要十几个员工同时开工(比如一个大型代码迁移,要并行调研 10 个模块),父子结构就显得单薄了。

这时候 Claude Code 切换到 Coordinator 模式 。这模式下,老板的角色发生根本变化:他不再干任何具体活,而是变成一个纯项目经理

老板的三大职责

  1. 派 Worker:根据任务拆解,一口气派出多个 Worker。
  2. 收结果:等 Worker 陆续完成,接收通知。
  3. 合成答案:自己读懂所有中间结果,做出最终决策并回复用户。

为了支撑这个角色,老板获得了一套「项目管理工具箱」:

  • TEAM_CREATE:创建 Worker 团队。
  • SEND_MESSAGE:给已派出的 Worker 发后续指令。
  • SYNTHETIC_OUTPUT:合成最终输出给用户。
  • STOP_WORKER:发现 Worker 跑偏时及时止损。

并行是超能力

Coordinator 模式的 Prompt 里有一句特别经典:

Parallelism is your superpower. Workers are async. Launch independent workers concurrently whenever possible.

翻译:并行是你的超能力。Worker 全是异步的,能一起派的绝不串行。

怎么实现?老板可以在同一条回复消息里 连续调用多个 TEAM_CREATE 工具------底层会一起并发执行,而不是一个跑完再跑下一个。

对比一下:

  • 串行:派 Worker1 → 等 2 分钟 → 结果 → 派 Worker2 → 等 2 分钟 → ...... 用户等十几分钟。
  • 并行:同时派 10 个 Worker → 等 3 分钟 → 所有结果陆续回来。用户等 3 分钟。

这就是并行带来的质变。

老板必须「理解」,不能「转发」

有一个非常容易踩的坑:老板收到 Worker 的结果后,偷懒直接交给另一个 Worker「based on your findings, implement the fix」。这是不合格的。

合格的老板会自己读所有 findings,真正理解问题,写成具体的实现规格,再派下去

Prompt 里反复强调:Synthesize, don't delegate。老板的存在价值就是做决策,不是当传话筒。

Worker 不能派 Worker

为了防止递归失控,Coordinator 模式下的 Worker 没有派活工具------它们只能干活,不能再去协调别人。整个系统保持扁平的两层结构:一个老板 + N 个 Worker。

常规 vs Coordinator 对比

维度 常规 Subagent Coordinator 模式
老板角色 全能选手,偶尔派临时工 纯项目经理,不干具体活
员工执行 默认同步(2 分钟后转后台) 默认异步
并发程度 偶尔并发 最大化并发
适用场景 单个任务 + 临时帮手 大任务 + 高并发拆解
系统形态 父子树 扁平两层

六、从 Claude Code 学到的 5 条「带团队」心法

文章快结束了,我们把所有内容总结成 5 条老板带团队的心法。这 5 条不仅能用在自己的多 Agent 系统里,也能直接用在面试答案里。

心法 1:给员工划清边界,按字段粒度做隔离

不要一刀切地「全隔离」或「不隔离」。对于每个状态字段,单独问一句:「员工拿了会污染老板吗?」------读文件缓存要克隆,写全局状态要关闭,任务注册通路要保留,深度计数要递增。

心法 2:沟通走「信箱」,不走「电话」

老板和员工之间不要用同步函数调用(打电话),而是通过消息队列 + 伪装成用户消息的通知。这样老板从不阻塞,员工异步执行,系统天然支持并发。

心法 3:工具箱要分级发放,不搞平均主义

全员禁用、自定义加严、后台白名单------不同身份的员工拿不同的工具包。既能保证干活,又能防止越权。

心法 4:降本增效是一种架构能力

通过 Fork Subagent 复用缓存,把每个员工的边际成本打到 10%,你才敢大规模并发。成本不是事后优化的事,而是设计之初就要考虑的。

心法 5:老板要「合成」,不要「转发」

多 Agent 系统的威力不在人多,而在协调者的决策质量。老板必须亲自理解所有中间结果,做出判断,而不是当传话筒。并行是手段,合成是目的。

写在最后

回头看,Claude Code 的多 Agent 设计并不是什么玄学。它本质上就是一个优秀老板的「派活」艺术:

  • 划清边界(隔离机制)
  • 高效沟通(消息驱动)
  • 降本增效(Fork 缓存)
  • 并行合成(Coordinator 模式)

每一块都不是新技术,但组合在一起,就成了一台能支撑顶级产品的工业级多 Agent 引擎。

希望这篇文章能帮你------无论是在面试中侃侃而谈,还是在自己设计 Multi-Agent 系统时少走弯路。

我们下篇见。


附:核心问题与回答

Q1:为什么要有多 Agent(Multi-Agent)?

A:单一 Agent 在复杂任务中存在三大痛点:上下文爆炸(信息太多装不下)、职责混乱(角色不清)、没法并发(一次只能做一件事)。多 Agent 通过任务拆解和专人专事来解决这些问题。

Q2:Claude Code 中父子 Agent 之间的通信机制是怎样的?

A :采用消息驱动的异步模型。父 Agent 通过 SendMessage 往子 Agent 的「信箱」(pendingMessages 数组)里写消息后立即返回;子 Agent 在每轮循环末尾主动读取信箱;子 Agent 完成后将结果包装成 XML 并伪装成用户消息,注入父 Agent 的对话历史。这种设计天然支持并发,避免阻塞。

Q3:Fork Subagent 是什么?解决了什么问题?

A:Fork Subagent 是一种复用父 Agent Prompt 缓存的优化机制。它通过保证 System Prompt、工具池等五项内容与父 Agent 字节级一致,从而命中 Anthropic API 的 Prompt 缓存,将成本降至原来的 10%。适用于需要继承父 Agent 完整上下文的任务(如生成 PR 描述),不适用于需要专业分工的场景。

Q4:Coordinator 模式与常规 Subagent 模式的核心区别?

A:常规 Subagent 模式下,主 Agent 是全能型选手,Subagent 默认同步执行,适合临时帮手。Coordinator 模式下,主 Agent 退化为纯协调者,不干具体活,只负责派 Worker、收结果、合成答案;Worker 默认异步,最大化并发,系统保持扁平两层结构。

Q5:Claude Code 如何实现 Subagent 的上下文隔离?

A :按字段粒度单独决策,而非一刀切。四个关键决策:1)读文件缓存克隆 一份给子 Agent;2)写全局状态完全关闭 (改为空操作);3)任务注册通路例外保留 ;4)独立 ID + 深度计数 +1。这些决策通过 createSubagentContext 函数实现。

相关推荐
名不经传的养虾人2 小时前
从0到1:企业级AI项目迭代日记 Vol.26|用AI是借力,教AI才是复制自己
人工智能·ai编程·skill·教ai复制自己
ZengLiangYi2 小时前
Cursor 对话导入:解析 SQLite 里的宝藏
ai编程·cursor
阿耶同学2 小时前
🔥 CrewAI 实战:构建多 Agent 协作团队
ai编程
GarrettGao2 小时前
MCP 实践-用 AI 对话触发 Jenkins 打包App
ai编程·mcp
郭煌2 小时前
# 什么该交给 AI,什么自己来:一个工程师的 4 象限决策法
ai编程
ZengLiangYi2 小时前
AI Coding JSONL 里的系统标签噪音如何过滤
ai编程
HLAIA光子2 小时前
Claude Code、Codex 为什么都选了 Grep 而不是 RAG
ai编程·claude
沫离痕2 小时前
Claude Code 配置目录说明
ai编程
人月神话Lee2 小时前
【图像处理】二值化与阈值——从灰度到黑白的决策
ios·ai编程·图像识别