你有没有发现,Claude Code用久了,有时候响应很快,有时候却慢得像在思考人生?这往往跟"缓存命中率"有关——缓存命中了,秒回;没命中,得重新计算。

今天咱们聊聊Claude Code的七个"缓存优化秘籍",看它是怎么把缓存命中率玩到极致的。

缓存优化的核心思路

缓存优化的本质是:减少变化,保持稳定

想象一下,你去饭店点菜:

  • 缓存命中:服务员记得你爱吃什么,直接下单
  • 缓存未命中:每次都要重新问你喜欢什么

API缓存也一样。每次请求都要发一大段"系统提示词+工具说明"给服务器。如果这段内容变了,服务器就得重新处理,费时费钱。

所以优化的方向是:让这段内容尽量不变,或者变化的影响最小

秘籍一:日期记忆化——跨午夜不失效

有个问题困扰了很多AI应用:午夜跨天

假设你在23:59问了AI一个问题,系统提示词里写着"今天是2026-04-01"。然后在00:01又问了一个,日期变成了"2026-04-02"。

就这一个字符的变化,导致整个系统提示词的缓存失效——约11,000 tokens要重新计算。

Claude Code的解决方案:记忆化日期

getSessionStartDate = 记住第一次获取的日期,以后永远用这个

这样即使过了午夜,系统提示词里的日期还是"昨天",缓存不会失效。

那AI怎么知道"今天"变了?Claude Code会在消息尾部追加新日期。尾部变化不影响前缀缓存。

这就像你跟服务员说:“我每次都点一样的菜”,只是今天加了个甜点——主菜不用重新介绍。

秘籍二:月度粒度——从每天变到每月变

系统提示词解决了,但工具提示词也需要时间信息。如果用完整日期(2026-04-01),每天都会变。

解决方案:只用月份(April 2026)。

变化频率从每天降到每月,30倍的稳定性提升。

这就像你办了一张月卡,不用每天买票。

两种时间精度的分工:

  • 系统提示词:精确到日,但记忆化(每会话一次)
  • 工具提示词:精确到月(每月一次)

秘籍三:Agent列表从工具描述移到消息附件

这是影响最大的一个优化——消除了**10.2%**的全量缓存重建成本。

问题在哪?AgentTool的描述里列出了所有可用Agent(包括MCP服务器提供的)。但这个列表是动态的:

  • MCP服务器异步连接
  • 插件刷新
  • 权限模式变化

每次列表变化,AgentTool的Schema就变了,导致整个工具Schema缓存失效。

解决方案:把动态列表从工具描述中移出,改为消息附件

工具描述变成静态的,只描述功能;可用Agent列表作为附件追加在消息尾部。

这就像:

  • 以前:菜单上印着"今日特供取决于厨师心情"
  • 现在:菜单固定,服务员口头告诉你今天的特供

菜单不变,缓存稳定;特供信息放尾部,不影响前缀。

秘籍四:技能列表预算——1%上限控制

SkillTool也面临类似问题:技能列表动态变化。

解决方案:严格控制预算,最多占上下文窗口的1%

对于200K窗口,就是8,000字符。如果列表超长,就截断。

这样做有两个好处:

  1. 限制工具描述大小,减少字节匹配的难度
  2. 预算满了新技能就不加,列表不变,缓存不破

这就像你的衣柜:满了就不买新衣服,保持整洁。

秘籍五:$TMPDIR占位符——消除用户差异

BashTool的提示词里需要告诉AI临时目录在哪。通常是/private/tmp/claude-{UID}/,不同用户UID不同。

这意味着:不同用户看到不同的提示词,无法共享全局缓存。

解决方案:$TMPDIR占位符替代具体路径

Claude Code的沙箱环境会设置$TMPDIR变量,AI用$TMPDIR引用临时目录效果一样。

但所有用户看到的提示词都相同——都是$TMPDIR——可以共享缓存。

这就像:

  • 以前:菜单上印着"本店地址:北京市朝阳区xxx号"(每个分店印不同的地址)
  • 现在:菜单上印着"本店地址:见门店招牌"(所有分店菜单一样)

秘籍六:条件段落省略——宁可不说,不要说了又删

系统提示词中有些段落是条件性的:某个功能开启时加一段说明。

问题是:如果这个条件在会话中途变化(比如远程配置更新),段落出现/消失会改变提示词,缓存中断。

解决方案:宁可不说,不要说了又删

具体做法:

  • 如果不重要,干脆总包含或总不包含
  • 如果必须条件包含,放在动态区域(不参与全局缓存)
  • 用附件机制替代内联条件

这就像你承诺朋友:“能来就来,不确定就别答应”——比"答应后又反悔"好。

秘籍七:工具Schema缓存——会话级锁定

工具Schema的生成涉及多个运行时决策:

  • GrowthBook功能开关
  • 工具的动态描述
  • MCP工具的Schema

如果每次请求都重新生成,GrowthBook的任何变化都会导致Schema变化。

解决方案:会话级缓存

TOOL_SCHEMA_CACHE = new Map()

第一次请求:生成Schema,存入缓存
后续请求:直接用缓存,不再重新生成

这样即使GrowthBook中途刷新,Schema也不会变。

这就像你第一次去餐厅,仔细看菜单;之后再去,直接点熟悉的菜。

有个细节:StructuredOutput工具的名称固定,但不同调用传入不同的Schema。所以缓存键不能只用名称,还要包含Schema内容。

曾经有个bug:只用名称缓存,导致不同工作流用了错误的Schema,错误率从5.4%飙升到51%。

七个秘籍的共同本质

回顾这些优化,可以提炼出一个决策流程:

发现动态内容
必须在前缀中?
    ↓否→ 移到消息尾部/附件
    ↓是
能消除差异?
    ↓是→ 使用占位符/标准化
    ↓否
能降低变化频率?
    ↓是→ 记忆化/降低精度/会话缓存
    ↓否
能限制变化幅度?
    ↓是→ 预算控制/条件省略
    ↓否
标记为动态区域(不参与全局缓存)

四个核心原则:

1. 把动态内容推向请求尾部

越靠前的内容,变化破坏性越大。所以:

  • 日期记忆化锁定系统提示词
  • Agent列表移到消息附件
  • 条件段落确保前缀不抖动

2. 降低变化频率

如果必须在前缀中,降低变化频率:

  • 日期从每天变到每月
  • 技能列表用预算控制
  • Schema缓存从每请求变到每会话

3. 消除用户维度差异

全局缓存要求所有用户看到相同前缀:

  • $TMPDIR占位符消除UID差异
  • 日期记忆化消除时区差异

4. 先测量,再优化

每个优化都来自数据:

  • 10.2%成本来自Agent列表变化
  • 77%工具变化是单个Schema变化
  • GrowthBook翻转导致中断

没有监控,这些优化不会被发现。

实战:如何提升自己的缓存命中率

理解这些模式,你可以这样优化自己的AI应用:

1. 审计系统提示词

找出其中的动态内容:

  • 日期/时间 → 记忆化或降低精度
  • 用户名/路径 → 用占位符
  • 配置值 → 移到动态区域或附件

2. 锁定工具Schema

工具定义在会话内应该保持不变。如果必须动态改变:

  • 考虑用消息附件替代
  • 使用会话级缓存
  • 延迟加载MCP工具

3. 监控cache_read_input_tokens

这是判断缓存是否工作的唯一指标:

  • 如果持续下降,说明有缓存中断
  • 结合日志找出变化源
  • 应用相应的优化模式

4. 理解前缀顺序

cache_control断点之前的内容变化会废弃该断点的缓存。构建请求时:

  • 最稳定的内容放最前面
  • 动态内容放后面或尾部

常见陷阱

陷阱原因解决方案
系统提示词嵌入时间戳每次请求都变记忆化
动态工具列表MCP连接变化附件机制
用户特定路径不同用户不同环境变量占位符
Feature flag影响Schema远程配置刷新会话级缓存
频繁切换模型模型是缓存键的一部分固定模型选择

总结

缓存优化是Claude Code降本增效的关键手段:

  • 七个秘籍:日期记忆化、月度粒度、Agent列表附件化、技能预算、$TMPDIR占位符、条件省略、Schema缓存
  • 核心思路:减少变化,保持稳定
  • 四个原则:推向后缀、降低频率、消除差异、数据驱动
  • 实战要点:审计提示词、锁定Schema、监控指标、理解前缀

这就像经营一家餐厅:

  • 菜单稳定,客人点菜快(缓存命中)
  • 特供信息口头告知,不影响菜单(附件机制)
  • 每日食材新鲜,但菜单不换(记忆化)
  • 用数据优化,什么菜受欢迎(测量驱动)

理解这些模式,你就能:

  • 诊断自己的AI应用缓存问题
  • 应用相应的优化策略
  • 显著降低API成本

下篇咱们聊聊权限系统——给AI装上"安全刹车"。