做 Coding Agent 的人,迟早会盯上同一个指标:缓存命中率。
原因很直接。Coding Agent 是典型的「长上下文 + 多轮迭代」场景——读文件、跑命令、改代码、再读再改,每一轮都要把完整历史重新发给模型。历史越长,重复付费越多。
业界对这件事的重视程度,可能超出你的想象:Manus 团队曾公开表示,如果只能选一个指标,KV 缓存命中率是生产级 AI Agent 最重要的单一指标;Anthropic 的 Claude Code 团队更是对命中率设置了告警——一旦命中率过低就触发严重事件(SEV),和对待系统宕机一个级别。
更关键的是,在 Coding Agent 里,缓存不是「优化项」,而是「架构地基」。你的提示词结构、工具设计、会话管理方式,几乎都要围着它设计。
这篇文章就把「怎么把命中率做上去」讲清楚。
一、先记住一条规则:缓存按「前缀」逐字匹配
所有优化都从这一条衍生而来:
缓存匹配是逐字的、从前向后的。请求开头只要有任何一个 token 变了,从变化点往后的全部内容都得重算。
一个典型的 Agent 请求长这样:
[tools 工具定义] → [system 提示词] → [项目规则 CLAUDE.md] → [对话历史] → [工具返回结果] → [本轮用户消息]只有这段序列的前面部分与上次请求逐字一致时,匹配上的那一段才能按缓存价计费。
三家主流厂商的实现方式略有不同,先看清差异:
| 维度 | Claude | OpenAI | DeepSeek |
|---|---|---|---|
| 控制方式 | 显式:用cache_control指定断点 | 自动:前缀够长(1024 token 起)自动尝试 | 默认开启,无需改代码 |
| 命中条件 | 断点之前内容逐字一致 | 精确前缀匹配 | 需先完整持久化前缀单元 |
| 缓存读取价 | 约0.1x(写入 5m 为 1.25x、1h 为 2x) | 提供折扣读价 | 价差最大,可达数十倍 |
| 有效期 | 默认 5 分钟,可选 1 小时 | 通常 5–10 分钟不活跃失效 | 数小时至数天自动清理 |
一句话:Claude 最可控但工程要求最高,OpenAI 最省心但控制感弱,DeepSeek 价差最猛但依赖链路透明。
二、为什么 Coding Agent 天生不容易命中
如果你直连 API,写个固定 prompt 很容易命中。但 Coding Agent 没那么简单——它已经不是一个 agent,而是一整套调度系统:要管工具、压缩上下文、切模式、拉子任务。
麻烦就出在这里:请求前缀里塞满了工具定义、项目规则、权限模式、MCP schema、git 状态、历史消息……该长期稳定的和每轮都变的,混在了一起。
四个反复出问题的环节:
1. 动态 system prompt。当前时间、工作目录、git 状态、权限模式、token 预算——这些每轮都可能变。一旦混进靠前的 system prompt,就把原本稳定的前缀拖成了动态前缀。
2. tool schema。MCP server 一多,工具定义又长又容易变,直接扰动前缀。
3. 中途切换模型。缓存是按模型隔离的,切了模型缓存完全不通用。你以为「复杂任务用强模型、简单任务用便宜模型」能省钱,实际是——在强模型上攒的 10 万 Token 稳定缓存,切到便宜模型后要全额重建,重建成本远大于模型差价。
4. 自动压缩与子代理。compaction 能降总 token,但会改写 messages 前缀、打断缓存链;subagent 各有自己的 prompt、工具与规则,不必然共享主会话缓存,反而可能让 token 烧得更快。
此外,还有一个容易被忽略的坑:统计口径。很多框架统一成简单格式,只留一个总输入 token,cache_creation与cache_read全被抹平,你根本看不到缓存到底有没有生效。
三、六条实操技巧(来自 Claude Code 团队的经验)
技巧一:静态前置,动态后置。
这是最基础、也最重要的一条。Claude Code 的请求是分层的:
| 层 | 内容 | 缓存粒度 |
|---|---|---|
| 最外层 | 静态 system 提示词 + 工具定义 | 全局缓存(跨会话共享) |
| 第二层 | 项目规则(CLAUDE.md) | 项目内缓存 |
| 第三层 | 会话上下文 | 会话内缓存 |
| 末尾 | 对话消息 | 不缓存(每轮都变) |
越稳定的越往前放,越易变的越往后放。cache_control断点要打在稳定内容之后,这样后面的用户问题随便变,前面那段前缀仍能复用。
技巧二:动态信息走「消息」,别改系统提示词。
「现在是星期三」「用户刚改了某个文件」这类信息,直觉上是直接改 system 提示词。但这么做代价极大——整段缓存直接失效。
正确做法:把动态信息作为一条消息追加在对话末尾。Claude Code 的做法是在用户消息里加一个标签注入这类信息,前缀完全没动,缓存自然保住。
由此得出一条黄金规范:长期规则写进项目文件(CLAUDE.md),临时变化全部进对话消息。
技巧三:会话中途不要切模型。
理由前面已经说了——缓存按模型隔离。真想用不同模型,正确姿势是用子代理(subagent)做侧活:主线模型不动、长前缀不动,子代理独立跑自己的缓存。
技巧四:工具定义延迟加载。
工具一多,光工具定义就吃掉大量 token,而且经常变动。Claude Code 的解法是「延迟加载」:默认只发轻量的工具存根(工具名 +defer_loading: true标记),模型真正需要时再通过一个「工具搜索」工具去发现完整定义。
这样即使你装了个新插件,也不会把整个前缀打翻。
技巧五:让子代理共享父级缓存前缀。
多代理不是简单「多发几份请求」。让子代理复用主会话已建立的稳定前缀,能让「派 5 个子 agent 并行干活、账单却几乎只算一份」成为可能——这也是 Claude Code 架构里最值得学的设计之一。
技巧六:上下文压缩时,复用同一前缀。
这一条特别精妙。当历史太长需要压缩时,天真做法是另起一个 prompt、把历史拍平发过去——这次调用必然全部 miss。
正确做法是:复刻会话原本的[系统提示词][工具定义][历史]前缀,只在尾部追加一句「请把以上内容压缩成摘要」。于是这次摘要调用的前缀,正是上一轮刚被缓存的那一段,压缩本身也命中了缓存。
四、一张风险分级清单
把日常操作按「是否摧毁缓存」分级,执行起来最直观:
| 级别 | 操作 | 影响 |
|---|---|---|
| 🔴高危 | 中途换模型、增删工具 / 重载 MCP、改项目规则文件、装新 Skill、闲置超 TTL | 缓存几乎必废 |
| 🟡中危 | 改 thinking 开关 / 推理预算、重载插件 | 视实现而定 |
| 🟢低危 | 正常对话(只在末尾追加消息)、侧线探索走 subagent、反复读同一文件 | 基本安全(文件内容也能被复用) |
五、怎么监控:盯「写读比例」,别只看总量
Claude 场景下最该盯的是两个字段的比例:
cache_creation_input_tokens(写入)cache_read_input_tokens(读取)
判断逻辑很简单:
- 写入高、读取低→ 前缀不稳,或复用次数不够
- 读取高、普通输入低→ 稳定前缀真的被复用了
单看总 token 极易误判:输入看起来很多,但如果大部分是 cache read,实际非常便宜。
六、别忘了接入层:中转站会吃掉你的缓存红利
很多人把前缀优化做得很漂亮,最后却在接入层翻了车。
原因在于,经过中转站后,缓存信息可能直接消失——不少 OpenAI 兼容接口会把 usage 统一成简单格式,只留一个总 input token。而更麻烦的是三层「猫腻」:
- 吃差价:上游已按缓存读取的低价结算,中转站却按普通输入卖给你
- 打散路由:在多个 key、账号、区域之间轮询,同一会话的请求被分散,模型名一致不代表缓存位置一致
- 改写请求:插入自己的 system 提示词、修改 tool schema、重排 messages——你的前缀早被改了,而你在日志里根本看不到最终请求
影响有多大?算笔账就清楚了。设普通输入价为 1、缓存读取为 0.1:
| 方案 | 计算 | 实际单位成本 |
|---|---|---|
| 3 折、命中率 50% | (0.5×1 + 0.5×0.1) × 0.3 | 0.165 |
| 6 折、命中率 95% | (0.05×1 + 0.95×0.1) × 0.6 | 0.087 |
结论很反直觉:**折扣只作用在明面单价上,而命中率改变的是计费基数。**长上下文任务里,命中率差一点,价格排序就可能反过来。
所以选接入方式时,至少看三件事:
- usage 字段是否透传(最好保留供应商原始字段,能看到缓存读写明细)
- 缓存输入按什么价计费
- 同一会话是否有路由粘性
这也正是向量云在解决的问题:通过火山方舟官方 API 与独享推理接入点,让请求路由固定、缓存空间隔离——缓存不被其他用户挤占,前缀才能稳定命中,独享场景下命中率可达 70%~90%,而不是公共资源池里随波逐流的 20%~40%。
获取 API Key:https://ark.tokenrize.cn/
一句话总结:前缀稳定性管住前半段,独享接入点守住后半段,命中率才是省出来的。
七、写在最后:四条保命口诀
把全文压成四句话,可以直接贴到团队规范里:
- 静态在前、动态在后——时间戳、git 状态塞进用户消息,绝不写进 system 正文
- 要换模型就用 subagent 做侧活——主线模型不变、长前缀不动
- 临时指令写进当前对话——别去改项目规则这种长期记忆
- 压缩也要复用前缀——别另起 prompt 把历史拍平
最后回到那句话:**在 Coding Agent 里,缓存不是优化项,而是架构地基。**你越早把它当成设计的第一性原理,后面要还的技术债就越少。