第 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 一个好上下文系统应该追求什么
如果把目标压缩成几句话,一个好的上下文系统至少应该做到:
- 当前相关信息足够可见
- 旧信息不会持续污染当前判断
- 关键约束在压缩后仍然保真
- 任务位置不需要靠聊天记录反推
- 长期可复用信息不会在压缩时丢失
换句话说,它追求的不是“记得最多”,而是:
让系统在长链路任务里仍然能稳着做对当前最重要的事。
7.11 本章小结
这一章真正想讲清楚的,是上下文问题并不是模型窗口扩展后自动消失的小麻烦,而是 Agent 系统的长期工程负担。
你现在应该记住六件事:
- 上下文膨胀是闭环任务的自然副作用,不是偶发现象。
- 上下文失控后,系统会重点漂移、重复劳动、约束丢失。
- 压缩不是简单摘要,而是重建一份可继续运行的表示。
- 裁剪不是删 token,而是做信息价值判断。
- 保真要求关键目标、约束和失败路径不能在压缩中失真。
- 成熟 Agent 依赖的不是更长上下文,而是更强的上下文治理。
下一章我们继续进入 Agent 的另一块核心地基:规划。不是那种写给人看的漂亮计划,而是系统怎样决定下一步、何时回退、何时停下、何时请求人类介入。