设计思想深度解读
不是代码层面的分析,而是工程思路的解读。基于源码拆解提炼的设计原则。
来源:@tvytlx
源码泄露了什么秘密?
大多数人对 Claude Code 的分析聚焦在两件事:system prompt 写了什么、它调了哪些工具。这两件事确实重要,但它们只是这个系统的皮肤。
真正差在哪?差在 prompt 背后有一整套编排机制,工具背后有一整条治理流水线,Agent 背后有一套分工和调度系统,生态扩展背后有一套让模型"知道自己能干什么"的感知通道。
1. System Prompt 不是一段固定文本
Claude Code 的 system prompt 是由 getSystemPrompt() 函数动态拼装出来的。
静态部分("宪法")
- 身份定位
getSimpleIntroSection() - 系统规范
getSimpleSystemSection() - 做任务的哲学
getSimpleDoingTasksSection() - 风险动作规范
getActionsSection() - 工具使用规范
getUsingYourToolsSection() - 语气风格
getSimpleToneAndStyleSection() - 输出效率
getOutputEfficiencySection()
动态部分("当期政策")
- session guidance、memory、环境信息、语言设置、输出风格
- MCP instructions、scratchpad、function result clearing
- token budget、brief mode
SYSTEM_PROMPT_DYNAMIC_BOUNDARY 标记明确了缓存友好边界。边界之前的内容稳定,可以被 API 层缓存。当产品每天处理海量请求时,这种设计直接影响运营成本。
2. "做任务的哲学"写成了制度
getSimpleDoingTasksSection() 把行为规范写成制度,而不是依赖模型临场发挥:
- 不要加用户没要求的功能
- 不要过度抽象
- 不要瞎重构
- 不要乱加注释和文档字符串
- 不要做不必要的错误处理和兜底逻辑
- 不要设计面向未来的抽象
- 先读代码再改代码
- 不要轻易创建新文件
- 不要给时间估计
- 方法失败时先诊断原因再换策略
- 删除确认没用的东西,不搞兼容性垃圾
- 结果要如实汇报,不能假装自己测试过了
3. 风险动作:把爆炸半径意识编进系统
getActionsSection() 定义了什么叫"需要确认的风险动作":
- 破坏性操作
- 难以回滚的操作
- 修改共享状态
- 对外可见的动作
- 上传到第三方工具
还特别强调:不要用破坏性操作当快捷方式,遇到陌生状态先调查,merge conflict 和 lock file 不要粗暴删除。
4. 工具使用规范是 grammar,不是工具列表
这不是在说"你有这些工具",是在说"你必须用正确的方式使用这些工具":
- 读文件用
FileRead,不要用cat/head/tail - 改文件用
FileEdit,不要用sed/awk - 新建文件用
FileWrite,不要用echo重定向 - 搜文件用
Glob,搜内容用Grep - Bash 只留给真正需要 shell 的场景
- 没有依赖关系的工具调用要并行
很多 agent 的不稳定,恰恰来自模型用错了工具。比如用 bash sed 去改代码,一个正则写错就崩了。
5. 六个内建 Agent:分工比想象中细
| Agent | 职责 | 权限 |
|---|---|---|
| General Purpose | 主任务执行 | 全权限 |
| Explore | 代码探索 | 纯只读(不能 bash/不能写文件) |
| Plan | 需求理解 + 架构规划 | 纯只读(architect,不是 executor) |
| Verification | 独立验证 | try to break it |
| Claude Code Guide | 引导用户 | 只读 |
| Statusline Setup | 状态栏配置 | 只读 |
背后判断:让一个 Agent 同时做研究、规划、实现、验证,最后每件事都做不扎实。
Explore Agent 的只读设计
- 不能创建/修改/删除/移动文件
- 不能写临时文件、不能运行改变状态的命令
- 工具只有
Glob、Grep、FileRead - Bash 只允许
ls、git status、git log、git diff
探索阶段如果不小心改了什么东西,后面的实现阶段就会出问题。把探索和实现的权限彻底隔离。
Verification Agent:"想办法搞坏它"
Prompt 点出两类常见验证失败:
- verification avoidance — 只看代码不跑检查,写个 PASS 就走了
- 被前 80% 迷惑 — UI 看起来行、测试过了,就忽略剩下 20%
强制要求做 adversarial probes,主动找边界情况。每个检查必须带实际执行的命令和输出。最后必须给出 VERDICT: PASS/FAIL/PARTIAL。
6. 子 Agent 调度的 14 步 pipeline
主模型决定调用 Agent 工具
解析输入
判断类型
teammate / fork / built-in / background / remote
选择 agent definition
构造 prompt messages
构造或继承 system prompt
组装工具池
创建 agent 专属的 ToolUseContext
注册 hooks、skills、MCP servers
调用 runAgent()
内部调用 query() 进入主循环
query 产出消息流
记录 transcript,处理生命周期,清理资源
汇总结果或走异步通知
7. 工具调用的治理链路(14 步)
当模型决定调用一个工具时,实际链路:
- 找到对应的 tool definition
- 解析 MCP metadata
- 用 Zod schema 做输入校验
- 跑 tool 自己的
validateInput - 如果是 Bash,跑
speculative classifier预判风险 - 跑
PreToolUse hooks - 解析 hook 返回的权限结果
- 走正式的 permission 决策流程
- 根据 permission 决策可能再次修正输入
- 真正执行
tool() - 记录 analytics、tracing、OTel
- 跑
PostToolUse hooks - 处理结构化输出
- 失败时跑
PostToolUseFailure hooks
Hook 的表达能力
PreToolUse Hook 不只能记日志,它能返回:
message— 改写输出blockingError— 直接拒绝updatedInput— 改写输入permissionBehavior— 修改权限行为preventContinuation— 阻止后续流程additionalContexts— 补充上下文
但权力不是无限的:Hook 说 allow 不一定能绕过系统 deny/ask 规则。Hook 说 deny 则直接生效。 强大但受控。
8. 三套扩展机制
Skill
不是文档,是 workflow package。带 frontmatter 的 markdown prompt bundle,可以声明 allowed-tools,按需注入上下文。系统要求模型匹配到 skill 时必须调用,不能只提到而不执行。
Plugin
比 Skill 更重:markdown commands、SKILL.md 目录、commandsMetadata、userConfig、shell frontmatter、model 和 effort hints。是模型行为层面的扩展单元。
MCP
不只是工具桥。MCP server 连接时,如果提供了 instructions,会被拼进 system prompt。同时给模型新工具和使用说明。
9. 给子 Agent 写 prompt 的规范
AgentTool/prompt.ts 专门教模型怎么给子 Agent 写 prompt:
- fresh agent 没有上下文,要像给新来的同事做 briefing
- 说明目标和原因
- 说明你已经排除了什么
- 提供足够的背景让它能做判断
- 如果只要短答案,明确说
- 不要把理解任务的工作外包给子 agent
- 不要写"基于你的发现再去修 bug"这种偷懒 prompt
- 应该给到具体的 file path、行号、具体改动要求
10. 上下文是预算,不是免费空气
整个源码里有大量设计围绕一个主题:上下文是稀缺资源。
SYSTEM_PROMPT_DYNAMIC_BOUNDARY— 缓存友好边界- fork path 的 cache-identical prefix — 复用主线程缓存
- Skill 按需注入,不是一开始全塞进去
- MCP instructions 根据连接状态注入
- function result clearing 机制
- summarize tool results 机制
- compact 和 transcript 机制
- resume 机制
做 Demo 可以不在乎这些。做产品时,缓存命中率提高 10%,一个月省的钱够多雇一个人。
11. 后台任务和生命周期管理
runAgent() 里有大量不起眼但很说明问题的代码:
recordSidechainTranscript()writeAgentMetadata()registerPerfettoAgent()cleanupAgentTracking()killShellTasksForAgent()- 清理 session hooks、克隆的文件状态、todos entry
后台 Agent 有独立的 abort controller,支持前后台切换、自动 summarization、notification 回到主线程。
12. 五条核心设计原则
原则一:不要信任模型的自觉性
好行为要写成制度。你希望模型先读代码再改代码,就把这条规则写进 prompt。你希望模型遇到风险操作停下来确认,就在 runtime 层加权限检查。
原则二:把角色拆开
至少把"做事的人"和"验收的人"分开。同一个 Agent 既实现又验证,天然会倾向于觉得自己做得没问题。
原则三:工具调用要有治理
不是模型说调就调,中间要有输入校验、权限检查、风险预判。执行完也不是结束,要有 post-processing 和失败处理。
原则四:上下文是预算
每个 token 都有成本。能缓存的要缓存,能按需加载的不要一开始就塞进去,能压缩的要压缩。做 Demo 可以不在乎,做产品必须在乎。
原则五:生态的关键是模型感知
你给系统接了十个插件,但模型不知道什么时候该用哪个,那这十个插件就等于不存在。扩展机制的最后一步,是让模型看到自己的能力清单。