标题:动态工具会破坏提示缓存吗? | Mohammed Reschreiter

HN AI Best Practices 2026-08-31T19:56:27.522089

简短回答:不会。

动态工具激活并不会摧毁提供商侧的提示缓存。在一项对 OpenAI、Google Gemini 和 OpenRouter 上 10,186 个助手回合的审计中,工具切换仅在 2.4% 到 3.4% 的回合中造成缓存未命中,同时避免了 7120 万未使用的 schema token,并将平均回合成本降低了 32.5%。

超过 82.5% 的提示缓存未命中源于常规的多文件读取、上下文压缩,以及云服务商 5 分钟空闲超时,而非工具切换。

这项研究是我上一篇架构深度分析《How I Cut 80%+ of Context Overhead in My Coding Agent》的实证后续。


我在发布 AI 编程代理中的动态工具激活架构时,Hacker News 上最常见的反驳意见立刻出现了:

「动态添加工具看起来没问题,但移除工具是个糟糕的主意。切换 schema 会改变提示前缀,不断摧毁你提供商侧的提示缓存。」

从理论上看,这个反驳似乎很合理。主流大模型提供商(Anthropic、OpenAI、Google)都会缓存提示前缀。如果你修改系统提示或工具 schema,前缀哈希就会改变,模型必须以标准或更高的写入价格重新写入缓存条目。

为了验证动态工具激活在实际生产中是否真的损害提示缓存,我审计了 Pi 在 OpenAI、Google Gemini 和 OpenRouter 上的 93 次多轮编程会话、10,186 个助手回合。

以下是实证遥测数据揭示的结果。


数据集

我分析了 11 天内在日常工程工作流中启用动态工具激活的所有交互式编程会话。


1. 代理实际多久调用一次待机工具?

「缓存摧毁」担忧的核心假设是:代理每两个回合就会不停地切换工具。

但实践中,软件开发遵循严格的幂律分布(即少数工具占据绝大多数调用,多数工具很少被用到)。

在总计 11,461 次工具执行中:

核心工具 (bash, read, edit, write):  ██████████████████████████████ 94.28%
备用工具 (browser, loops, image):     █ 5.72%

智能体(agent)超过 94% 的工作量都花在读取文件、编辑文本和运行 shell 命令上。由于这 4 个默认工具始终留在提示词(prompt)里,工具结构(schema)前缀保持 100% 一致,在整个会话期间有 85% 到 90% 以上的时间都能命中缓存。


2. 真正导致缓存未命中的原因是什么?

在全部 10,186 次助手回合中,共出现 2,030 次缓存未命中或零缓存事件(总未命中率 19.93%,整体缓存命中率 80.08%)。

我把每一次缓存未命中都按技术触发原因做了分类:

10,186 次回合中提示词缓存未命中的根因分析

图 1:10,186 次助手回合中缓存未命中的根因分布。超过 82.5% 的未命中源于日常文件操作和云端 TTL(超时机制),与工具切换无关。

未命中数据的关键结论:

  1. 工具激活只占回合数的 3.47%。在所有提供商和模型上,切换工具、或工具因超过 2 回合 TTL 而过期,只在 354 个回合中触发了缓存切换。其余 96.53% 的回合完全没有出现与工具相关的缓存中断。

  2. 在 OpenAI 模型上,工具相关的未命中率为 2.40%。在 4,164 个 OpenAI 回合里,工具激活恰好制造了 100 次缓存切换。

  3. 超过 82.5% 的缓存未命中与工具无关。缓存频繁失效的主要元凶,是往提示词里塞入 2,000 行的文件内容,这会让上下文边界发生偏移,并迫使会话压缩(session compaction)。


3. 为什么各家提供商的缓存命中率不一样?

对比不同提供商的命中率,差异实际上来自各家缓存引擎的架构设计:

各提供商和模型的提示词缓存命中率

图 2:各模型和提供商端点的实际缓存命中率。

Google Gemini 的 32k 阈值

Google Gemini 的 78.8% 命中率乍一看低于 OpenAI 的 86.5%。查阅 Google Cloud 文档后,原因就很清楚了:

在短会话或早期回合中,只要上下文不足 32k token,Gemini 就会按设计返回 cacheRead: 0。在 772 次 Gemini 缓存未命中里,有 471 次(61.0%)仅仅是因为提示词还没达到 Google 的 32k 阈值。一旦会话超过 32k token,Gemini 的缓存命中率就攀升到 90% 以上。


4. 经济账:缓存写入与工具结构拖拽的成本

提示词缓存读取虽然有大幅折扣,但并非免费。OpenAI 对缓存读取的收费是基础输入价格的 10% 到 50%(GPT-5.6 / GPT-4o 上约为每百万 token 0.30 到 1.25 美元)。

当你在 Codex 这类环境里保持 79 个静态工具常驻时,每一轮都要多发送约 12,000 个工具结构 token。

以下是我在 4,164 个 OpenAI 回合中得到的精确账目:

拖拽 79 个静态工具,意味着每一轮、整个会话期间,都要为 12,000 个从未使用的 token 支付缓存读取费用。

通过在备用工具闲置 2 回合后将其裁剪掉,我花了大约 0.80 美元进行 100 次缓存重建,从而节省了 62.45 美元的缓存读取费用。投资回报率约为 77 倍。

在所有模型和会话中,我的平均单回合成本从 0.0609 美元降至 0.0411 美元(账单直接减少 32.5%)。


如何在你的智能体里最大化缓存稳定性

基于这 10,000 回合的实测数据,维护提示词缓存稳定性有以下三条规则:

1. 把高频搜索工具提升为核心工具

最初 web_searchweb_fetch 都放在备用列表里。由于网络搜索占全部工具激活次数的 36%,把这两个工具提升到默认工具集后,只多花了约 350 个 token,就消除了 36 次缓存切换。

把重量级引擎(browser_use、多智能体循环、图像生成器)留在备用列表,而把轻量、高频的查询类工具放在核心列表。

2. 强制提示词内容按确定性排序

备用工具列表在拼入提示词之前,应按字母序排序(standby.sort())。如果工具发现机制在多次运行中返回的顺序不一致,字节串就会变化,从而破坏前缀匹配。

3. 用有边界读取代替整文件导入

大文件读取导致了 70% 的缓存未命中。在项目说明里加一条简单的规范,就能阻止智能体把 2,000 行的文件整个塞进上下文:

先用 rg -n 定位目标行,再用带 offsetlimit(100 到 200 行)参数的 read 读取,而不要一次性把大文件全部载入上下文。


结论

查看原文