Claude Code 提示词缓存的核心启示

Claude Code 提示词缓存的核心启示

整理时间: 2026-02-20
来源: 群聊消息(来自 Claude Code 开发者 @trq212)
整理人: AI助手

摘要

对于 Claude Code 这种需要长时间运行、进行多次往返交互的智能体工具,提示词缓存是决定其经济成本和响应延迟可行性的核心技术。本文整理了提示词缓存的底层原理、最佳实践架构、以及复杂场景下的优化方案,为构建高效 AI Agent 提供工程实践指导。


一、核心技术原理

1.1 前缀匹配机制

特性 说明
缓存方式 前缀匹配
缓存范围 从请求起始位置到指定的 cache_control 断点
关键特性 前缀中任何细微改变,都会导致该位置之后的所有缓存失效

1.2 缓存的重要性

  • 经济成本:缓存命中 vs 未命中,成本差异巨大
  • 响应延迟:缓存命中 = 极速响应
  • 可行性:没有缓存,长会话 Agent 根本无法落地

二、最佳实践架构(从静到动)

2.1 缓存分层原则

Claude Code 的架构遵循“静态内容在前,动态内容在后”的原则:

层级 内容 缓存范围
第 1 层 全局静态系统提示词 & 工具定义 全局共享
第 2 层 项目级上下文(如 CLAUDE.md) 项目内共享
第 3 层 会话级上下文 会话内共享
第 4 层 具体对话消息记录 每次不同

2.2 排列顺序的重要性

[静态系统提示词 + 工具定义] → [项目上下文] → [会话上下文] → [对话消息]
        ↑                                    ↑
     缓存起点                            缓存终点(动态)

核心原则: 越静态的内容越靠前,越动态的内容越靠后


三、工程实践中的「反直觉」经验

3.1 状态更新:使用「系统消息」而非「修改系统提示词」

场景 错误做法 正确做法
外部状态变化 更新系统提示词(如时间改变) 使用 标签

原因: 更新系统提示词会破坏整个会话的缓存

正确做法:

# 错误 ❌
system_prompt = f"当前时间: {datetime.now()}"  # 破坏缓存!

# 正确 ✅
messages.append({
    "role": "system-reminder",
    "content": f"当前时间: {datetime.now()}"  # 不破坏缓存
})

3.2 避免中途切换模型

场景 错误做法 正确做法
会话中切换模型 从 Opus 切换到 Haiku 使用子代理交接

原因: 缓存与具体模型绑定,切换模型会导致缓存完全失效

正确做法:
- 主会话保持 Opus
- 让 Opus 生成任务交接消息给 Haiku
- Haiku 作为子代理处理简单任务
- 主会话缓存保持完整


3.3 绝对不要中途添加或移除工具

场景 错误做法 正确做法
优化工具数量 只给模型当前需要的工具 工具集保持静态

原因: 工具定义缓存在前缀中,增减工具会立刻破坏缓存

正确做法: 工具集必须在整个会话中保持不变


四、复杂场景下的缓存优化方案

4.1 规划模式的设计

需求: 进入只读模式(不修改代码)时,如何避免缓存失效?

方案: 保留所有工具,引入模式切换工具

工具 功能
EnterPlanMode 进入规划模式
ExitPlanMode 退出规划模式

实现:
- 开启规划模式时:发送系统消息 “你现在处于规划模式,只能探索代码”
- 不移除任何工具
- 缓存零破坏

额外优势: AI 可以自主决定何时进入规划模式


4.2 延迟加载解决海量工具问题

问题: 几十个 MCP 工具,全部加载太贵,中途移除破坏缓存

方案: 工具存根 + 延迟加载

# 轻量级存根(永远在缓存中)
tools = [
    {
        "name": "search_files",
        "defer_loading": True,  # 延迟加载标记
        "schema": {...}
    },
    # ... 更多存根
]

# 模型需要时,通过 ToolSearch 动态发现并加载完整 Schema

优势:
- 前缀中永远只有不变的存根
- 缓存前缀绝对稳定
- 按需加载完整工具


4.3 上下文压缩的「缓存安全分叉」

问题: 对话历史超限时,需要总结压缩

错误做法:

# 直接用新请求总结,会导致缓存完全失效 ❌
response = api.chat_completion(
    messages=[{"role": "user", "content": "请总结以上对话"}]
)
# 缓存未命中!需支付全额费用

正确方案:

步骤 操作
1 复用与主会话完全相同的系统提示词
2 复用相同的工具定义
3 复用历史消息
4 仅在末尾追加 “请进行总结”
# 正确做法 ✅
response = api.chat_completion(
    messages=[
        *system_prompt,      # 完全相同
        *tool_definitions,   # 完全相同
        *conversation_history, # 完全相同
        {"role": "user", "content": "请进行总结"}  # 追加指令
    ]
)
# 完美命中缓存!

关键: 在设计时预留”压缩缓冲区”


五、一句话总结

不要随意改变前缀,用状态机(消息和工具调用)来代替环境改变,把缓存机制当作第一性原理来设计系统。


六、核心原则汇总

原则 说明
静态在前,动态在后 系统提示词 → 项目上下文 → 会话 → 对话
前缀不可变 任何前缀改动都破坏缓存
状态用消息传递 不用修改提示词来更新状态
模型不要中途切换 用子代理代替
工具集保持静态 全程不变,模式切换用工具
压缩要复用前缀 总结时保持系统提示词和工具不变

整理备注

本文档基于 Claude Code 开发者 @trq212 的实战分享整理,包含提示词缓存的核心原理、最佳实践及复杂场景优化方案。