当前位置: 首页 > news >正文

深入 Claude Code 源码(六):多智能体——Coordinator 与 AgentTool 深度解析

单个 AI Agent 的局限是明显的:上下文窗口是固定的,一次只能处理有限量的信息;任务是串行的,做完一件事才能开始下一件;注意力是单一的,无法同时从多个角度分析同一个问题。

当任务足够复杂——比如同时重构多个模块、并行跑多条研究思路、让一个「策略层」和多个「执行层」分工合作——单个 Agent 就开始捉襟见肘了。

Claude Code 对这个问题的答案是:让多个 Claude 实例协同工作。具体有两种实现方式,一种是工具级别的子代理(AgentTool),另一种是进程级别的协调者模式(Coordinator Mode)。本文带大家把这两套机制都搞清楚。


一、两种多智能体模式的本质区别

先把这两种模式的区别说清楚,因为它们经常被混淆。

AgentTool(工具调用子代理)

主代理通过调用Agent工具(工具名Agent)来派发子任务。子代理在一个独立的queryLoop里运行,有自己的消息历史和上下文,完成后把结果返回给主代理,主代理继续它的任务。这本质上是一种串行嵌套——主代理暂停,等子代理完成,再继续。

Coordinator Mode(协调者模式)

通过环境变量CLAUDE_CODE_COORDINATOR_MODE=1激活。此时 Claude 变成一个「协调者」,它不直接执行代码,而是把任务分发给一组可以真正并行运行的 worker agents(工人代理)。Worker agents 有各自独立的进程,可以同时执行,协调者统筹全局。

用一个建筑工程的比喻:AgentTool 像一个包工头在现场盯着活干,做完一道工序再做下一道;Coordinator Mode 像一个项目经理,把土建、水电、装修三队同时派出去,自己负责协调进度和验收结果。


二、AgentTool:子代理的完整生命周期

src/tools/AgentTool/AgentTool.tsx是子代理系统的核心。

子代理的创建(forkSubagent()

当主代理调用Agent工具时,forkSubagent()函数负责创建一个新的执行上下文:

  1. 从当前会话的工具列表里,按照白名单过滤出子代理可用的工具集(子代理默认不继承所有工具)
  2. 创建一个新的AbortController,并绑定到主代理的 abort 信号——主代理被中断时,所有子代理也会联动中断
  3. 分配一个新的agentId(UUID),用于标识这个子代理的 session、日志、文件产出
  4. 在这个独立上下文下运行query()循环,就像一个完整的会话,只是上下文隔离

子代理的工具限制

子代理的工具集比主代理受限,有两层控制:

  • 通用限制:防止子代理再创建子代理(避免无限递归),AgentTool在子代理的工具列表里默认被排除
  • Coordinator Mode 限制:如果当前是协调者模式,worker agent 只能使用ASYNC_AGENT_ALLOWED_TOOLS白名单里的工具,这个白名单来自coordinatorMode.ts,专门设计来防止 worker「越权」

子代理的进度可视化

agentColorManager.ts为每个子代理分配一个颜色。终端 UI 里,主代理的输出和每个子代理的输出会用不同颜色区分,大家一眼就能看出「这条 Bash 命令是哪个代理执行的」。这在调试多代理任务时极大地降低了认知负担。

子代理的 Resume

子代理也有自己的 session ID,产出的 transcript 文件存储在独立路径下。通过resumeAgent()可以在主进程重启后恢复一个中途中断的子代理,让它继续未完成的任务。


三、Coordinator Mode:协调者的工作机制

Coordinator Mode 是一个更复杂的多代理协作框架,通过bun:bundle的条件编译开关(COORDINATOR_MODE)保护,只在有对应 feature flag 的构建里存在。

如何激活

// src/coordinator/coordinatorMode.tsexportfunctionisCoordinatorMode():boolean{if(feature('COORDINATOR_MODE')){returnisEnvTruthy(process.env.CLAUDE_CODE_COORDINATOR_MODE)}returnfalse}

设置环境变量CLAUDE_CODE_COORDINATOR_MODE=1即可,退出设置0或删除变量。

协调者的 System Prompt 注入

getCoordinatorUserContext()会在协调者的 user context 里注入特殊指令,大意是:

你是一个协调者,你的职责是分解任务、分配给 worker agents、汇总结果。不要自己直接执行代码或编辑文件,把具体工作交给 workers。

这段指令通过QueryEngine.submitMessage()里的userContext注入,而不是放在systemPrompt里,是为了避免影响工具列表的序列化格式。

协调者与 Worker 的通信工具

协调者的工具箱里有几个专用工具:

工具作用
TeamCreateTool创建一组 worker agents,启动并行执行
TeamDeleteTool解散 worker 团队,等待最终结果
SendMessageTool向特定 worker 发送指令或接收其回复

这三个工具在普通的非协调者会话里不可见,只有isCoordinatorMode()为 true 时才会被注入到工具列表。

Scratchpad 共享目录

协调者和 worker agents 之间传递大型中间结果(比如分析报告、代码片段),通过一个共享的 scratchpad 目录完成。这个目录通过CLAUDE_CODE_SCRATCHPAD_DIR环境变量指定,或者由 Statsig feature gatetengu_scratch控制是否启用。

Worker 把结果写到 scratchpad,协调者读取,这样就不需要把大量内容都放进消息里,避免撑爆各自的 context。


四、完整的多智能体协作架构

把两种模式放在一起,整体架构如图所示:

AgentTool 子代理(串行嵌套)

Worker Agent 2(并行)

Worker Agent 1(并行)

协调者进程

TeamCreateTool
+ SendMessageTool

TeamCreateTool
+ SendMessageTool

AgentTool 调用

写入 scratchpad

写入 scratchpad

读取 scratchpad

SendMessageTool 回复

SendMessageTool 回复

Coordinator Claude
分析任务、制定分工

Worker Claude
执行子任务 A
(独立进程,独立 context)

Worker Claude
执行子任务 B
(独立进程,独立 context)

Sub-agent Claude
在 Worker 内部
执行更细粒度子任务

Scratchpad
共享文件目录

可以看到,两种模式可以组合使用——Coordinator 用TeamCreateTool启动并行 Workers,Workers 内部再用AgentTool派发更细粒度的子代理,形成两级的层次结构。


五、任务系统(Task Tools)

独立于 AgentTool 和 Coordinator Mode 之外,Claude Code 还有一套异步任务系统,对应TaskCreateToolTaskGetToolTaskListToolTaskStopToolTaskUpdateToolTaskOutputTool这组工具。

任务系统的设计目标是让 Claude 能够创建后台长时间运行的任务,任务有自己的进程,产出 stdout/stderr 输出,主代理可以随时查询任务状态或获取输出,不需要一直等待。

这就像 Linux 的&后台运行——Claude 说「去跑这个测试套件,跑完了我来看结果」,然后继续做其他事情,通过TaskGetTool定期查询结果:

Claude 调用 TaskCreateTool → 启动 "npm test" 后台任务 Claude 继续做其他工作(修改其他文件、写文档等) Claude 调用 TaskGetTool → 查询任务状态:「running,已跑 47/200 个测试」 Claude 调用 TaskGetTool → 查询任务状态:「completed,所有测试通过」 Claude 汇总结果,返回给用户

任务系统和 AgentTool 的区别在于:AgentTool 的子代理是另一个 Claude 实例,有推理能力;Task 是一个普通的 shell 进程,只是执行命令。前者适合需要 AI 判断的复杂子任务,后者适合确定性的脚本执行。


六、自定义 Agent 定义

src/tools/AgentTool/loadAgentsDir.ts负责从本地目录加载自定义 agent 定义,这个目录通常是项目的.claude/agents/

大家可以在这里定义专属的 agent 角色,比如:

  • test-engineer.json:专注于写测试的 agent,只有文件读写和 Bash 工具权限
  • doc-writer.json:专注于写文档的 agent,只能读文件和写 markdown

每个 agent 定义包含:角色名称、系统提示词补充、工具白名单、颜色标识等。主代理在调用Agent工具时,可以指定要派遣哪个预定义角色,而不是每次都从零开始描述这个 agent 的职责。

这类似于公司里的岗位 JD——不用每次招人都从头描述岗位职责,直接套用预定义的岗位模板。


七、Session 模式感知与 Resume

Coordinator Mode 有一个细节值得关注:当用户用--resume恢复一个历史会话时,系统需要确保恢复的模式和当时的模式一致——不能把协调者会话用普通模式恢复,也不能把普通会话用协调者模式恢复。

matchSessionMode()负责处理这个一致性:

exportfunctionmatchSessionMode(sessionMode:'coordinator'|'normal'|undefined,):string|undefined{constcurrentIsCoordinator=isCoordinatorMode()constsessionIsCoordinator=sessionMode==='coordinator'if(currentIsCoordinator===sessionIsCoordinator){returnundefined// 模式匹配,无需处理}// 动态修改环境变量,让 isCoordinatorMode() 返回正确的值if(sessionIsCoordinator){process.env.CLAUDE_CODE_COORDINATOR_MODE='1'}else{deleteprocess.env.CLAUDE_CODE_COORDINATOR_MODE}return'已切换到匹配会话的模式'}

这种「动态修改环境变量」的做法看起来有点非常规,但是有充分理由的:isCoordinatorMode()每次调用都是读环境变量(没有缓存),所以修改环境变量之后,下一次调用就立刻反映新的值,不需要重启进程。在 Resume 场景里,这是最干净的实现方式。


到这里为止,我们共同走完了 Claude Code 源码 Harness 工程全解析的六个篇章:

  1. 启动层:守门员检查 + 并行预热 + 编译时功能开关 + 三条执行路径
  2. 查询引擎:AsyncGenerator 流式管道 + queryLoop 状态机 + 错误恢复 + session 持久化
  3. 工具系统:统一契约 + 三层权限防护 + BashTool 的精密安全设计 + 结果大小管理
  4. 上下文管理:四层防御(Budget → Snip → Microcompact → AutoCompact)+ Token Budget 续写
  5. MCP 协议:三种传输层 + OAuth 鉴权 + Elicitation 双向通信
  6. 多智能体:AgentTool 嵌套子代理 + Coordinator Mode 并行协作 + 任务系统

Claude Code 还在快速迭代,很多实验性功能(HISTORY_SNIPCONTEXT_COLLAPSEREACTIVE_COMPACTCOORDINATOR_MODE)正在逐步走向正式发布。所以这里不是终点,而是一个全新的开始——源码永远是最准确的文档,有疑问的时候,直接去读它,比任何文章都更可靠。

祝大家都拥有一段愉快而充实的 AI 工程探索之旅!

http://www.gsyq.cn/news/1610540.html

相关文章:

  • 9大网盘直链下载助手:浏览器一键解锁高速下载新体验
  • B站视频下载神器:3分钟掌握BiliDownloader高效下载技巧
  • Go语言的runtime.ReadMemStats内存统计与实时监控指标的导出方法
  • YOLO实例分割工业圆形仪表指针读数识别数据集|电力电表电流电压表深度学习视觉实战仓库
  • 06.28.每日总结
  • 安全组网前五品牌推荐
  • 导师放养没人带?笔墨 AI 全程逻辑引导,相当于半个指导老师
  • APK Installer深度解析:Windows平台上的Android应用部署技术内幕
  • 基于Basler相机的同步软件触发二次开发程序
  • Java的java.lang.StackWalker分布式
  • 2026国内GEO公司排名前十深度盘点!行业格局+实力拆解(企业选型必看)
  • LangGraph 中的 add_messages
  • 如何彻底解决Zotero Style插件兼容性问题:终极修复指南与优化方案
  • Sunshine游戏串流服务器:打造你的终极跨平台游戏串流系统
  • 数字电路模拟程序系列题目实践总结与分析
  • 程序员写技术博客的正确姿势|从零写出高质量 CSDN 爆款文章(排版+结构+流量技巧)
  • 从Vgs到VCO:用拉扎维《模拟CMOS》的核心概念,手把手拆解一个PLL设计流程
  • 在Windows上使用DS4Windows:将PS4/PS5手柄无缝转换为Xbox控制器
  • VR-Reversal:让3D全景视频在普通屏幕上自由探索
  • 2026年6月,长春市优质机动车鉴定评估机构揭秘
  • 别再死磕理论了!手把手带你用CANoe实测Autosar网络管理状态机(附报文分析)
  • SpringBoot+Vue 公益服务平台管理平台源码【适合毕设/课设/学习】Java+MySQL
  • AWS EBS 磁盘扩容与挂载实验手册
  • YOLOv8一站式本地部署:图像分类、检测与分割实战指南
  • Beyond Compare 5终极激活指南:三步实现永久专业版
  • 告别臃肿控制软件:G-Helper如何用50MB重塑华硕笔记本性能管理体验
  • Sora接入国内企业私有云的完整链路:从模型蒸馏、视频缓存优化到GPU资源调度(含华为昇腾适配代码)
  • 扩散模型能耗预测:计算复杂度与能源效率的关系
  • 008、SRGAN感知损失:对抗生成网络在超分中的视觉质量革命
  • 计算机专业就业:工程实践里的常见坑