从构建 Claude Code 得到的经验:Prompt Caching 就是一切
这篇文章把 Claude Code 的实践经验收敛为一个核心结论:在生产级 Agent 系统里,Prompt Caching 不是优化项,而是决定成本、延迟和迭代速度上限的基础架构。缓存命中率为什么是系统级指标作者强调真正瓶颈并非模型“聪明程度”,而是长链路 Agent 循环中的计算复用效率。Prompt Cachin…
转载说明:本文翻译并转载自 Lessons from Building Claude Code: Prompt Caching Is Everything,原文发布时间为 2026-02-19(以 X 帖子时间为准)。从构建 Claude Code 得到的经验:Prompt Caching 决定上限 工程里常说一句话:Cache Rules Everything Around Me。这条规律在 Agent 系统里同样成立。 像 Claude Code 这种长链路的 Agent 产品之所以可行,很大程度上依赖 prompt caching:它能复用前几轮请求的计算结果,显著降低延迟与成本。 到底什么是 prompt caching、它怎么工作、如何在工程里真正落地?可以先看 @RLanceMartin 的文章与我们这次自动缓存发布。 在 Claude Code 里,我们几乎把整套运行框架都建立在 prompt caching 上。缓存命中率高,成本就低,我们就能把订阅计划的速率限制做得更宽松。因此我们会对缓存命中率设置告警,命中率过低时甚至会按 SEV 事件处理。 下面是我们在大规模优化 prompt caching 时总结出来、而且很多看起来并不直觉的经验。为缓存设计 Prompt 布局 Prompt caching 的核心是前缀匹配:API 会从请求起点开始缓存,到每个 cache_control 断点为止。也就是说,内容顺序影响极大,你需要让尽可能多的请求共享同一个前缀。 最有效的方法是:静态内容在前,动态内容在后。在 Claude Code 中通常是:静态系统提示词 与工具定义(全局可缓存)Claude.MD(项目级可缓存)会话上下文(会话级可缓存)对话消息 这样可以最大化不同会话之间的缓存复用。 但这套顺序非常脆弱。我们以前打破它的典型方式包括:把细粒度时间戳写进静态系统提示词、工具定义顺序出现非确定性变化、修改工具参数(例如 AgentTool 可调用的代理集合)等。用消息更新,而不是改系统提示词 提示词里的信息有时会过期,比如时间变化了,或用户改了文件。直觉上你会想去改 prompt,但这会直接导致缓存失配,用户成本可能明显升高。 更稳妥的做法是把这类更新放进下一轮消息。比如在 Claude Code 中,我们会在下一条用户消息或工具结果里追加 <system-reminder> 标签(例如“现在是周三”),让模型拿到新信息,同时尽量保住缓存。不要在会话中途切模型 Prompt cache 是按模型隔离的,这会让缓存成本计算变得反直觉。 如果你已经在 Opus 的会话里积累了 100k tokens,这时想问一个“看起来很简单”的问题,切到 Haiku 反而可能更贵,因为你得为 Haiku 重新建立整段缓存前缀。 如果确实要切模型,更好的方式是用子代理:让 Opus 先准备一条 handoff 消息,再把任务交给另一个模型。我们在 Claude Code 的 Explore agents 上经常这么做(它们会使用 Haiku)。不要在会话中途增删工具 会话中途改变工具集,是最常见的缓存破坏源之一。直觉上“当前只给模型需要的工具”似乎更合理,但工具定义本身就是缓存前缀的一部分;一旦增删工具,整段对话缓存都会失效。 Plan Mode:围绕缓存约束来设计功能 Plan mode 是一个典型例子。直觉实现是:进入 plan mode 时,把工具集切成只读工具。但这会破坏缓存。 正确做法是始终保留完整工具集,把 EnterPlanMode / ExitPlanMode 设计成工具本身。用户切到 plan mode 时,系统消息只更新当前模式与行为约束(探索代码、不改文件、完成后调用 ExitPlanMode),工具定义保持不变。 这样还有额外好处:EnterPlanMode 既然是工具,模型可以在识别到复杂问题时自行进入计划模式,而且不会破坏缓存。 Tool Search:延迟加载,而不是移除工具 工具搜索功能同理。Claude Code 可能挂载几十个 MCP 工具,全部放进每个请求会很贵;但中途移除又会破坏缓存。 我们的做法是 defer_loading:不移除工具,而是先提供轻量 stub(仅保留工具名并标记 defer_loading: true),模型需要时通过 ToolSearch 工具发现并加载完整 schema。这样缓存前缀依旧稳定:同一批 stub 始终按同样顺序出现。 你也可以直接通过 API 使用 tool search 来简化这件事。上下文分叉与压缩(Compaction) Compaction 指的是:上下文窗口打满后,把已有对话压缩成摘要,再在新会话里继续。 这个过程在 prompt cachi…
正在初始化 WebAssembly 引擎…
首次编译原生模块可能需要数秒
就绪后,页面交互将以接近原生的速度运行