Agent 上下文越用越堵?6 种压缩策略,从实验数据到生产落地
做过 Agent 的人大概都遇到过这一幕:任务跑到第五轮,上下文窗口满了,任务直接失败。不是模型不够聪明,是对话历史里堆了几十万字符的工具输出——搜索结果、网页正文、代码片段,绝大多数在读完那一刻就成了占地方的噪声。
但你有没有好奇过:Claude Code、ChatGPT、Deep Research 这些主流 Agent,到底是怎么处理这个问题的?大多数人对压缩的认知停留在两句口诀:一句是"上下文超过阈值就自动压缩",另一句是"把脏活累活拆给子 Agent,只回传结论"。可真要追问下去——超过阈值之后具体做了什么?摘要怎么写的,丢了什么、留了什么?除了压缩和子 Agent,还有没有别的招?能说清楚的人就不多了。
这些问题的答案,藏在一本开源书里:《AI Agents in Depth》第二章「上下文工程」。作者用一组对照实验把压缩这件事拆得很彻底:六种压缩策略逐一对测,token 消耗、压缩率、任务成功率摆在一起对比;又给了一套生产环境的分层压缩方案,外加一张"什么能删、什么绝不能动"的保留优先级清单。这篇把核心结论提炼给你:压缩到底在做什么、有哪些策略、怎么压才不会破坏 KV Cache,以及为什么子 Agent 隔离比压缩更聪明。
为什么要压缩:不只是窗口不够用
压缩上下文有两个动机,第一个人人都懂,第二个才是重点。
动机一:长度和成本。 上下文窗口有限,128K token 看着不小,但一次网页搜索就可能返回几万字符。书中实验里,Agent 追踪一位 OpenAI 联创的职业状态,做了 7 次搜索,累计拿到约 36.7 万字符——到第 5 次迭代就把 128K 窗口撑爆了,任务失败。token 多,还意味着 API 账单和推理延迟一起涨。
动机二:总结后的知识,比原始信息更好用。 这是更深的一层。作者反复强调一个观点:上下文学习本质是「检索」而不是「推理」。注意力机制擅长从几万 token 里捞出相关片段,但不擅长在一次前向传播里做统计归纳。
书里有个生动的例子:上下文里有 100 个笼子的巡查记录,90 只黑猫、10 只白猫。你问模型"笼子 37 里是什么猫",它秒回;你问"黑猫白猫各多少只",它就得开思维链从头数一遍,而且每次被问到都要重数。但如果你提前在上下文里写一句"当前统计:黑猫 90,白猫 10",它就只是检索一个现成结论。
这引出一个配套概念:上下文腐化(Context Rot)。窗口没满,但 Agent 突然找不到关键信息了,反复纠结一个早已解决的问题。溢出是"装不下了",腐化是"装得下但找不到了",后者更隐蔽——表面正常,决策质量却在悄悄下滑。
所以压缩的设计原则是:别指望模型从冗长上下文里自己提炼,主动把提炼好的高密度知识喂给它。
压缩与 KV Cache:看似矛盾,实则互补
前面章节强调过,系统提示词和工具定义是"静态前缀",必须保持字节级不变,才能命中 KV Cache——模型每生成一个 token 都要看前文,缓存住前文的中间结果,新请求只算新增部分。
那压缩不是要改上下文中间的内容吗?不矛盾,关键在于压缩发生在两次 API 调用之间,由框架对消息列表做预处理:
- System Prompt 和工具定义永远不动,缓存持续命中;
- 压缩对象是对话历史里的 tool results——用摘要替换原始输出时,替换位置之后的缓存会失效,之前的仍然有效。
这是个有意识的权衡:不压,上下文爆掉任务失败;压了,损失部分缓存但换回可控的长度和更高的信息密度。因此压缩的频次要克制——接近阈值时批量压缩,而不是每轮都压。
六种压缩策略的实测对比
书中实验 2-10 用 Kimi K3(刻意把上下文预算限制在 128K 以触发压缩)实现了六种策略,下图是各策略的 Token 用量对比,数据很有参考价值:

无压缩就不用说了,几次搜索就耗尽窗口(166,043 token,超过 128K 限制,任务失败)。个体摘要给每个搜索结果独立写 2-3 段摘要,问题是碎片化——多个页面重复描述同一事件,白白浪费空间。组合摘要把所有结果合并成一份综合摘要,好一些,但输入超长时必须截断,末尾信息可能丢。
上下文感知压缩是这轮实验的亮点。它的核心创新:把"当前的查询意图"和"已积累的信息"纳入压缩决策。压缩提示里带上 Given the search query: {query} 和 Current context: {context},让模型知道该保什么。实测一次把 147,877 字符压到 1,963 字符(约 1.3%),创始人的姓名和职位变动这些关键信息一点没丢。这背后是个重要洞察:多步骤任务的不同阶段需要的信息密度不同——初期要广收集,中期要核验事实,后期要综合整合。压缩策略跟着阶段走,价值最大化。
带引用的上下文感知压缩在智能压缩基础上给每条事实附上来源 URL,让有损压缩和无损索引结合——内容压掉了,但随时可以回溯原始信息。
自适应窗口化换了个思路:前期空间充足就不急着压,直到 token 数超过窗口 80%(128K 即 102,400)才触发,然后一次性批量压缩所有未标记的工具结果,并用 [COMPRESSED] 标记防止重复处理。总 token 偏高,但前几轮保留了完整原始信息,给初期探索最大灵活性。
生产环境:五层分层压缩
单个策略不够,成熟系统把多种策略组合成分层机制。书中以 Claude Code 为参照,列出五个层次:
- 工具结果预算控制:大体积工具输出落盘,模型只看摘要预览;替换决策一旦做出就冻结,保证缓存一致性;
- 噪声直接删除:低价值内容直接移除,不做摘要——给噪声做摘要就是浪费 token;
- API 层微压缩:用 API 的上下文编辑能力,让服务端从前缀移除指定工具结果,本地消息不动。适合上下文即将溢出、反正要付出一次缓存重建代价的场景;
- 归档式摘要:逐轮做结构化摘要,像 git log 那样保留每轮独立记录(而不是 git squash 合并成一条),保住对话的逻辑脉络;
- 全量压缩:LLM 驱动的最后手段,分两阶段——先压会话记忆,不行再全量压缩,并配熔断器。为什么需要熔断?生产数据表明大量会话会困在"反复压缩失败"的死循环里,熔断避免在这些会话上持续烧钱。
四条设计原则和一份保留优先级清单
作者提炼了四条原则:信息价值非均匀分布(关键决策点 > 支撑性证据 > 冗余噪声)、语义完整性(“Sutskever 于 2024 年 5 月离开 OpenAI” 不能压成 “Sutskever 离开”)、任务相关性(同样内容在不同任务下应压出不同结果)、压缩即理解(有效的压缩需要接近主模型的语义理解能力,形成"模型调用模型"的递归架构)。
生产级系统建议显式定义保留优先级:
- 架构决策和关键约束:不得摘要
- 已修改文件列表和关键变更记录:完整保留
- 验证状态(pass/fail):必须保留
- 未解决的 TODO 和回滚笔记:必须保留
- 工具输出:可以删除,只留 pass/fail 结论
比压缩更聪明:隔离
最后这个思路值得单独说。压缩是信息已经进入上下文之后做减法——有损、还要额外花一次 LLM 调用。更釜底抽薪的办法是:让大体积的中间信息根本不进主上下文。
这就是子 Agent 上下文隔离。主 Agent 把"在代码库里大范围搜索"这类会产生海量中间内容的任务,委派给独立的子 Agent;子 Agent 在自己的上下文里完成探索,只回传几百 token 的结论性摘要(“函数位于 src/payment/callbacks.py 的 handle_callback,另有两处调用点”)。中间那几万 token 随子 Agent 的上下文一起被丢弃,主 Agent 的 KV Cache 前缀完全不受影响。
代价是子 Agent 看不到主 Agent 的完整上下文,任务描述必须自包含、目标明确——这又回到了上下文工程的核心命题:上下文的质量决定能力上限,对子 Agent 同样成立。Claude Code 的 Task 工具、各类 Deep Research 系统的检索子 Agent,都是这个模式的生产实现。
写在最后
把这套东西串起来看,主线是清晰的:显式地管理信息,而不是让模型在堆积如山的原始记录里自己捞。压缩是其中一环——在保留决策、约束、失败记录和来源的前提下,把历史信息压成高密度知识;隔离则更进一步,让噪声从源头就不进上下文。
如果你的 Agent 也经常跑到一半"失忆"或者被长历史拖慢,建议从两件事做起:一是给历史工具输出设一个压缩阈值,接近窗口 80% 时批量压缩,并显式声明保留优先级;二是把会产生海量中间结果的任务拆给子 Agent 做。这两步的投入产出比,通常比换更大的模型高得多。
本文基于开源书籍《AI Agents in Depth》(bojieli.github.io/ai-agent-book)第二章「上下文工程」整理,实验数据与结论均引自该书实验 2-10 与生产实践章节。