窗口做到一百万 token,Agent 还是越跑越笨

2026-10-04T08:00:00+08:00 | 10分钟阅读 | 更新于 2026-10-04T08:00:00+08:00

@
窗口做到一百万 token,Agent 还是越跑越笨

凌晨两点的终端里,你在第 1 轮给 Agent 定过一条规矩:不要改公开接口。第 45 轮,它把公开接口改了,并且很有把握地告诉你任务完成了。

模型没有变笨。变的是它的上下文。

Anthropic 在《Effective context engineering for AI agents》里把这件事讲得很平:上下文是有限资源,边际收益递减,工程目标是找到「能让目标产出概率最大化的一组最小高信号 token」。这句话在 2025 年听起来像一句正确的废话。到了 2026 年,它变成了一堆测量数据支撑起来的结论。

这篇文章想说的也是这一件事:上下文窗口的大小是厂商的军备竞赛,而上下文的预算纪律才是工程上的分水岭。

一、窗口填满之前,可靠性就已经开始垮

「反正有一百万 token,全塞进去」是过去两年最常见的偷懒。它错得比大多数人以为的更早。

Chroma 的 Context Rot 报告测了 18 个主流模型,包括 GPT-4.1、Claude 4、Gemini 2.5 和 Qwen3,结论是模型并不会均匀地使用自己的上下文:随着输入变长,表现越来越不可靠,而且是零碎地、不均匀地下滑,不是一个整齐的悬崖。报告还顺手拆掉了业界最爱引用的那个基准:Needle in a Haystack 本质上只是词面匹配,一把针插进无关文本里让你捞出来,它测不出真实任务里那种需要语义判断的检索。

更扎心的是 EMNLP 2025 的《Context Length Alone Hurts LLM Performance Despite Perfect Retrieval》。研究者在 5 个开源和闭源模型上做实验,发现即使模型能完美检索到全部相关信息,性能照样随输入变长下滑 13.9% 到 85%。把无关 token 换成极少量干扰的空白,下滑依旧;把所有无关内容全部遮掉、强迫模型只看相关 token,下滑依旧;把证据直接摆在问题前面,还是下滑。作者给出的缓解办法朴素到有点出乎意料:让模型先把检索到的证据复述一遍,再回答问题,等于把一个长上下文任务改写成短上下文任务,在 RULER 上让 GPT-4o 涨了最多 4 个点。

还有一条更细的线。arXiv 上一篇研究指出,除了长度和位置,还有第三个被忽视的轴叫「词汇密度」,也就是上下文里引入新信息的速率。八个模型在稀疏上下文里接近满分,换到密度更高的基准上直接掉到 60% 分以下;降低密度就能把性能找回来。也就是说,同样长度的上下文,信息越密,有效窗口越小。

最后是 GAIR 团队那篇《Diagnosing and Mitigating Context Rot in Long-horizon Search》,它给这种下滑起了一个准确的名字:提前终止。在长上下文里,模型会在远未用尽窗口的情况下就放弃,或者给出一个自己都不确定的错误答案,而这种放弃的比例和上下文长度正相关。这篇论文把上下文管理重新定义成一种测试时扩展手段:多花一点推理成本去降低放弃率,让模型多探索几步,就能换来性能。

把这些放在一起看,有一条判断我觉得值得写死:这不是等下一代模型能顺手修掉的 bug。注意力机制要为 n 个 token 算 n² 对关系,双倍上下文就是四倍关系负担;长序列在训练数据里本来就比短序列稀少。窗口大小是模型能力的上限,不是你该开的工作点。

二、真正的成本中心是工具输出,不是对话

一旦接受「上下文要省着用」,下一个问题就很实际:到底是谁在吃上下文。

直觉答案是对话历史。工程现实里,答案通常是工具输出。

Anthropic 的官方 Cookbook 给过一个很具体的例子:一个研究型 Agent 要读八篇各约 40K token 的综述文档,光工具结果的体量就有 320K token,早就进入上下文衰减会发生作用的区间,而其中绝大部分内容,Agent 需要时完全可以重读一次。工具定义本身也不便宜,一个复杂的 JSON schema 就能吃掉 500 多个 token;如果挂了 90 个工具,用户还没开口,5 万 token 就已经没了。

有位工程师写过自己的翻车经历:他给 Agent 挂了 23 个工具「为了灵活」,结果 Agent 把大量注意力花在四个功能重叠的搜索工具之间做选择。Anthropic 给出的红线很直接:如果一个人类工程师都无法明确说出某种情况下该用哪个工具,就不要指望 Agent 能做对。工具应该自包含、抗错误、功能最小重叠,像写得好的函数一样。

这部分最省事也最见效的一招,是把工具输出「去壳」。用完之后能重新取到的原始载荷(整个 API 响应、整份文件内容、200 行测试输出)属于死重,清掉,只留下结论和那次调用的记录。实测里这一步单独就能把每轮成本砍掉约 38%,而且没有可观测的记忆力损失,因为需要的时候再调一次工具就行。

三、三种压缩原语,管的是三件不同的事

Anthropic 把上下文管理拆成三件可以被区分开的事,理解它们的差别,比记住名词重要。

  • 压缩(compaction):上下文快满了,就把整段历史总结一遍,用摘要重新开始。它是整条记录级别的操作,用户消息、助手消息、工具调用、工具结果全被压平进摘要,代价是一次推理(要跑一个摘要模型),而且有损。官方文档明确写着:丢失细节是预期行为,不是边缘情况。
  • 工具结果清理(tool-result clearing):只针对工具结果做手术,把旧的结果体替换成一个短占位符,工具调用记录本身保留,让模型仍然知道「我调过这个工具」。它是子记录级别的操作,零推理成本,而且可以做到无损,因为内容可以重新取回。
  • 记忆(memory / 结构化笔记):让 Agent 把笔记写到上下文窗口之外的外部存储,需要时再读回来。它管的是跨会话的东西,成本是文件读写,质量取决于 Agent 自己记笔记的纪律。

三种不是互相替代,而是各自对应不同的瓶颈。Anthropic 的官方组合演示里,工具结果清理和压缩是可以在同一次请求里叠着用的,记忆单独接。官方给出过一组内部数字:把上下文编辑和记忆工具组合起来,长任务上的 token 用量减少了 84%,另一个 100 轮任务的性能提升 39 个点。Claude Code 的生产做法是压缩后的历史加上最近触碰的五个文件。

我的判断是:这三件事的取舍不该被讲成流派之争。日志化的推理过程用压缩,可重取的工具结果用清理,跨会话的事实用记忆。今天绝大多数 Agent 的上下文问题,其实只有第三种最缺,也最没人做。

四、2026 年的反直觉教训:缓存命中时,不压缩反而更便宜

如果这个领域只有「压缩省 token」这一条结论,那它不值得单独写一篇。2026 年的实验把这条结论推翻了一半。

Towards AI 团队在八月份公开了一组基于自己生产环境 AI 家教系统的评测。他们本来的默认设置里塞了一套看起来完全合理的压缩策略,结果在内存探针上只拿到 38% 分,成本是「什么都不做」的两倍,而一个盲测裁判还给它的答案打了「不错」。这三件事同时成立,正好说明了为什么这件事不能靠肉眼判断。

他们的核心发现是:在现代 prompt 缓存之下,保留完整历史在所有被测策略里同时赢下了成本、延迟和记忆召回三项。原因不复杂,也和缓存的机制直接相关:总结会重写被缓存的前缀,于是你为了省 token 做的那次压缩,反而要为重新计算前面全部内容付出全价。真正省钱的压缩是「便宜的那一层」,把每一次工具输出限制在一个稳定的大小,这一招在零可观测记忆损失的前提下把每轮成本降了 38%,因为它缩小了上下文,却没有动缓存依赖的前缀。

所以他们给出的结论不是「压缩已死」,而是「压缩是有条件的」。用之前先给你的约束起个名字:

  • 窗口根本装不下,指向分块或分层加载;
  • 被缓存输入的单价超过大约每百万 token 0.55 美元,指向压缩或缓存策略调整;
  • 实测到质量衰退,指向真正的上下文管理。

三个约束指向三种不同的解法,前提是你真的测过自己的系统,而不是照抄别人的默认值。这条我觉得是整篇里最容易被忽略的:成本模型变了,结论就得重算一遍。

五、压缩的代价,是把约束弄丢

压缩最隐蔽的伤害不是丢了细节,而是丢掉约束。

有一个现象叫目标漂移。它不会在某一个戏剧性时刻发生,而是一轮一轮地漏。你在第 2 轮说的「保持公开 API 不变」,被总结成「更新了 API」,再被总结成什么都没有;到第 25 轮,Agent 面不改色地把公开 API 改了,而且它觉得自己一直遵守着当初那个目标。

对应的解法也不复杂:钉一条常驻的进度笔记,写成结构化的交接单,而不是日记:

GOAL: 给 HTTP 客户端加带退避的重试逻辑,配测试
DONE: 在 http_client.py 加了三次退避包装;写了 test_retry
LEFT: 还剩一个失败用例,test_auth 在过期 token 场景下挂了
CONSTRAINT: 不要破坏旧的 token 路径,否则会拖垮 staging

分界线在于:凡是「一旦弄错就会让构建失败」的约束,它就是一条事实,不是脚注。剩下的那些东西(diff、目录列表、200 行测试输出)留在代码库里,一次重读就能拿到。把细节丢掉和把细节交接出去,是两件不同的事。

位置也要注意。信息放在上下文最前面和最后面时,模型利用得最好,埋在中间时最差。所以任务放顶部,当前状态钉在底部,让模型在回答问题前最后读到的是它,那一大堆历史放在中间,可用但不承重。

社区里对自动压缩的怀疑也来自这里:一份摘要保存错误的能力,和保存事实的能力一样强,它压掉的只是啰嗦,不是错误。所以更多人的做法是把自动压缩关掉,改用子 Agent 隔离、主动裁剪和回退,把压缩当成最后手段。

六、今天就能落地的一套最小做法

把上面这些压成一张清单,都是单个工程团队这周就能动手的:

  1. 精简工具集:功能重叠的工具合并掉,一个定义明确的工具永远好过两个含糊的工具。
  2. 工具输出去壳:能重取的原始载荷用完即清,只留结论和调用记录。
  3. 轻标识符,不搬数据:上下文里留文件路径、行号、URL,真正的内容按需拉取。
  4. 钉一条进度笔记:GOAL / DONE / LEFT / CONSTRAINT,并让它出现在每一轮窗口的末尾。
  5. 跨会话的事实放进外部存储,不要指望窗口替你记住。
  6. 大任务甩给子 Agent,只回一份 1000 到 2000 token 的摘要,把脏活关在它自己的窗口里。
  7. 阈值先往下压再往上调:从 50% 就开始考虑整理,而不是等到 90%,但一定要配合自己的测试调整。
  8. 用你自己的任务测压缩:通用的长上下文基准分数,不告诉你你的压缩提示词有没有丢任务真正依赖的那个细节。

结语

上下文窗口的大小是营销轴,上下文纪律才是工程分水岭。

过去两年,行业在比谁装得下更多;接下来要分出高下的,是谁知道每一轮该往窗口里放什么。这个转向对做产品的人反而不算坏消息,因为它不需要更大的算力预算,只需要把你自己的任务、自己的成本结构、自己真实的召回率测清楚。

如果只带走一句:把上下文当成一份需要每天对账的预算,而不是一个可以随便塞满的硬盘。前者会让你改架构,后者只会让你买更大的模型。

参考来源

  • Anthropic, Effective context engineering for AI agents:https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
  • Anthropic Cookbook, Context engineering: memory, compaction, and tool clearing:https://platform.claude.com/cookbook/tool-use-context-engineering-context-engineering-tools
  • Chroma, Context Rot: How Increasing Input Tokens Impacts LLM Performance:https://research.trychroma.com/context-rot
  • Du et al., Context Length Alone Hurts LLM Performance Despite Perfect Retrieval (EMNLP 2025 Findings):https://aclanthology.org/2025.findings-emnlp.1264/
  • Dense Contexts Are Hard Contexts: Lexical Density Limits Effective Context in LLMs (arXiv:2606.06203):https://arxiv.org/pdf/2606.06203v1
  • Diagnosing and Mitigating Context Rot in Long-horizon Search (arXiv:2606.29718):https://arxiv.org/html/2606.29718
  • Louis-François Bouchard, Context Engineering in 2026: Why We Stopped Compacting Our Agent’s Context:https://www.louisbouchard.ai/context-engineering-2026/
Me

Cut out summary from your post content here.

The remaining content of your post.