← 返回目录
第 4 章

多 Agent 体系:分工和调度

6 种内建 Agent、fork 与 spawn 的缓存优化、Verification Agent 的对抗性 prompt——Claude Code 的多 Agent 架构。

让一个 Agent 同时研究、规划、实现、验证,每件事都做不扎实。职责拆分是基本工程原则,Claude Code 的多 Agent 体系就是这个原则的具体实现。

6 种内建 Agent

Claude Code 内置了 6 种 Agent,每种都有明确的职责边界:General Purpose(通用执行)、Explore(纯只读代码探索)、Plan(纯规划不执行)、Verification(对抗性验证)、Claude Code Guide(使用指导)、Statusline Setup(状态栏配置)。

Explore Agent 的 prompt 措辞非常强硬,明确禁止创建、修改、删除文件,禁止用重定向写文件,禁止运行任何改变系统状态的命令。可用工具只有 GlobGrepFileReadBash 仅限 lsgit statusgit log 这类只读操作。外部用户默认用 Haiku 模型(更快更便宜),内部用户继承主模型。为什么这么极端?因为探索阶段如果不小心改了东西,后续实现阶段就会在错误的基础上继续。把权限彻底锁死,朴素但有效。

Verification Agent 是 6 种里设计最复杂的,单独一节讲。

Verification Agent:130 行对抗性 prompt

130 行 prompt,可能是整个源码里最精心设计的一段文字。核心方向只有一个——想办法搞坏它(try to break it)。

prompt 开头列出两种常见的验证失败模式:第一种是 Verification avoidance,只看代码不跑检查,写个 PASS 就走;第二种是被前 80% 迷惑,UI 看着不错、测试也过了,就忽略剩下 20% 的边缘问题。然后强制要求一系列验证动作,根据变更类型有不同策略——前端改动要启 dev server 然后用浏览器自动化去点;CLI 改动要检查 stdout/stderr/exit code;数据库迁移要测 up/down 还要测已有数据。

最狠的部分是列出了验证者常见的合理化倾向,并要求识别和抵制。“代码看起来是对的”——看不是验证,跑一下。“实现者的测试已经通过了”——实现者也是 LLM,独立验证。每个检查项必须包含实际执行的命令和观察到的输出,最后给出 VERDICT: PASS / FAIL / PARTIAL

设计这个 Agent 的人预判了 LLM 作为验证者会走的所有捷径,然后一一堵死。

AgentTool:1397 行的调度中心

AgentTool.tsx 是所有子 Agent 调用的入口。进来一个调用请求,它做这些事:判断类型(fork / 内建 agent / 多 agent teammate / 远程),解析输入参数(descriptionpromptsubagent_typemodelrun_in_backgroundisolationcwd),按权限规则过滤可用 agent,检查 MCP 依赖,构造 system prompt 和 prompt messages,处理 worktree 隔离,注册前台/后台任务,最终调用 runAgent()

输入参数里有几个值得注意。isolation 控制子 Agent 是否在独立 git worktree 里跑,隔离级别影响文件系统访问。run_in_background 让 Agent 异步运行,主线程不等结果,完成后通过 notification 通知。model 允许为子 Agent 指定不同模型——但有一个重要限制,下面讲。

Fork 的缓存优化

fork 和普通 spawn 的区别,在缓存层面最明显。

fork 一个子任务时,它继承主线程的 system prompt、完整对话上下文、工具集,尽量保持字节级一致。为什么?为了让 API 请求的前缀和主线程一样,从而复用主线程的 prompt cache。源码注释直说:fork 不应该换模型,因为换模型会改变 system prompt 里的模型描述字段,破坏 cache 前缀匹配。普通 spawn 的子 Agent 有干净的上下文,适合需要和主线程完全隔离的场景,代价是没有缓存复用,成本约为 fork 的 10 倍。

选 fork 还是 spawn,不只是功能问题,是成本决策。

runAgent.ts:子 Agent 完整生命周期

runAgent.ts 973 行,负责子 Agent 从初始化到清理的完整过程。

启动阶段:初始化 Agent 专属 MCP servers(可从 frontmatter 定义),克隆 file state cache,获取 user/system context,对只读 Agent 做内容瘦身(裁掉不必要的工具和 prompt 内容),构造专属权限模式,组装工具池,注册 frontmatter hooks,预加载 skills,执行 SubagentStart hooks,调用 query() 进入主循环。

清理阶段:记录 transcript,断开 MCP 连接,注销 hooks,停止 perfetto tracing,清理 todos 和 shell tasks。子 Agent 不是”调用完就完”,它有完整的资源生命周期,每一项都要显式清理。

任务系统:5 种任务类型

tasks/ 目录下实现了 5 种任务类型,覆盖不同的执行场景:

DreamTask 是自主后台任务,Agent 在后台持续运行,完成后通过 notification 回到主线程。LocalAgentTask 处理本地 Agent 的前台、后台、异步三种模式。RemoteAgentTask 对接远程 Agent 执行环境。InProcessTeammateTask 是进程内的 teammate,共享内存空间。LocalShellTask 处理 shell 任务。

后台 Agent 有独立的 abort controller,可以随时被主线程终止。多个后台任务并发时,各自的生命周期互不干扰——这是第一章提到的”进程管理”在任务层面的具体实现。


参考来源: 本文内容参考 Xiao Tan(@tvytlx)的《Claude Code 源码架构深度解析 V2.0》,基于原报告的分析框架和研究成果整理。