上下文压缩:为何编程Agent容易失控,聊天Agent却能聊几小时?

上下文压缩:为何编程Agent容易失控,聊天Agent却能聊几小时?

最近在做 Agent 相关开发时,发现一个很有意思的现象:同样是上下文压缩,在不同业务场景下的影响天差地别。

用 Claude Code、Codex、Cursor、Trae这类编程工具写代码,对话压缩个两三次,你就会明显感觉到它 “变笨了”—— 找不到工具、记不住文件路径、忘记之前定好的约束,甚至开始重复做已经完成的事。而日常聊天类产品,比如你跟豆包聊一下午,天南海北扯几十轮,上下文不知道被压缩了多少轮,你却几乎感觉不到明显的质量下降。

这背后不是模型能力的差距,而是两类业务对上下文信息的要求,本质上就不在一个维度上

一、先搞清楚:上下文压缩到底在做什么

上下文压缩不是简单的 “删除旧消息”。目前主流的压缩方式大致分三层:

微观清理层(Micro-compact):每次 API 调用前,静默清理过期的工具返回结果、冗余的日志输出、重复的状态信息。这一层几乎无损,成本极低。

摘要压缩层(Auto-compact):当上下文接近窗口阈值时,调用模型把历史对话重写为一段摘要,用几十到几百 token 替代几千 token 的原始对话。这是真正有损的一步。

KV Cache 层:推理引擎层面做的 token 合并、低秩压缩、量化,例如 DeepSeek 采用的 MLA(多头潜在注意力)/ HCA 机制,通过对 KV 进行低秩压缩,大幅减少了显存占用。这一层对语义损伤较小,但对精细符号有影响。

以 Claude Code 为例,它有完整的 5-7 层渐进式压缩流水线,从工具结果落盘、历史裁剪、微压缩,到最后的全量摘要,是一套 “不到万不得已不动用有损压缩” 的防御体系。但只要触发了摘要式压缩,信息损耗就不可逆转。

二、核心差异一:符号精确性 vs 语义连续性

这是最本质的区别。

编程类业务是典型的高信息密度 + 零容错符号系统。代码世界里,差一个字符就是天壤之别:
文件名 userService.tsUserService.ts 是两个文件
变量名 userIduser_id 差一个下划线,就是完全不同的标识符
函数参数从 (id: string) 变成 (userId: string),调用方全崩
文件路径 src/api/v2/handler.ts 记错一级目录,工具直接找不到文件
缩进、括号层级错一处,整个代码的语法结构直接失效

摘要式压缩的本质是语义蒸馏—— 它的底层逻辑是「丢弃细节、保留大意」,擅长留住 “这段代码在做用户鉴权” 这种宏观描述,但不擅长精确保留 validateToken(payload: JwtPayload): boolean 这种精确符号。可在代码世界里,”大意” 几乎没有实用价值:只知道 “这里有个处理用户数据的函数”,却记不住具体函数名和参数列表,Agent 根本无法完成调用。

每压缩一次,符号精度就衰减一次;多轮压缩后,具体的标识符就模糊成了 “某个验证函数”。一次关键的符号丢失,就可能直接造成语法错误或逻辑断裂,让 Agent 直接失控。

聊天类业务是低信息密度 + 高容错的语义系统。人类日常对话本身就充满语义冗余:同一件事往往会反复表述,核心信息包裹在大量寒暄、铺垫和修饰里。你和豆包聊旅行、聊美食、聊电影,压缩后只要还能记住 “用户想去日本、喜欢吃拉面、上周刚看过某部电影” 这些语义要点,对话就能继续顺畅进行。

记错几个细节?漏掉一两句无关紧要的寒暄?没关系,自然语言的模糊性天然提供了极高的容错空间,用户甚至根本察觉不到。

打个比方:压缩就像把一张高清图转成缩略图。聊天场景下,你只需要认出 “这是一只猫”,缩略图足够了;编程场景下,你需要数清猫身上有几根毛、每根毛的精确角度 —— 缩略图完全不够用。

三、核心差异二:链式推理的误差放大效应

编程 Agent 的工作方式是多步链式推理:读文件 → 分析问题 → 制定方案 → 修改代码 → 运行测试 → 修复错误 → 再测试…… 每一步都依赖前一步的精确结果。从本质上看,这是一个严密的离散状态机:Agent 需要在内存中持续维护一组精确的 “状态变量”—— 当前修改的文件路径、当前的变量作用域、上一步工具返回的报错信息、待完成的任务清单。这些状态是非此即彼的,不存在中间地带。

这就形成了一个误差放大器
第一次压缩:记错了一个变量名 → 写出来的代码有 bug
第二次压缩:忘记了之前发现的某个边界条件 → 修复方向跑偏
第三次压缩:连已经改了哪些文件都记不清了 → 开始重复劳动、陷入循环

每一轮压缩引入的微小误差,都会在后续的推理链条中被放大。到第三四轮压缩时,Agent 的内部状态已经和真实状态严重偏离,表现出来就是 “失控”—— 工具乱调、逻辑混乱、忘记任务目标。

更麻烦的是 Agent 的隐性状态维护。Claude Code 会维护 todo list、已完成项、已知错误列表这些隐性状态,这些状态不会每次都显式说出来,而是存在对话的隐含逻辑里。上下文压缩最容易抹掉这些离散的状态节点,相当于状态机丢失了当前的状态指针,直接导致 Agent”失忆”,忘了自己做到哪一步。

聊天业务完全没有这个负担。对话更像是连续的语义流,核心是主题和情感的延续,不存在严格的前后依赖链条。每一轮对话相对独立,用户说一句、AI 答一句,话题跳了、偏了、忘了某个细节,都不影响对话的整体体验。这种语义层面的抽象与泛化,恰恰是大模型最擅长的能力,也是聊天场景不怕压缩的核心原因之一。

四、核心差异三:结构化数据的脆弱性

编程 Agent 重度依赖结构化的工具调用协议。每一次工具调用在消息序列里都是严格配对的:Assistant 发出一个 tool_use(带 ID),User 回复对应的 tool_result(带相同 ID)。

上下文压缩时,这个配对关系非常容易被破坏。比如:
裁剪历史时,切点落在 tool_use 和 tool_result 之间,产生 “孤儿消息”
摘要重写时,把结构化的 tool_use 块写成了自然语言描述
多轮并行工具调用的顺序被打乱,导致状态错乱

除此之外,工具调用本身有严格的 JSON 格式约束,工具定义的 Schema、参数结构都必须完整保留才能被正确解析。但当前的压缩技术很难完美保障结构化数据的完整性:无论是语义摘要还是 Token 裁剪,都可能破坏 JSON 的闭合结构、截断字段定义。一旦解析器无法识别工具调用格式,Agent 的整个执行循环就会直接崩溃。

这就是为什么很多人遇到 “Claude Code 突然不调用工具了,开始用嘴说命令”—— 不是它不想调用,是压缩后的上下文里,工具调用的结构化边界已经模糊了,模型把它当成了普通文本。

而聊天业务几乎没有结构化数据。整条对话就是纯文本消息,压缩前后都是纯文本,不存在结构破坏的问题,自然也不会遇到 “格式解析失败” 这类硬阻断故障。

五、核心差异四:任务闭环 vs 开放交互

还有一个容易被忽略的视角:谁在驱动对话前进

编程 Agent 是自主闭环执行的。你说一句 “帮我重构这个模块”,接下来的十几轮可能都是 Agent 自己在驱动:读文件、改代码、跑命令、查错误…… 用户可能全程只看着。这意味着 Agent 必须自己维护完整的任务状态,一旦压缩导致状态丢失,没有人来帮它纠正。

聊天产品是用户驱动每一轮的。每一轮对话都是用户发起、用户掌舵。如果 AI 记错了什么,用户自然会提醒;如果话题跑偏了,用户会拉回来。用户本身就是上下文质量的校正器。

换句话说:聊天场景下,用户的每一次输入都在“隐式的”重新锚定上下文;编程场景下,Agent 自己在黑盒里跑,压缩跑偏了也没人拉一把。

六、核心差异五:深度推理模式 vs 直觉联想模式

除了业务场景的客观差异,模型本身的设计取向也放大了这种感受差。

像 Claude 这类主打长上下文深度推理的模型,在 Agent 工作流中实际上是在运行系统 2 思维模式:慢速、严谨、步步为营,每一步推导都严格依赖前面的结论和信息。这种模式对上下文的连贯性和完整性要求极高,上下文压缩就像在一个人演算数学题时突然抽走半页草稿纸,哪怕只丢失少量信息,也可能让后续的推理完全跑偏。

而聊天场景下的模型更多运行在系统 1 模式:快速、直觉、联想式生成。它不需要严密的逻辑链条,只需要顺着语义和情绪自然延续即可,本身就不要求强逻辑连贯性,因此对压缩带来的信息损耗抗干扰能力要强得多。

七、结语

总结一下,五类差异层层叠加:

维度 编程类业务 聊天类业务
信息类型 精确符号系统,差一字符即错 模糊语义系统,容错率极高
推理结构 严格链式状态机,误差逐级放大 发散式语义流,误差相互独立
数据结构 结构化工具调用,边界脆弱 纯自然语言,结构简单
驱动方式 Agent 自主闭环,无人校正 用户驱动每轮,自然校正
思维模式 深度逻辑推理,对连贯性要求高 直觉联想生成,抗干扰能力强

这也是为什么做 Agent 框架的团队,永远在和上下文管理死磕 —— 因为你面对的不是 “聊天记不记得住” 的体验问题,而是 “符号系统能不能保真” 的工程问题。聊天场景 80 分的压缩算法,放到编程场景可能连及格线都到不了。

从另一个角度说,这也解释了为什么 “无限上下文” 至今都是伪命题。不是技术做不到更长的窗口,而是当任务本身要求符号级精确时,窗口再大也没用 —— 注意力稀释、位置编码失真、压缩损耗,这些问题不会因为窗口变大就消失

对编程 Agent 来说,真正的解法从来不是 “把窗口做更大”,而是:结构化外部记忆、状态显式化、可验证的任务边界,以及 —— 承认压缩必然有损,在工程上设计好熔断和重置机制。长远来看,核心思路是将关键状态与工具定义从易受压缩的对话上下文中剥离,为 Agent 设计独立的、不受压缩影响的外部记忆体与草稿板,用结构化存储保障核心信息的绝对保真。

而在日常使用中,最直接有效的办法也很简单:当发现编程 Agent 的对话已经过长、即将触发多次压缩时,及时开启新会话,重新明确当前的核心状态与目标,往往是防止 Agent”失控” 最具性价比的方案。毕竟,人类程序员写代码也会记不住,还不是靠注释、文档和 Git 吗?

Leave a Reply

Your email address will not be published. Required fields are marked *

*