看完了 Claude Code 的源码实现,我建议你重构所有的 Agent 项目
Claude Code 源码拆解:它为什么更像一个 Agent 操作系统
很多人用 Claude Code 写代码时,都感觉它特别“懂事”。任务拆得清楚,代码改得稳当,不会随便加一堆没用的东西,也很少跑偏。表面看,这像模型能力强,或者 prompt 写得巧。但实际不是。

我逆向了它的 npm 包源码,发现真相完全不一样。它根本不是一个简单的命令行聊天机器人,而是一整套 Agent 操作系统。它的强,来自模块化的提示词装配、专门的 Agent 调度、可治理的工具执行流程,以及把安全和扩展都做成系统级机制。这套设计让它从玩具级工具变成了能长期用的产品级系统。普通开发者第一次接触 coding agent 时,常以为只要接个大模型加几个 shell 工具就够了。可实际跑起来,上下文污染、行为漂移、安全边界模糊这些问题很快就会冒头。Claude Code 提前把这些坑都用工程手段堵住了,所以用起来才那么顺。
核心结论就一句话:Claude Code 的优势不在任何一段神秘 prompt,而在它把提示词、Agent 编排、工具治理和扩展机制整合成了一套可产品化的运行时。这套系统让模型不再是临场发挥,而是按工程规范一步步执行。
Claude Code 的提示词不是一坨固定文字,而是装配框架
先说清楚提示词装配是什么东西。它就像搭积木,不是把所有规则一次性塞进模型,而是把不同部分按需组合成最终的系统提示。Claude Code 在 src/constants/prompts.ts 里实现了这个框架。
这个框架先定义身份和开场白,告诉模型自己是谁、要按什么风格回应。接着是基础规则,比如怎么完成软件工程任务、工具该怎么用、遇到风险动作要不要确认。最重要的部分是把工程行为哲学直接写进了规则:不要做用户没要求的功能,不要过度抽象代码,不要没必要就重构,不要乱加注释或类型定义,先读现有代码再提修改,不要轻易新建文件。如果任务失败,先诊断问题,不要盲目重试。结果必须诚实汇报,没验证过就别说验证过了。这些规则不是建议,而是硬性要求。
为什么这么做?因为很多 coding agent 出问题,不是模型笨,而是行为容易漂移。把好的工程习惯制度化后,模型就少走弯路。提示词里还专门写了工具使用规范:读文件优先用 FileRead,改文件优先 FileEdit,新建文件用 FileWrite,搜文件用 Glob,搜内容用 Grep,只有真需要 shell 时才用 Bash。无依赖的工具调用尽量并行执行。这套语法让模型知道“应该怎么正确用工具”,而不是只知道“有工具可用”。
更高级的地方是它有 prompt cache boundary 意识。源码里用了动态边界标记,把稳定部分和会话特定部分分开。这样哪些内容适合缓存、哪些必须动态注入、怎么减少 token 浪费,都考虑进去了。这已经不是 prompt 手艺活,而是 infra 级别的工程设计。
假设你在写一个大型项目,模型每次都要重新读全套规则,会浪费大量 token,还容易命中缓存失效。Claude Code 通过装配框架把稳定规则做成 cache-friendly 前缀,动态部分只注入必要内容,实际使用时响应更快、成本更低。这就是为什么它在长任务里表现特别稳。普通开发者如果只抄一段 prompt 去做类似工具,很快就会发现上下文膨胀、重复计算这些问题,而 Claude Code 把这些都提前工程化了。
提示词还分层。除了主系统提示,还有独立的 Agent prompt 层。子 Agent 运行在更窄、更实用的协议下:用可用工具完整完成任务,不要半成品,不要过度装饰,完成后给简洁报告。这层协议让子任务不会污染主上下文。整个装配系统把 markdown、metadata 和运行时约束结合在一起,形成了可扩展的产品 runtime。
Agent 调度不是简单 fork 子任务,而是专业化分工系统
Agent 在这里不是随便开个新聊天窗口。它是一套完整的 orchestration 系统。源码里 src/tools/AgentTool/runAgent.ts 和相关文件把这个流程写得清清楚楚。
先解释 Agent 是什么:它相当于给模型分配一个带特定角色和工具池的工作线程。Claude Code 内置了好几种专业 Agent,而不是让一个 Agent 什么都干。General Purpose Agent 负责常规执行,Explore Agent 纯读模式,Plan Agent 负责规划,Verification Agent 负责验证。这些分工直接写在 prompt 里,模型知道什么时候该用哪个、怎么写子 Agent 的 prompt、foreground 和 background 的区别、worktree 隔离的含义。
拿 Explore Agent 举例。它被严格限制成只读专家:绝对不能创建、修改、删除文件,不能写临时文件,不能跑改变系统状态的命令。只通过搜索、读文件和受限 shell 来探索,追求快速回报,还尽量并行调用工具。这不是普通搜索 Agent,而是故意裁剪成 specialist,只做探索不碰状态。
Plan Agent 也只读。它的工作是彻底理解需求、探索代码库、找现有模式、设计实现方案、给出 step-by-step 计划,最后列出关键实现文件。它是 architect,不是 executor。
最有意思的是 Verification Agent。它不是走过场确认“看起来 ok”,而是被指令要求 try to break it。它明确对抗两种常见失败模式:只读代码不跑命令就直接 pass,或者被表面成果迷惑。实际要求它跑 build、跑 test、跑 linter、针对改动类型用不同策略、做 adversarial probes,每个检查都要给出 command 和 observed output,最后输出 VERDICT: PASS / FAIL / PARTIAL。这套逻辑把验证做成了对抗性流程,从根本上避免了“自己给自己发毕业证”。
子 Agent 执行分两条路径:fork path 和 normal path。fork 适合继承上下文又不想污染主线程的情况,它尽量保持 system prompt 和 tool defs 一致,帮助 prompt cache 命中。normal path 则为指定类型 Agent 构造隔离上下文。runAgent 函数是子 Agent runtime 的构造器,它要初始化 MCP servers、合并工具、克隆 context、管理 file-state cache、注册 hooks、预加载 skills、创建 ToolUseContext,还要在结束时清理一切。这不是 wrapper,而是一整套 runtime 构造流程。
普通开发者第一次做多 Agent 系统时,最头疼的就是上下文变成垃圾桶,或者 token 浪费严重。Claude Code 用 fork 机制和 cache 优化解决了前者,用 specialization 解决了后者。整个调度链从 AgentTool.call 作为路由控制器开始,解析参数、检查权限、构造 prompt,再进入 runAgent 执行。这条 pipeline 让 Agent 行为可预测、可治理。
工具执行、Hook 和扩展机制:把治理做成运行时的一部分
工具执行在 Claude Code 里不是裸调函数,而是一条完整 pipeline。toolExecution.ts 描述了整个流程:找到 tool、解析 MCP metadata、schema 验证、speculative checks、执行 pre-tool hooks、根据 hook 结果做 permission decision、执行 tool、写 telemetry、执行 post-tool hooks、组装结果。如果失败还走 failure hook。
Permission 模型是整个系统的骨架。它决定哪些工具能自动跑、哪些要 ask 用户、hook 怎么参与、background Agent 有什么约束。hook 本身支持 pre-tool-use、post-tool-use、post-failure 等类型,能发消息、返回 blocking error、改写输入、注入 context、返回 allow/ask/deny,还能在某些情况下改写 MCP 输出。但 hook 给出的 allow 不会绕过其他 permission rules,runtime 还是会检查 settings 和交互要求。这就是成熟系统和玩具项目的区别。
Skill 不是说明文档,而是 prompt-native 的 workflow 模块。模型匹配到某个 skill 时,必须先调用 Skill tool,不能只嘴上说说。Skill 按需加载,不会一开始就把所有内容塞进 prompt。Plugin 更进一步,它提供 markdown commands、通过 SKILL.md 暴露 skill、frontmatter metadata、allowed-tool 约束、shell declarations 等,相当于把 prompt 内容、metadata 和 runtime 约束打包成扩展包。
MCP(假设是某种模型能力协议)不只是工具桥,还能把 instructions 拼进 system prompt,同时扩展模型能做什么、该怎么理解这些能力。这让扩展同时成为 capability bridge 和 behavior extension channel。
Hooks 和 permission 结合,把 runtime governance 做到了极致。整个工具层还围绕 context、cache、telemetry、lifecycle 做了工程化设计,所以用起来不像实验项目,而像长期维护的软件产品。
Claude Code 把 markdown、metadata 和 runtime constraints 结合起来的 plugin system,让扩展不再是外部漂着的脚本,而是模型能直接感知的行为模块。
假设你在本地跑一个 coding assistant,普通工具调用很容易失控:模型乱跑危险命令,或者 hook 绕过安全。Claude Code 的 pipeline 在每一步都插了 validation 和 governance 点,跳过任何一步都会让行为不可控。这就是为什么它能在真实环境里用,而不只是 demo。
操作案例:Verification Agent 在实际任务里的完整流程
以 Verification Agent 为例,看看这套系统怎么落地。假设主 Agent 完成了一次代码修改,现在要验证。
第一步,主模型调用 AgentTool,指定 subagent_type 为 Verification Agent,同时传入 description 和 prompt。为什么这一步?不指定类型就走普通路径,上下文容易污染;指定后系统会构造 agent-specific system prompt 和工具限制。
第二步,AgentTool.call 解析参数,检查 teammate 约束、MCP servers 是否满足、isolation 模式,然后分流到 fork 或 normal path。这里如果任务适合继承上下文,就走 fork,保持 cache 友好;否则构造隔离 worker context。跳过这一步,主线程很快就被中间验证日志淹没。
第三步,runAgent 初始化:合并 inherited 和 local MCP clients、克隆 context messages、管理 file-state cache、获取 system context、对 read-only agents 做 slimming、解析工具池、构建 agent-specific prompt、注册 frontmatter hooks 和 skills、创建 ToolUseContext、记录 transcript。为什么这么多初始化?为了让这个 Agent 成为一个自包含的 runtime bundle,不依赖外部状态。
第四步,进入执行循环。Verification Agent 收到指令:try to break it。它先探索代码,跑 build、test suite、linter、type-check,根据改动类型选择策略,做 adversarial probes。每步必须输出 command 和 observed output,最后给 VERDICT。这一步如果只读代码不跑命令,就会触发 prompt 里的 verification avoidance 警告,直接 FAIL。
第五步,结束时 runAgent 清理 MCP、hooks、shell tasks 和内存状态,同时把结果组装成 tool-result block 返回给主线程。为什么清理?不清理就会积累垃圾上下文,下次任务 token 爆炸。
跑完这一流程,你会看到主 Agent 收到干净的 PASS/FAIL 报告,附带所有 command 输出和 verdict。没有中间噪音,权限也全程受控。如果是 production 环境,telemetry 还会记录整个过程供后续分析。
这个案例里,每一步都服务于“让验证真正有效”这个目标,而不是走形式。普通开发者自己搭 Agent 时,往往只写个 prompt 说“去验证”,结果模型就随便看两眼说 ok。而 Claude Code 把对抗逻辑、工具限制、输出格式都硬编码进了 runtime,所以验证才可靠。
Claude Code 的这套设计给所有想做 coding agent 的人指了一条路:不要再把希望寄托在 magic prompt 上。真正能长期成立的,是模块化 prompt 装配、可治理的 tool runtime、把 workflow 做成 skill 资产、Agent specialization、context hygiene、让扩展对模型可感知、把安全写进 runtime。这些才是护城河。
下次再用 Claude Code,或者自己搭类似工具时,先想想它背后的系统,而不是只看表面输出。你会发现,好的 agent 产品,从来都不是模型单打独斗,而是把工程思维变成了代码。
夜雨聆风