Context Rot:长上下文不是长期记忆
用 AI 做长一点的编程任务时,很容易产生一种误会:只要上下文窗口够大,就可以放心把所有东西都塞进去。
需求说明、代码片段、测试日志、搜索结果、旧方案、会议结论、刚才的失败尝试,全都给它。模型不是能看很长吗?那它应该会记得更多,理解得更完整,最后做得更稳。
我现在越来越觉得,这个想法危险的地方在于:它把“能放下”误认为“能用好”。
长上下文确实有价值。它让模型能一次读更多材料,也让复杂任务少一些来回搬运。但长上下文不是长期记忆,更不是天然干净的工作台。很多时候,Agent 不是因为看不见信息而失败,而是因为看见了太多旧的、相似的、过期的、未经验证的信息,最后在一堆上下文里拿错了权重。
我把这种现象称为 Context Rot:上下文还在窗口里,但已经开始变质。
不是忘了,而是记住了太多不该记的东西
context window 解决的是容量问题:一次请求里最多能放多少可被模型回看的内容。Anthropic 的文档把它描述成模型生成文本时能够回看并引用的文本总量。[1]
但容量不是记忆质量。
你可以把一整张桌子铺满资料,但这不等于桌面更适合工作。桌上有当前需求,也有三轮之前废弃的方案;有刚跑出来的测试失败,也有已经被修复过的旧报错;有真正相关的文件,也有名字相似但语义不同的模块。它们都在“可见范围”里,却不应该拥有同样的地位。
这就是 Context Rot 的核心:问题不是模型完全忘了,而是上下文里的信号密度、时效性和证据身份开始下降。模型仍然能看到文字,但更难稳定判断哪些是当前事实、哪些是旧计划、哪些只是失败路径,哪些只是临时猜测。
所以它经常表现得很迷惑:明明前面已经改过方向,它后面又沿用旧方案;明明读过正确文件,它总结时却引用了相似但错误的上下文;明明用户补充了新约束,它实现时还是被早期目标牵着走。
它不是没有记忆。
它是记忆太脏。
长上下文本身也会退化
这不是纯经验感受。Lost in the Middle 研究观察到,模型处理长输入时,相关信息的位置会影响使用效果;信息放在开头或结尾通常比放在中间更容易被利用。[2]
Chroma 的 Context Rot 技术报告进一步讨论了输入变长以后模型表现的退化。他们关注的不只是简单的“针在草堆里”检索,而是更接近真实应用的情况:上下文里有干扰项、语义相似项、结构化输入和不同相似度的问题。报告的一个重要提醒是,长上下文能力不能只用“能不能找回一个明确字符串”来代表。[3]
真实的 Coding Agent 任务通常比这些实验更乱。
因为编程任务里的上下文不是一份干净文档,而是一条不断滚动的工作流。它会混入:
- 代码搜索结果
- 文件全文
- 测试日志
- 构建失败
- 网页资料
- 临时计划
- 已经废弃的假设
- 用户中途补充的新目标
- Agent 自己写过但还没有验证的解释
这些材料都可能有用,但它们的有效期不一样。测试日志可能只在定位阶段有用;旧计划一旦被推翻,就不应该继续参与实现;搜索结果如果没有打开原文验证,只能算候选线索;模型自己的总结如果没有证据,只能算假设。
一旦这些身份被混在一起,上下文就开始腐烂。
Coding Agent 里最常见的五种腐烂源
第一种是旧计划残留。
长任务一开始可能走 A 方案,后来发现不合适,改成 B 方案。但 A 方案的理由、文件路径、设计草图和半成品解释还留在对话里。后面 Agent 写代码或总结时,又把 A 方案当成有效背景拿回来用。
第二种是失败路径残留。
排障时会尝试很多假设。假设本来应该被证据淘汰,但如果没有明确标记“这条路已排除”,它会变成上下文里的幽灵状态。后续推理可能继续围着它转。
第三种是工具结果堆积。
rg 输出、测试日志、网页正文、API 响应、stack trace 都很有价值,但它们多数是短期证据。定位完成后,大段原始输出应该被压缩成“命令、结果、关键证据、可重取路径”。如果一直留在 active context 里,它们会持续占用注意力预算。
Anthropic 的 context engineering 资料也把 compaction、tool-result clearing、external memory、sub-agent/context isolation 等放在一起讨论,本质上都是在治理 active context,而不是迷信窗口容量。[4]
第四种是相似干扰项。
最危险的上下文不一定是完全无关的东西,而是“看起来相关但不是这次答案”的东西。比如相似模块、相似错误、旧版本接口、同名概念、另一个分支里的实现。它们会给模型一个很自然的错误抓手。
第五种是规则膨胀。
把所有偏好、禁忌、工具说明、写作风格和边界条件都塞进 always-on prompt,看起来很保险,实际可能稀释真正关键的规则。AGENTS.md、skill、项目文档都应该是索引和高频约束的载体,而不是百科全书。
Context Rot 的症状
日常使用里,可以从几个现象判断上下文已经不干净了。
Agent 开始重复已经否定过的方案。
它不断调用更多工具,但判断质量没有提升。工具调用越来越像是在给旧假设找理由,而不是寻找能区分假设的证据。
它读了很多文件,却引用错了文件。尤其是当仓库里有多个相似模块、相似命名、旧实现和新实现并存时,这种情况很常见。
它在总结里混入早期探索结论。明明中途已经改了方向,最后交付说明还是把旧方案、旧目标或旧报错带进来。
它开始忽略新约束。用户刚刚说了“不改这个模块”“只做本地验证”“不要动生成文件”,后面实现时却又被前面的大目标牵走。
还有一个很有意思的信号:压缩、重开任务或把当前事实整理成短摘要之后,模型表现突然变好了。
这说明问题可能不是能力不够,而是工作现场太乱。
更大的窗口不能根治它
更大的上下文窗口能推迟一部分问题,但不能消除 Context Rot。
因为 Context Rot 的核心不是“空间不够”,而是“上下文身份混乱”。窗口变大以后,旧计划、失败日志、相似干扰项和未经验证的总结也能放得更多。它们不会因为窗口变大就自动变成低权重,也不会自动被标记为过期。
所以大窗口更像一间更大的工作室。空间变大以后,确实可以放更多材料;但如果没有整理规则,它也可以更快变成仓库。
工程上真正要管理的是几件事:
- 当前任务到底是什么
- 当前阶段需要什么证据
- 哪些内容已经过期
- 哪些结论有来源
- 哪些工具结果可以重取
- 哪些规则应该常驻
- 哪些资料应该按需加载
OpenAI 的 Codex best practices 强调给 Agent 明确目标、上下文、约束和完成标准,也建议把重复出现的项目指导沉淀到 AGENTS.md,并让 Agent 通过测试、lint、review 等方式验证结果。[5] 这背后的逻辑也是一样的:好的 Agent 工作流不是让模型背更多,而是让它在每一步拿到更正确的工作现场。
怎么治理 Context Rot
第一,按阶段切上下文。
研究阶段可以宽一点,多读文件、多搜索、多列假设。计划阶段应该收窄,只留下关键事实、取舍、风险和验收方式。实现阶段更应该窄,只保留当前文件、邻近接口和确定的设计决策。验证阶段需要的是新鲜证据,而不是早期信心。
第二,压缩工具结果。
工具输出不要默认长期驻留。大段日志读完以后,应该变成:
1 | 命令:npm run generate |
这比把完整日志一直放在上下文里更有用。
第三,显式废弃旧假设。
不要只追加“现在改用 B 方案”。最好写清楚:
1 | 已废弃:A 方案,因为测试 X 证明它不能覆盖 Y 场景。 |
这能帮模型把历史状态和当前状态分开。
第四,把稳定结论外存。
如果某个结论下次还会用,就不要只留在聊天记录里。项目规则进 AGENTS.md 或文档;通用知识进 wiki;验证方式进脚本或 CI;可复用流程进 skill;一次性移交进 handoff。对话应该是临时工作台,不应该承担知识库的职责。
第五,保留证据指针,而不是保留全文。
很多内容是可重取的:文件路径、行号、命令、URL、测试名、日志路径。对模型来说,当前阶段通常不需要所有原文,只需要知道证据在哪里、结论是什么、是否仍然有效。
第六,把外部内容当证据,不当指令。
网页、issue、邮件、PDF、搜索结果都可能进入上下文,但它们不能越权改变任务规则。它们可以提供 claim,可以提供线索,可以被总结;但是否采纳,要看来源、时间、权限和当前目标。
一个简单检查清单
当一个 Agent 任务变长时,我会问这几个问题:
当前目标还能不能一句话说清楚?
当前阶段是研究、计划、实现、验证,还是沉淀?
现在窗口里最占地方的内容,还是不是当前阶段需要的?
有没有已经被否定但还没有标记废弃的方案?
有没有一大段工具输出可以压缩成摘要和指针?
关键结论有没有来源?来源是文件、命令、测试、文档,还是模型自己的猜测?
新约束有没有覆盖旧目标?旧目标是否需要明确失效?
完成判断有没有新鲜证据?
如果这些问题回答不上来,继续往上下文里塞材料通常不会让 Agent 更聪明,只会让它更容易把垃圾加工成一套看起来完整的方案。
长上下文应该被使用,而不是被迷信
我不是反对长上下文。
相反,长上下文是 AI 编程真正好用的重要原因之一。没有它,很多跨文件理解、长文档阅读、复杂需求梳理都会变得很麻烦。
但长上下文应该被管理,而不是被崇拜。
它适合承载当前任务所需的高信号材料,不适合永久保存所有历史痕迹。它适合帮助模型理解工作现场,不适合替代文档、测试、脚本、wiki 和人工判断。它适合让 Agent 少猜一点,不适合让我们把证据边界、任务边界和责任边界都交给模型自己整理。
如果说 AI 上下文工程:把正确的信息放到正确的位置 讲的是“要把正确的信息放到正确的位置”,那么 Context Rot 这篇想补上的就是另一半:
错误的位置、过期的信息和未清理的历史,本身也会变成一种输入。
Agent 的输出不是只由模型能力决定,也由它所在的工作现场决定。上下文越长,越要认真整理现场。否则它不是长期记忆,而是一张越来越乱的桌子。
参考与延伸阅读
- 本博客:AI 上下文工程:把正确的信息放到正确的位置
- 本博客:AI 事实性:让模型找到证据,而不是生成答案
- 本博客:从 Prompt 到 Skill:AI Agent 工作流的下一层抽象
- Chroma, Context Rot
- Liu et al., Lost in the Middle
- Anthropic, Effective context engineering for AI agents
- OpenAI, Codex best practices
Anthropic, Context windows。这里引用它对 context window 作为模型当前可回看文本范围的解释。 ↩︎
Nelson F. Liu et al., Lost in the Middle: How Language Models Use Long Contexts。这篇研究支持“相关信息在窗口内不等于模型会稳定利用它”的判断。 ↩︎
Kelly Hong, Anton Troynikov, Jeff Huber, Context Rot: How Increasing Input Tokens Impacts LLM Performance,Chroma Technical Report, 2025。这里引用它来支持“长输入、干扰项和任务形式会让模型表现不均匀退化”的判断。 ↩︎
Anthropic, Effective context engineering for AI agents,以及 Anthropic Cookbook, Context engineering: memory, compaction, and tool clearing。这里引用它们对 active context、compaction、tool-result clearing、external memory 和上下文隔离的工程实践。 ↩︎
OpenAI, Codex best practices。这里引用的是任务目标、项目上下文、
AGENTS.md、验证命令和 review 对 Coding Agent 工作质量的影响。 ↩︎