如果你在为一个会跑几十轮、上下文动辄十万 token 的编码智能体付账,我建议你先确认一件事:它每一轮发出去的那一大段里,有多少是服务端已经算过、本来可以直接拿出来用的。我核对了这一批材料之后的判断是,真正决定账单的不是模型价格,而是你的运行环境在那段已经发出去的文本上动了几个字。这篇稿子不做成本治理总览,也不做推理引擎横评,只讲一件事:缓存破损——前缀缓存本来能免掉的重复计算,是怎么被一层自己人打碎的,以及你能怎么把它测出来。
一次编码智能体会话的输入,习惯上被当成一个数字看:输入 token 单价乘以总量。这个看法在单轮问答里差得不多,在长会话里差得很远。
我按这批材料把它拆成三段:
第三段的存在感有多低,看两个数字就够。TurnCost 在 600 条公开轨迹上测出,98.6% 的输入 token 是由前缀缓存供给的,因此按平价输入价格去估算单步成本,平均会高估约七倍。另一家按实测能耗计费的推理云服务商在 2026 年 10 月公布的自家数据显示,实验室里 539 次后续请求中有 88% 是纯追加,剩下 65 次全部发生了缓存破损,而每一次的成因都追溯到了同一件事:调用方改写了它自己此前已经发出去的文本。
需要先把口径说清楚:前一个数字来自预印本,后一组来自服务商对自家流量的自述分析,我按作者口径转述,未做独立复现。
把这三段摆在一起,会得到一张和直觉不太一样的表。
| 这一段是什么 | 命中缓存时的代价 | 决定它的人 | 受影响的特征 |
|---|---|---|---|
| 历史前缀(历史对话 + 系统提示) | 复用已算过的键值,只付极小代价 | 调用方是否追加写、是否中途改文本 | 会话越深,一次破损越贵 |
| 本轮新增(用户消息 + 工具返回) | 真实新增的预填充 | 轮次数量与观测裁剪 | 轮数而不是单轮体积主导成本 |
| 工具定义(工具清单与参数结构) | 每轮都在前缀里,随工具集大小线性增长 | 装了多少工具、是否全量装载 | 工具越多,前缀越长、越容易被改动 |
2610.15093(TurnCost) 的做法是把循环本身当成被研究对象:改代码、跑工具、看结果、决定下一步,这个循环怎么设计,就决定了钱花在哪。作者分析了 600 条公开发布的编码智能体轨迹,横跨两种 scaffold 与两个模型。
结论里有两条和常见做法直接冲突。第一条是观测体积:中位观测只有 118 到 286 个 token,而那些被反复拿来论证「必须压缩工具返回」的大型构建日志,出现在第 99 百分位。也就是说,为极端情况做的优化,在绝大多数轮次上没得可压。第二条更关键:轮次数量解释了 84% 的对数轨迹成本方差,而平均观测大小只解释 4%。最贵的那批轨迹,恰好是轮次最多、单轮观测最小的那批。
我把这两条合起来读,得到的行动方向是「减轮次」而不是「压观测」。这也解释了为什么缓存破损在账单上比模型单价更值得盯:前者动的倍数,后者动的是比例。作者也推导并验证了模型下发的盈亏平衡条件,结论是下发在半数设定里反而更贵,落点接近预测边界。这条结论我没在生产环境跑过,但它至少提示:把简单轮次丢给便宜模型不是无条件的省钱动作。
缓存破损的判定条件其实只有一条:精确前缀。一旦调用方改写了已经发出去的任何一处,服务端就会从第一个差异位置开始重新计算,改得越靠前,重算得越多。
值得留意的是,触发源全是「合理的产品功能」。上面那家推理云在实验室里用录制代理跑了四种开源编码智能体,脚本化的会话覆盖规划、子智能体、重启、MCP 连接与压缩。结果是:空闲、重启与子智能体一个都没引发破损,65 次破损全部来自调用方改动已发文本。作者特别点出的两个例子是,某个调用方把计划模式提醒挂在用户消息上、下一轮又移除,导致每轮都要多读 330 到 2340 个 token;另一个调用方把已重读文件的早期读取替换成「已作废」标记。还有一个细节我记了下来:切换精力档位时,首个字节差异出现在第 8 个 token。
系统提示里的日期是另一个典型——它一天变一次,而它之后的所有内容都会因此失效。
为什么前面那个 98.6% 值得单独拎出来说?因为它改变的是计价基准,而不是某个优化技巧。
在近乎理想的缓存条件下,输入 token 里只有极小一部分是真正新算的。若按平价输入价格去估算一步的开销,平均会高估约七倍。这意味着很多团队在做「换个便宜模型」「压一压提示词」这类决策时,用的分母本身就是错的:真正的大头在轮次与前缀是否被保住,而不在每轮塞进去多少字。
还有一个旁证来自 2610.22289:作者把「什么时候重置环境」这个决策从模型挪到一个脚本化控制器上,在不改动任何评测代码的前提下,恢复了部分专能配置的优势;同一篇还报告,额外增加教程类经验反而让表现下降,而性能提升伴随着更高的 token 成本。我把这两条读成同一方向的证据——少而稳定的输入,比多而频繁变动的输入更划算。
我在自己的判断里给这条证据很高权重,还有一个原因:它给出了一个闭式的判据,而不是一句经验。下发是否划算,取决于缓存命中率、两个模型的价格比与新增 token 的规模,作者把它写成了可判定的条件并做了验证。这类判据的价值在于,你可以把自己的数字代进去,而不是照抄结论。
这是缓存破损的触发点清单,也是我最想让你带走的一张表。左列是触发源,中列是触发条件,右列是我按上面那份分析整理的建议动作。需要说明的是,这组数字来自服务商对自家实验室与生产流量的自述,我未核到第三方独立复现,标注为供参考。
| 触发源 | 触发条件 | 观测到的数字 | 建议动作 |
|---|---|---|---|
| 系统提示里的日期 | 每天变化一次 | 一处改动使其后全部重算 | 移出系统提示,或放到最末 |
| 计划模式提醒 | 挂在用户消息上,下一轮移除 | 每轮多读 330 到 2340 个 token | 改为独立消息(2.x 已改) |
| 精力档位切换 | 会话中途切换 | 首个字节差异出现在第 8 个 token | 会话内固定档位 |
| 已重读文件的早期读取 | 替换为「已作废」标记 | 前缀中段改写触发重算 | 追加而不是替换 |
| 工具列表变更 | 会话中途连接或断开服务器 | 前缀中段改写触发重算 | 会话内固定工具集 |
| 新增技能与压缩 | 中途装载或触发压缩 | 前缀改写位置不可预测 | 会话开始一次性装载 |
深度是另一个量级的问题。同一份分析里,超过 128k 上下文之后,每一千个轮次里约有 3 个会重读超过一半的前缀,平均每次重读约 230k token,占该深度全部重读 token 的 75%;而该深度下一个普通轮次的中位新增只有约 370 个 token。换算下来,一次这样的深度重读,预填充量约等于 600 个普通轮次。能耗侧的对照是:在约 50k 提示词、输出长度相近的同等请求上,几乎未缓存的请求约为全缓存请求的两倍能耗,在某个模型上是约 2.5 倍。
我在这份数据里最看重的一行是破损频率而不是未缓存比例:未经缓存的输入在不同调用方之间落在 1.6% 到 11.1% 区间,但按轮次算,采用追加日志与固定最小系统提示的那个调用方约为每一百轮一次,另外两个约为每一百轮三次。作者自己也提醒,生产数据里混入了缓存淘汰与负载效应,实验室数据来自脚本化会话而不是真实用户提示词。
如果说前缀是被「改」坏的,工具定义则是被「装」坏的。
2026 年 10 月 17 日建库的一个开源项目 aicodeking/leanrea,用一个约 8 KB 的技能文件去替代 morluto/rea 那套 207 个工具的 MCP 服务器。技能文件做的事很朴素:告诉智能体面对哪类目标直接跑哪条命令行工具,比如 otool、nm、go version 后接参数、jadx、sqlite3,中间不加一层服务器。
按作者自述的对照,全量装载时,207 个工具的定义会占用 400.7k 个 token,一次「回复 OK」就要约 1.60 美元;换成那个技能文件是 34.5k 个 token、约 0.09 美元。端到端的三臂对照如下,均为作者自述,四个任务、三次重复、一个模型、一台机器:
| 配置 | 总耗时 | 成本 | 轮次 | token | 任务得分 |
|---|---|---|---|---|---|
| 8 KB 技能文件 | 388 秒 | 2.17 美元 | 55 | 2.40 M | 74 / 75 |
| 无技能、无服务器 | 479 秒 | 2.21 美元 | 81 | 3.11 M | 67 / 75 |
| 207 工具服务器加技能 | 627 秒 | 3.36 美元 | 124 | 5.93 M | 75 / 75 |
我读这张表的顺序和作者不一样。最该被看到的不是「技能打败了服务器」,而是第二行:什么都不加的裸模型,成本 2.21 美元,和加了技能文件的 2.17 美元几乎持平。换句话说,省下来的钱主要来自拆掉了中间层,而模型本来就认得这些命令行工具。作者也明确写了,服务器是在对其最有利的条件下被测的——默认延后加载工具定义的话,只有全量装载的智能体才会付那 400k。
这组数字的局限同样明显:三次重复、一个模型、一台机器,重型路径未被触发,我把它当方向性提示而不是选型结论。
把视线从调用方挪到推理栈,复用本身也有代价。我按代价类型把它分成三笔。
存储侧的笔账。 2610.21241(Range) 指出前缀恢复已经被推到了关键路径上:同一份 6 GiB 的键值状态,作为 192 个对象恢复需要 2.1 秒,作为 6144 个对象需要 3.0 秒,逐层加载更慢。字节一点没变,变的是对象数——存储栈的每一层,查找、分配、I/O 提交、GPU 投递、写入、索引,都按逻辑对象收费。作者据此重写了存储引擎,在 32 倍对象数区间内把中位首字延迟稳定在 1.79 到 1.80 秒,比前缀已经驻留显存的情况只慢 70 毫秒。
精度侧的笔账。 缓存复用会漏掉全量预填充本该算的跨片段注意力。2610.18925(CacheSmith) 把选择性重算拆成预热、探测、修补三段,配一个按延迟预算配置的规划器,在四种基准上把质量门控的延迟达标率最高提升了 27.5%。这条对我的启发是:重算不是越少越好,而是要在质量与延迟的权衡曲线上可配置。
安全侧的笔账。 复用把「别人算过的中间状态」变成了共享面。2610.22873(R2ECAP) 给出一个纯黑盒的投毒路径:只通过对话界面植入两条推理轨迹,前一条把模型导向对抗目标,后一条携带这个目标;即便前一条与其缓存条目被丢弃,被保留下来的那个缓存里仍能残留对抗影响。作者在三个开源权重模型上报告最高 79% 的攻击成功率,在九个资源受限设定里有八个优于一个白盒基线,在一个真实的推理轨迹检索系统里是 46%,而流行提示注入检测器只抓到 1% 的留存响应。
我把这三笔账放在一起,不是为了得出「别复用」这种结论,而是想说清楚:缓存破损只是一个最容易被观察到的表象,底下是复用在成本、质量、安全三个方向上同时要付的代价。
下面两段都是示意,不是可直接安装的库。我按上面几份材料的共同口径整理,作用是把「前缀有没有被改」变成一条可追溯的结构化记录。
def cache_probe(prev_prefix, cur_prefix): limit = min(len(prev_prefix), len(cur_prefix)) first_diff = limit for i in range(limit): if prev_prefix[i] != cur_prefix[i]: first_diff = i break recomputed = len(cur_prefix) - first_diff half = max(len(prev_prefix) // 2, 1) return { "prefix_len": len(cur_prefix), "first_diff": first_diff, "recompute_ratio": recomputed / max(len(cur_prefix), 1), "deep_break": first_diff in range(half), }
我给这四个字段的用途是:prefix_len 看会话深度,first_diff 定位被改动的位置,recompute_ratio 估算重算占比,deep_break 是我按「改动位置在前半段就值得排查」这个粗略规则设的信号。这个阈值没有理论依据,是我自己的经验取值,你在自己的负载上大概率需要重设。
import hashlib def fingerprint(parts): body = "\n".join(sorted(parts)) return hashlib.sha256(body.encode("utf-8")).hexdigest()[:16] def assert_stable(before, after): a, b = fingerprint(before), fingerprint(after) if a != b: raise RuntimeError("prefix changed mid-session: " + a + " to " + b)
这段的价值在于把「会话内不能变的东西」变成断言:系统提示、工具清单、档位设置、已装载的技能,都进这个指纹。一旦中途变了就抛错,而不是等到月末账单出来才发现。缓存破损最麻烦的地方就是它不报错,只表现为慢一点和贵一点,等你从聚合指标上看见它时,钱已经付完了。
我把上面的材料收敛成六步,按代价从低到高排:
这个顺序的好处是每一步都能独立产出结论,不必等全部做完才有收益。代价是它只覆盖调用方这一侧,服务端与调度层的问题不在其中。
不是。压缩是主动缩短前缀,目的是省空间;缓存破损是前缀被意外改写,后果是被迫重算。两者会互相影响——压缩本身就会改写前缀从而触发重算——但关注点不同:一个在省,一个在别改。
不能。它来自 600 条公开轨迹、两种 scaffold 与两个模型的测量。不同调用方的前缀稳定性差别很大,上面那份生产分析里未缓存输入就落在 1.6% 到 11.1% 的区间里。建议的用法是先自己测一轮,再决定优化方向。
按 leanrea 的对照,更准确的说法是:省下来的钱主要来自去掉中间层,而模型本来就认得这些命令行工具——裸模型对照组的成本与技能文件组几乎持平。所以先问「这一层是不是非加不可」,再问「换成什么」。
会,而且这是被量化过的。R2ECAP 在只通过对话界面植入的条件下,于三个开源权重模型上报告最高 79% 的攻击成功率。这不意味着不能复用,而是意味着跨请求、跨租户复用推理缓存时,需要把缓存条目当作可被外部影响的状态来处理。
一个可能的原因是压错了对象。TurnCost 测出中位观测只有 118 到 286 个 token,而轮次数量解释了 84% 的对数轨迹成本方差。若你的成本主要来自轮次与前缀重算,压单轮观测的边际收益会很小。
会,这是真实取舍。固定工具集意味着会话内不能动态挂新服务器;代价是不能随时扩展能力,收益是前缀稳定。建议按场景分:短会话允许动态,长会话固定。
加前缀指纹断言。它成本最低,且是后面所有分析的前提:没有「前缀什么时候变了」这条记录,你事后无法区分慢是重算还是负载,其余优化只能靠猜。