Claude Code 的核心架构原则:Prompt Caching 决定一切
Summary
Thariq(Claude Code 团队)公开 Claude Code 的核心工程原则——整套 harness 围绕 prompt caching 设计。Prompt caching 通过**前缀匹配(prefix matching)**复用上次请求的计算,长任务 Agent 产品的可行性几乎完全建立在它之上。关键约束:前缀任何位置发生变化都会让其后所有 token 失效。五条经验:① 静态内容前置(System Prompt → Tools → CLAUDE.md → Session → Messages),追求最大前缀共享;② 用 message(如 <system-reminder>)传递更新而非改 system prompt;③ 不要中途换模型(缓存按模型分),切换用 sub-agent handoff;④ 不要中途增删工具(用 EnterPlanMode/ExitPlanMode 工具切状态、用 defer_loading 替代移除);⑤ Compaction 用 cache-safe forking(前缀与父对话完全一致,只追加 compaction prompt)。最反直觉的发现:在 100K Opus 对话中切换到 Haiku 答简单问题,比让 Opus 继续答更贵——因为要重建 Haiku 的 prompt cache。运维要求:把 cache hit rate 像 uptime 一样监控,cache miss 率波动几个百分点即按 SEV 处理。Plan Mode 设计是最好的范例:不切工具集,把 Plan Mode 本身做成工具,cache 完全不破。金句:Claude Code is built around prompt caching from day one — you should do the same if you're building an agent.
Key Concepts
- 前缀匹配缓存 — Prompt caching 通过 prefix matching 工作,前缀任何位置变化都会让其后失效;这是 Claude Code 一切设计的底层约束
- Cache Rules Everything Around Me — 工程界经典格言在 Agent 时代的回响;长任务 Agent 的可行性建立在 caching 之上
- 静态在前动态在后 — System Prompt → Tools → CLAUDE.md → Session → Messages,追求最大前缀共享
- system reminder 模式 — 不改 system prompt 传更新,用消息层注入(如时间变化、文件修改)
- 模型间缓存隔离 — Prompt cache 按模型分;100K Opus 对话切 Haiku 答简单问题反而更贵
- Sub Agent Handoff — 需要换模型时不在同 session 切,用 sub-agent 准备 handoff 消息
- Plan Mode 即工具 — 不切换工具集进入 plan mode,把 EnterPlanMode/ExitPlanMode 做成工具本身
- defer_loading 替代移除 — 工具不移除而用轻量 stub(defer_loading: true)+ ToolSearch 按需展开 schema
- Cache Safe Forking — Compaction 等 fork 操作必须复用父对话的完整前缀(同 system + 同 tools + 同 history),只追加新内容
- Compaction Buffer — 上下文窗口预留空间给 compaction prompt 和 summary 输出
- 缓存命中率即可用性指标 — 把 cache hit rate 当 uptime 监控,miss 率几个百分点波动即 SEV
- token 顺序的脆弱性 — 工具顺序非确定性、时间戳进 system prompt、参数变化都会破缓存
- Autonomous Plan Mode 入口 — 因为 Plan Mode 是工具,Agent 能自主进入;这是 cache-friendly 设计的副作用红利
Tags
claude-code, prompt-caching, prefix-matching, agent-engineering, harness-design, plan-mode, tool-search, compaction, cost-optimization, anthropic
Detailed Content
核心命题:Cache 是 Agent 工程的底层约束
[Long-running Agentic Product]
↓
依赖于
↓
[Prompt Caching]
↓
通过
↓
[Prefix Matching]
↓
约束
↓
[整个 Harness 设计]
为什么这件事重要:
- 长任务 Agent 每轮都要把整个对话历史传回模型
- 没有 caching → 每轮成本 × 轮数 = 不可负担
- 有 caching → 第二轮起仅付增量成本
- Claude Code 的订阅 plan 慷慨度直接挂钩 cache hit rate
五条经验(含设计哲学)
经验 1:静态在前,动态在后
正确顺序(Claude Code 实际架构):
1. Static system prompt & Tools ← 全局缓存(跨用户跨 session)
2. CLAUDE.md ← 项目级缓存
3. Session context ← session 内缓存
4. Conversation messages ← 增量
反例(破坏缓存的常见错误):
- 静态 system prompt 里嵌时间戳
- 工具定义顺序非确定性变化
- 工具参数动态变化(如 AgentTool 能调用的 sub-agent 列表)
设计含义:任何带有时间属性、上下文属性的内容,都不要塞进前缀。
经验 2:用 message 传更新
错误做法:
更新时间 → 改 system prompt → 整个 cache 失效
正确做法:
更新时间 → 在下一条 user message 或 tool result 注入
<system-reminder>It is now Wednesday</system-reminder>
→ 前缀不变,cache 命中
Claude Code 的 system-reminder 模式就是这条经验的产物——你看到的 <system-reminder> 标签是 cache-friendly 的更新通道。
经验 3:不要中途换模型
反直觉数学:
- 你在 100K Opus 对话中
- 想问个简单问题想用 Haiku 省钱
- 结果:切换到 Haiku 比让 Opus 继续答更贵
- 原因:Haiku 没有这个 100K 的 cache,要重建
正确做法 — Sub-Agent Handoff:
[主 session, Opus, 100K cached]
↓
Opus 准备 handoff 消息(任务描述、必要上下文)
↓
[Sub-agent, Haiku, 干净上下文]
↓
处理任务
↓
返回结果给主 session
Claude Code 的 Explore agent 用的就是这个模式(Haiku 处理代码探索)。
经验 4:不要中途增删工具
One of the most common ways people break prompt caching.
直觉上觉得"该给模型的工具就给"是对的,但工具是缓存前缀的一部分——增删工具 = 让前缀变 = 整个对话的 cache 失效。
范例 1:Plan Mode 设计
错误的直觉做法:
进入 plan mode → 把工具集换成只读 → cache 失效
Claude Code 的实际做法:
始终保留所有工具
将 EnterPlanMode 和 ExitPlanMode 做成工具本身
进入 plan mode → 模型收到 system message 说明 plan mode 规则
退出 plan mode → 调用 ExitPlanMode 工具