Skip to content

缓存是什么、如何控制

为什么 Agent 离不开缓存

LLM API 是无状态的:每一轮请求都要把完整的对话历史重新发送、重新计算一遍。编程 Agent 一个任务动辄上百轮工具调用,意味着开头那几万 token 的系统提示、工具定义、文件内容要被重复处理上百次。

Prompt Caching(提示缓存) 解决的就是这个问题:服务端把已经算过的前缀的内部状态(KV cache)存下来,下一轮请求如果前缀完全一致,就直接复用,不必重算。

效果(以 Anthropic API 为例):

类型价格(相对基础输入价)延迟
普通输入 token正常
缓存写入(首次)1.25×(5 分钟 TTL)/ 2×(1 小时 TTL)正常
缓存读取(命中)0.1×,一折大幅降低首 token 延迟

一个长会话里 90% 以上的输入 token 都可以是缓存命中——这正是 Claude Code、Codex CLI 能以可接受的成本运行长任务的基础。OpenAI API 也有对应机制(automatic prompt caching,前缀 ≥1024 token 自动生效,命中打五折/部分模型更低),原理相同。

缓存的关键性质:前缀匹配

缓存只匹配完全一致的前缀。请求内容按固定顺序参与哈希:

text
tools(工具定义)→ system(系统提示)→ messages(对话历史)
────────────────────────────────────────────▶ 位置越靠前,越应该稳定

规则只有一条,但推论很多:

  • 前缀哪怕变了一个字节,从那个位置往后的缓存全部失效,需要全额重建;
  • tools 排在最前——中途增删任何一个工具定义,整个缓存作废(这也是工具爆炸的隐性成本之一);
  • 对话是"追加式"的就天然缓存友好:旧消息不动,只在末尾加新内容,每轮只有增量需要计算。

缓存的控制:cache_control 断点

Anthropic API 的缓存是显式控制的:在内容块上标 cache_control,告诉服务端"缓存到这里为止的所有前缀":

python
import anthropic

client = anthropic.Anthropic()
resp = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "你是代码审查助手。以下是项目编码规范:\n" + long_style_guide,
            "cache_control": {"type": "ephemeral"},   # ← 断点:缓存 tools + 到此为止的 system
        }
    ],
    messages=[{"role": "user", "content": "审查这个 PR ..."}],
)

要点:

  • 一个请求最多可放 4 个断点,可分别标在工具定义末尾、系统提示末尾、对话历史末尾等层级上;
  • 默认 TTL 为 5 分钟,每次命中会刷新;可用 "cache_control": {"type": "ephemeral", "ttl": "1h"} 换 1 小时 TTL(写入价更高,适合低频但重复的场景);
  • 最小长度门槛(多数模型 1024 token,Haiku 类为 2048/4096),太短的前缀不会被缓存;
  • 响应里的 usage 字段可以验证效果:cache_creation_input_tokens(本轮写入)、cache_read_input_tokens(本轮命中)。接了新系统后先看这两个数,命中为 0 说明前缀被你弄变了。

在 Claude Code / Codex 里需要手动控制吗?

不需要。Claude Code、Codex CLI 这类官方 Agent 已经自动管理缓存断点。你要做的不是"开启缓存",而是不要破坏它——这正是下一篇避免反复重建缓存的主题。

一个算术题:缓存能省多少

假设系统提示 + 工具定义 + CLAUDE.md 共 30K token,任务跑了 50 轮:

  • 无缓存:30K × 50 轮 = 150 万 token 全价输入;
  • 有缓存:首轮 30K × 1.25(写入)+ 后续 49 轮 × 30K × 0.1(命中)≈ 18.4 万 token 等效费用,约为前者的 12%,且每轮首 token 延迟显著下降。

上下文越大(尤其 1M 模式),这笔账越悬殊——1M 前缀重建一次的成本,足够缓存命中跑几十轮。

缓存不是万能的

  • 缓存只降输入成本,输出 token 照常计费;
  • TTL 过期(默认 5 分钟无访问)后需要重新写入——长时间挂起的会话回来第一轮总是慢一些、贵一些;
  • 缓存按账号隔离,不同 API key/组织之间不共享;
  • 它不能替代上下文管理:窗口塞满导致的质量下降,缓存救不了。

AI Coding Guideline — 面向 Claude Code / Codex 等 AI 编程工具的实践指南