Skip to content

第 7 章:上下文为什么总会失控

本章目标:解释上下文膨胀是怎样发生的,为什么压缩、裁剪与保真是 Agent 系统绕不过去的工程问题。
本章对应总纲:docs/ebook-outline.md 中“第 7 章正文写作提纲(2026-03-31 归档)”。


7.1 为什么上下文问题不是“大模型时代已经解决的小事”

这一章先回答四个词:

  • inflation:上下文不断膨胀
  • compression:把旧信息压成更高密度表示
  • trimming:裁掉不该继续携带的信息
  • fidelity:压缩后关键事实不能失真

很多人会觉得:

  • 现在窗口都很大了
  • 上下文长度越来越长
  • 能塞更多内容进去

所以似乎上下文管理已经不是问题。

这判断很天真。

因为 Agent 一旦开始真实执行任务,它面对的不是一两段问答,而是持续增长的信息流:

  • 用户不断追加要求
  • 工具不断返回结果
  • 文件内容不断被读取
  • 计划不断变化
  • 错误不断引出新错误

于是问题很快从“能不能装下”变成:

哪些信息现在必须看,哪些可以压缩,哪些应该丢掉,哪些绝不能丢。

这不是窗口大小能单独解决的。


7.2 上下文为什么天然会膨胀

只要任务进入闭环运行,上下文膨胀几乎就是必然的。

7.2.1 因为环境信息会持续流入

每一次读取文件、搜索结果、测试输出、用户回复,都会把新信息带进来。

7.2.2 因为历史决策也会留下痕迹

系统不仅要看环境,还要记得:

  • 之前试过什么
  • 哪条路径失败了
  • 哪个假设已经被证伪
  • 当前为什么选择这条路

7.2.3 因为任务边界会动态变化

用户可能中途补条件,环境也可能中途变。

比如一开始只是修一个报错,后来发现:

  • 它牵涉到类型定义
  • 又牵涉到调用链
  • 再牵涉到测试和兼容性

于是任务本身就在变大。

所以从系统视角看,上下文膨胀不是偶发现象,而是闭环任务的自然副作用。


7.3 上下文失控后,系统会怎么坏

上下文问题最麻烦的一点,是它不会立刻爆炸,而是会慢慢把系统拖钝。

常见症状有:

7.3.1 重点漂移

模型开始盯着不重要的信息打转,反而忽略当前最关键的问题。

7.3.2 历史污染当前判断

前几轮已经过时的中间推测,还残留在上下文里,继续影响现在的动作选择。

7.3.3 重复劳动

因为信息太多又太乱,系统反而没法快速抓住“已经做过什么”,于是开始重复读、重复搜、重复试。

7.3.4 关键约束被淹没

最危险的情况不是信息少,而是重要约束被大量噪音埋掉了。

比如:

  • 用户明确说过不要超范围修改
  • 某接口必须保持兼容
  • 某高风险动作需要确认

这些一旦被埋掉,后面就容易出事故。


7.4 压缩不是缩短文字,而是重建可继续运行的表示

7.4.1 为什么“摘要一下”远远不够

很多人把上下文管理理解成:

  • 聊天太长了,做个 summary

这当然比什么都不做好,但远远不够。

因为 Agent 需要的不是一份好看的会议纪要,而是一份还能继续驱动动作的中间表示。

一个有用的压缩结果,至少要保留:

  • 当前目标
  • 已完成动作
  • 已失败路径
  • 当前未解决问题
  • 风险边界和约束
  • 下一轮最相关的信息入口

如果这些没保住,那压缩就只是把问题写短了,不是把系统救活了。

所以压缩不是单纯做减法,而是:

把低价值细节扔掉,把高价值结构提炼出来。

这才叫可继续运行的压缩。


7.5 裁剪:不是所有历史都值得继续带着走

上下文处理除了压缩,还有一个更硬的动作:裁剪。

7.5.1 为什么必须裁剪

因为有些信息不是“需要变短”,而是“根本不该继续留着”。

比如:

  • 已经证伪的旧推测
  • 不再相关的大段搜索结果
  • 只对前一轮有价值的细节日志
  • 已经完成阶段里的重复描述

这些内容如果一直留着,只会继续污染当前判断。

7.5.2 裁剪最难的地方是什么

最难的不是删,而是判断:

  • 这段信息真的没用了,还是只是暂时没用?
  • 现在删掉会不会导致后面再次走错路?
  • 哪些细节应该进入状态层,而不是继续留在上下文里?

所以裁剪从来不是简单的 token 清理,而是一种信息价值判断。


7.6 保真:压缩和裁剪之后,什么绝不能丢

讲上下文管理,最容易被忽略的一层就是保真。

很多系统不是不会压缩,而是压缩完以后把关键事实弄丢了。

7.6.1 最不该丢的通常是什么

通常包括:

  • 当前真正目标
  • 用户给出的硬约束
  • 已验证失败的路径
  • 高风险边界
  • 当前等待条件
  • 还未解决的核心问题

7.6.2 为什么“语义差不多”往往不够

有些信息一旦压缩得太抽象,就会失真。

比如:

  • “不要改 API 行为” 被压成 “注意兼容性”
  • “只能改这两个文件” 被压成 “尽量少改”
  • “不要运行 destructive 命令” 被压成 “谨慎操作”

这类压缩看似保留了意思,实际上边界已经变松了。

Agent 一旦在这些地方失真,后果通常不是文风变差,而是动作出错。

所以保真不是锦上添花,而是动作安全性的基础。


7.7 为什么上下文管理不能只靠模型自己“自然理解”

很多系统喜欢把上下文问题继续甩给模型:

  • 反正模型会读
  • 反正模型会总结
  • 反正模型自己能抓重点

这还是老毛病:把结构问题丢给模型硬扛。

模型当然可以帮助压缩和整理,但:

  • 什么该保留
  • 什么该裁剪
  • 什么必须结构化进入状态层
  • 什么要升级成长期记忆

这些都应该是系统级设计问题,而不是全靠模型临场发挥。

如果没有这些设计,模型每轮都只能重新猜“哪些重要”。这很不稳。


7.8 上下文、状态、记忆三层在这里是怎么配合的

上一章刚拆清三层,这一章就能看到它们为什么必须协同。

上下文层负责:

  • 给当前判断提供最近、最相关的信息

状态层负责:

  • 把“任务走到哪了”结构化保存下来
  • 避免系统从大段历史里反推阶段信息

记忆层负责:

  • 留住那些未来还值得复用的长期事实
  • 不让长期规则被压缩流程顺手丢掉

这三层配合之后,系统才不会把所有信息管理压力都扔进当前上下文。

如果三层不分,最后结果一定是:

  • 当前上下文越来越肥
  • 状态越来越模糊
  • 长期信息越来越脏

7.9 用 Claude Code 看一个现实中的上下文治理样本

Claude Code 这类系统很适合作为现实样本,因为它天然面对长链路任务:

  • 读代码
  • 改代码
  • 跑检查
  • 继续修
  • 跟用户来回确认
  • 还可能调用子 Agent

这种任务非常容易把上下文拖长。

但当前项目真正值得学的,不只是“任务会变长”,而是它没有把所有信息都硬塞进同一层。前面已经能从系统结构里看到几种明确分工:

  • plugins/README.md:48 把入口、执行角色、知识封装、生命周期挂点、外部能力接入拆成不同目录
  • examples/settings/settings-strict.json:1 把当前运行允许与不允许的动作边界单独落成配置
  • 当前系统又把长期信息、任务推进、即时消息分成记忆、状态、上下文三种时间尺度

这背后其实就是上下文治理,而不是“让模型自己多记一点”。

如果把这些线索压成设计规则,会更清楚:

  • 不属于当前轮直接判断的信息,不要继续塞在上下文里
  • 运行边界要单独落盘,不要让模型每轮重新猜这次能做什么
  • 长期信息要升级成记忆,阶段位置要升级成状态,别全挤在消息历史里
  • 上下文压缩的目标不是留住所有细节,而是留住还能继续跑的结构

所以现实里的 Agent 系统要跑稳,靠的不是“更长窗口”,而是把不同信息放回它们各自该在的层里。这才叫上下文治理。


7.10 一个好上下文系统应该追求什么

如果把目标压缩成几句话,一个好的上下文系统至少应该做到:

  1. 当前相关信息足够可见
  2. 旧信息不会持续污染当前判断
  3. 关键约束在压缩后仍然保真
  4. 任务位置不需要靠聊天记录反推
  5. 长期可复用信息不会在压缩时丢失

换句话说,它追求的不是“记得最多”,而是:

让系统在长链路任务里仍然能稳着做对当前最重要的事。


7.11 本章小结

这一章真正想讲清楚的,是上下文问题并不是模型窗口扩展后自动消失的小麻烦,而是 Agent 系统的长期工程负担。

你现在应该记住六件事:

  1. 上下文膨胀是闭环任务的自然副作用,不是偶发现象。
  2. 上下文失控后,系统会重点漂移、重复劳动、约束丢失。
  3. 压缩不是简单摘要,而是重建一份可继续运行的表示。
  4. 裁剪不是删 token,而是做信息价值判断。
  5. 保真要求关键目标、约束和失败路径不能在压缩中失真。
  6. 成熟 Agent 依赖的不是更长上下文,而是更强的上下文治理。

下一章我们继续进入 Agent 的另一块核心地基:规划。不是那种写给人看的漂亮计划,而是系统怎样决定下一步、何时回退、何时停下、何时请求人类介入。