AI agent 一旦进入真实流量,缓存几乎必然会被提上日程。因为很多成本和延迟问题都能通过缓存缓解:检索结果可以复用,分类结果可以复用,文档摘要可以复用,某些工具查询结果也可以复用。
但缓存也是最容易制造“看起来对,实际上早就过期或越权”的地方。AI agent 的缓存难点不是怎么命中,而是:命中了以后,还能不能信。
建议先配合 AI agent 工具结果标准化、AI agent 成本控制与预算治理、AI agent Workspace 状态分层 和 AI agent 数据脱敏实践 一起看。
先给结论:缓存至少分 4 层
| 层级 | 缓什么 |
|---|---|
| prompt prep cache | 稳定上下文摘要、系统规则展开结果 |
| retrieval cache | 检索命中、重排结果、文档片段 |
| tool result cache | 只读工具查询结果 |
| final answer cache | 可复用的最终答案或中间摘要 |
不同层的失效条件完全不同。把它们混成一个“cache”目录,后面一定解释不清。
一、先判断“能不能缓存”,再判断“值不值得缓存”
不是所有内容都适合缓存。一个简单判断表:
| 内容 | 是否适合缓存 | 原因 |
|---|---|---|
| 固定规则摘要 | 适合 | 变化少,复用高 |
| 只读配置查询 | 适合 | 结果稳定 |
| 用户私有实时数据 | 谨慎 | 受权限和时间影响 |
| 高个性化最终回答 | 通常不适合 | 命中风险高 |
| 外发前结果 | 不适合 | 风险高,需实时确认 |
缓存前先问一句:命中后如果错了,代价是什么?
更工程化一点的做法,是在“要不要缓存”之前再加一道 admission policy,也就是缓存准入规则。常见判断包括:
- 当前结果是否涉及高风险写入前判断
- 当前结果是否依赖强时效业务状态
- 当前结果是否带有高度个体化权限上下文
- 当前结果是否足够昂贵,值得承担一致性成本
这样缓存就不是“默认开,再慢慢排除”,而是“先定义谁有资格进入缓存”。
二、缓存 key 不能只看输入文本
AI agent 缓存最容易错在 key 设计过于简单。一个更稳的 key 通常要包含:
- task type
- normalized input
- user / tenant scope
- prompt version
- tool version 或 retrieval index version
- permission scope
例如:
cacheKey = taskType + normalizedInput + promptVersion + tenantId + permissionScope + indexVersion
如果缺少 permissionScope,你可能把 A 用户能看的数据返回给 B 用户。缺少 promptVersion,你可能在新策略下继续用旧答案。
如果系统里已经有 schemaVersion、policyBundleVersion、toolSetVersion 这类运行时版本,最好也直接进 key 或 invalidation token。否则缓存层会变成系统里唯一一个“不知道当前协议版本”的地方。
三、Retrieval cache 过期的不只是时间,还有索引版本
很多人给检索缓存只加 TTL,例如 10 分钟、1 小时。但对知识库型 agent,更重要的失效因素常常是:
- 文档更新了
- 重排策略改了
- embedding 模型换了
- 索引重建了
所以 retrieval cache 需要绑定版本信息:
{
"indexVersion": "kb_v20260507",
"embeddingModel": "embed_v3",
"rerankerVersion": "rerank_v2"
}
只靠时间失效,会让“结构变了但时间没到”的脏缓存继续存在。
很多团队到这里会引入一个统一的 invalidation token,把时间、版本和权限变化收敛成一个可比较值。例如:
{
"cacheDomain": "retrieval",
"token": "kb_v20260507:embed_v3:rerank_v2:tenant_001"
}
当任一关键因素变化时,不需要逐条扫缓存,只要让 token 变掉,旧结果自然失效。
四、Tool result cache 最怕忽略权限和状态变化
只读工具结果虽然适合缓存,但要注意两类风险:
- 结果依赖用户权限
- 结果依赖业务状态
例如“当前审批状态”这种查询,如果目标对象刚被别人更新,缓存就会立即失真。对这种状态性很强的数据,TTL 应该很短,甚至直接不缓存。
更稳的处理是把状态性查询分为两类:
| 类型 | 建议 |
|---|---|
| 读后只用于展示 | 可短 TTL 缓存 |
| 读后会驱动写入或外发 | 命中缓存后必须再校验最新状态 |
这样团队就不会把“读缓存”误当成“拿到了最新事实”。
五、Final answer cache 要比前面三层更保守
最终答案一旦缓存,最容易出现“看起来复用了智能结果,实际上复用了错误上下文”。
更适合缓存的不是完整最终答案,而是:
- 稳定结构化摘要
- 模板化说明片段
- 中间 evidence summary
如果一定要缓存最终答案,至少要满足:
- 输入高度标准化
- 权限边界明确
- prompt 版本稳定
- 风险等级低
除此之外,final answer cache 最好明确是“直接命中复用”还是“作为草稿候选”。后者通常更安全,因为系统还能在命中后做额外检查,而不是把旧答案原样发给用户。
六、缓存命中策略也要区分强一致和性能优先
缓存并不总只有“命中”或“失效”两种处理。很多系统会在不同层选择不同策略:
| 策略 | 适用场景 |
|---|---|
| strict miss | 状态敏感、命中后会驱动写入 |
| stale-while-revalidate | 成本高但对短暂旧值容忍的检索结果 |
| async refresh | 稳定摘要、配置型数据 |
关键不是策略多,而是要把“哪类缓存允许短暂旧值”说清楚。
七、上线后要看缓存健康指标,而不是只看命中率
命中率高不代表缓存健康。更值得看的指标是:
| 指标 | 用途 |
|---|---|
| 命中后被二次校验打回比例 | 判断缓存是否经常带来旧值 |
| 误命中权限冲突数 | 判断 key 是否缺少权限维度 |
| invalidation token 变更频率 | 判断版本变更是否过于频繁 |
| stale serve 占比 | 判断系统是否过度依赖旧值兜底 |
| 高风险路径缓存命中数 | 判断准入规则是否失守 |
如果命中率很好看,但被二次校验打回的比例持续升高,说明缓存只是把问题从前面挪到了后面。
八、失败案例:缓存命中后把旧审批状态当成最新事实
一个审批 Agent 把“当前任务状态”缓存 5 分钟,认为能减少工具调用。某次任务在第 2 分钟被人工改成 rejected,agent 第 4 分钟继续从缓存读到 pending,又执行了后续步骤。
根因不是缓存本身,而是系统把“高状态敏感数据”当成了普通只读查询。
修复后,他们做了三件事:
- 状态类查询默认不进长 TTL cache
- cache key 加 entityVersion
- 命中缓存时,如果后续动作是写入,必须再次校验最新状态
九、缓存失效 Checklist
- 是否区分 prompt prep、retrieval、tool result、final answer 四层缓存
- 是否有明确的 cache admission policy
- cache key 是否包含权限、版本和任务类型
- 是否使用 invalidation token 统一表达关键版本变化
- retrieval cache 是否绑定索引版本和 embedding 版本
- 高状态敏感数据是否避免长 TTL
- 驱动写入的缓存命中后是否再次校验最新状态
- 命中缓存后做写入前是否再次校验最新状态
- 最终答案缓存是否只用于低风险稳定任务
- 是否监控误命中权限冲突和 stale serve 占比
- 缓存清理是否和 workspace / artifact 分层一致
结语
AI agent 的缓存设计,本质上不是“怎样更快”,而是“怎样在更快的同时不误导系统”。先把缓存层次、key、权限和版本想清楚,再谈命中率,才不会把性能优化变成数据污染。
延伸阅读:


