清华CoACT:Coding Agent上下文开销如何降33%?
Coding Agent 的上下文越长,每一步调用的开销越高,能否在不影响任务完成的前提下压缩上下文?Coding Agent 解决软件问题时,需要反复查看代码、修改程序、运行测试:每一步返回的文件内容、搜索结果和日志,都会留在上下文里,下一轮调用时还要整段重新带上。任务越难,上下文越长,每一步要处理的 token 就
上下文一长,Coding Agent每一步调用的花销就往上走。能不能在不拖累任务完成的情况下把上下文压下来?这是清华团队想解决的问题。
Coding Agent做软件任务时,要反复看代码、改程序、跑测试。每一轮返回的文件内容、搜索结果和日志都会堆在上下文里,下一次调用还得整段重新带上。任务越难,上下文越长,每步要处理的token越多,费用也跟着涨。统计显示,在SWE-bench Verified上,这些observation占总token消耗的45.7%,在Terminal-Bench上最高能到67.8%。那能不能直接压掉这些observation?难就难在:压缩的时候,很难判断删掉的内容后面还会不会用到。
清华大学人工智能学院的团队给出了CoACT,一种面向Coding Agent的observation压缩方法。它判断压缩好坏的标准不是结果像不像原文,而是压缩之后Agent的下一步动作有没有变。在SWE-bench Verified的200个实例、三个Agent模型上,CoACT平均让总token消耗少了33.0%,平均PASS@1从69.0%升到71.0%,任务表现和没压缩时差不多。这项工作已被CCF A类会议ICSE 2027直接接收(Top 5%)。
论文标题:CoACT: Action-Preserving Observation Compression for Coding Agents
论文链接:https://arxiv.org/abs/2607.02911
代码地址:https://github.com/THU-Agent/CoACT
一、现有压缩方法的局限
已有的做法大致分两类。一类是改写历史:滑动窗口把较早的命令和输出丢掉,AgentDiet则让模型定期回看历史,自行删掉重复或用不上的内容。问题是历史一改,原有的KV Cache就没法完整复用,模型得重新预填充改写后的内容,token是少了,开销未必跟着少。
另一类是在新的observation进上下文之前就压好。之前的历史原样不动,缓存照常复用。CoACT走的就是这条对KV Cache更友好的路。
选这条路,先得把压缩目标想明白。Agent的任务是完成工作,压缩效果自然要看任务能不能完成。于是目标定为:在任务成功率(PASS@1)与未压缩Agent接近的前提下,尽量压低总token消耗。
取舍就落在两头:砍得太多,Agent 拿不到必要信息,任务可能失败,或者反复回读;砍得太少,开销降不下来。
二、核心思路:下一步动作保持(NAP)
最省事的验证是让 Agent 拿着压缩结果把任务跑完。可同一份 observation 的压缩方式很多,每种都跑全程,代价太大;一次任务里压缩次数又多,最终结果究竟由哪一次压缩造成,也很难归因。
按研究团队的看法,Agent 执行任务可拆成“读输出、做动作、拿新输出”的循环。只要初始环境一致、环境对相同动作的反应一致,且每次压缩后 Agent 的下一步动作不变,环境收到的操作与返回结果就相同,后续动作序列乃至最终结果理论上也不会变。
由此提出下一步动作保持(Next-Action Preservation,NAP):任务目标与历史保持不变,让 Agent 分别读压缩前后的 observation,再比对它下一步的动作。举例来说,读完一段代码后 Agent 原本要去查其中调用的某个函数,换成压缩结果后它仍去查这个函数,这次压缩就算保住了下一步动作。每次压缩都能单独检验,不必等任务结束。
三、训练数据怎么造:
基于 NAP 构造压缩示范
有了 NAP,团队训练了一个轻量压缩器,基座是 Qwen3.5-4B。流程分几步:
先由教师模型 Gemini3-Flash 对同一份 observation 生成 8 份压缩候选;再让 Agent 在原始 observation 下多次采样,得到 8 个参考动作。每份压缩结果引出的动作与参考动作逐一比对,取最相似的 3 个求平均,得分到 0.6 才算过关。比对不看字符串,而是解析命令的操作类型、目标文件和读取范围,写法不同但读的是同一段代码,会被认作相同操作。
过关之后,挑更短的版本当训练示范。若 8 份候选全部没过,就拿原始 observation 当目标,让模型学会该保留时保留。
四、两阶段训练:离线引导与在线对齐
只用未压缩 Agent 的轨迹造数据有隐患:采集时 Agent 的历史都是完整的;部署之后,前几步读到的内容已被压缩,它看到的历史并不一样。
CoACT 分两步走:第一阶段用离线轨迹做监督微调,得到初始压缩器;第二阶段让压缩器真正参与 Agent 运行,保留此前已压缩的历史,重做动作比对与长度筛选,产出第二批数据;两阶段数据合并后训练最终压缩器。
对照实验里,仅靠离线数据训练出的压缩器PASS@1为56.0%,比不做压缩的57.0%还低一点;把第二阶段的在线数据加进来后,这一数字升到60.5%,总token消耗则与未压缩时大致持平。
五、实验结果:省下三分之一,性能没有变在SWE-bench Verified中随机抽出的200个实例上,Qwen3.5-35B-A3B、Deepseek-v4-Pro和Gemini3-Flash三个模型的token消耗都降了:Qwen由3.795M降至2.428M,Deepseek由1.068M降至0.868M,Gemini由0.685M降至0.422M,平均降幅33.0%。三个模型的平均PASS@1从69.0%升到71.0%,其中Qwen和Gemini各自提高3.5和4.0个点,Deepseek小幅回落1.5个点。平均交互步数同样由56.5步减至51.2步。
落到具体表现上,压缩之后那些又长又占空间的observation明显少了。以Qwen3.5-35B-A3B为例,超过1K token的observation占比由32.3%降至9.4%。
与现有observation压缩方法对比,结果更耐人寻味。拿Qwen来说,LLMLingua-2压缩后PASS@1从57.0%掉到50.0%,总token反倒由3.795M涨至10.329M;SWE-Pruner涨到4.471M;LongCodeZip降至3.165M;CoACT则是2.428M,PASS@1为60.5%。Deepseek那边,三种基线的总token都高过未压缩的1.068M,CoACT降到0.868M,在两个评测模型上都是总token最低的方案。可见只盯着缩短observation长度,未必能让整个任务的总开销跟着降下来。
CoACT属于单步压缩方法,但也能和历史压缩方法搭配使用。AgentDiet单独跑时,总token虽然少了,估算总费用却从未压缩的41.26美元升到45.65美元,问题出在改写历史破坏了KV Cache复用。在AgentDiet流程中先接入CoACT,估算总费用回落到25.88美元,任务成功率与原来相近,比单用AgentDiet低约43.3%。
作者介绍
这项研究出自清华大学人工智能学院 AI Agent 课题组。通讯作者是该院助理教授李佳,其主要研究方向为 AI + 软件、可信智能体。第一作者陈浩瑞是清华大学人工智能学院 2027 级直博生(拟入学),主攻 Efficient AI。