Agent 跑长任务,上下文占到窗口八成,压缩触发,从最早的内容开始扔。十分钟后它又去读了一个刚读过的文件,重复问了一个刚回答过的问题。
这条阈值只知道你快装不下了,完全不知道你能安全丢什么。
这是长程 Agent 设计手记系列的第三篇,起因是我们精读了 BEACON(浙江大学,arXiv:2605.06078)。第一篇讲防止打转,第二篇讲里程碑设计。
先说我们自己的实现
Orkas 是个多 Agent 桌面客户端,长任务是这里的常态,压缩天天遇到。我们的实现就是按 token 阈值触发,上下文占到窗口八成左右开始压。写这篇之前,我们没觉得这里有什么问题。
业界常见的边界大概三种:按窗口占比、按对话轮次、让模型写一段摘要盖掉旧内容。我们属于第一种。
前两种压根不看内容。第三种看了,但把「什么该留」整个交给了模型。
三种都在回答什么时候必须扔东西。可我们真正要问的是哪些东西可以不要了。到点就砍,砍掉的是最早的内容,不是最不重要的内容。
里程碑边界,以及它底下压着的那条假设
上一篇讲的里程碑,本来能给出一个比这三种都好的边界。但这里有个坑,上一篇讲得太顺了。
BEACON 里有条假设叫里程碑马尔可夫性。翻译成人话:到了某个里程碑之后,后面怎么走只看还剩哪些子目标,跟你之前怎么摸到这儿的没关系。拿到钥匙以后,要紧的是拿它开哪扇门,你怎么找到它的不重要了。
听起来正好能拿来压缩:过了里程碑,前面那段过程就能折叠掉。
但它是假设,不是事实。论文原话是「约等于」,作者还专门讨论过它什么时候不成立。
训练里够用,拿到压缩里就不够了
同一条假设,两种用法,严格程度差着一个量级。
训练的时候,它只要统计上成立就行。几千次尝试里有几十次不符合,偏差会被平均掉。训练里还压着一层轨迹级信号兜底,把那层去掉,ALFWorld 的成绩从 91.4 掉到 23.4,比什么都不做还差一大截。
压缩不一样,它得逐点成立,对眼前这一次运行成立。丢错一回,这个任务就废了,没有几千次可以平均。
所以论文用了这条假设,不代表你能把它搬到压缩上。两边对它的要求根本不在一个档次。
四种情况下它不成立
想压缩策略的时候,我们拿这四条当检查表。
1. 前面积累下来的隐性认知。某一步试出来「这个接口返回的时间戳是 UTC」。这条认知不属于任何里程碑,可后面每一步都得用。
2. 已经烧掉的资源。token 预算、调用配额、剩余时间。里程碑不记我已经花掉六成,可这个数决定了后面还敢不敢重试。
3. 路径留下的痕迹。里程碑上写着重构完成。但一旦开始调试,你得知道具体动了哪五个文件。
4. 里程碑本身就说不清楚。这条最麻烦。论文里的里程碑是环境给的完整状态,拿到钥匙就是拿到钥匙,一点歧义都没有。而计划里的一步只是一句自然语言,「完成数据清洗」这六个字,根本兜不住那一段里到底发生了什么。
那该带什么过去
别只留一段摘要。摘要是模型写的,它凭感觉决定什么重要。
要留一组固定的字段,由人定死。至少四类:
- 工作区现在什么样:哪些文件动过,动成了什么样。
- 还剩多少额度:token、调用次数、时间。
- 前面已经搞清楚的事:那条 UTC,以及所有会影响后面决策的同类结论。
- 还没搞清楚的事:卡过一次、绕开了、但可能还会撞上的。
跟上面那四种失效情形对着看,正好一一对上。这个对应关系,是判断一套压缩策略够不够用的最简单方法。
其中一半几乎是白捡的。上一篇说过,宿主侧在每次工具调用结束时都会记一批确定性事实:文件有没有真被改写、命令跑没跑成。那批数据本来是为了验证里程碑做的,但它就是工作区快照,压缩时直接带过去就行,不用再让模型总结一遍。
难的是另外两类。已经搞清楚的和还没搞清楚的,眼下只有模型自己写下来才存在,这也正是它们在压缩里最先阵亡的原因。
这事不用争,能测
压缩之后,如果 Agent 又去读了已经被压掉的文件,或者重复问了前面回答过的问题,那就是这条假设在这个任务上失效了,证据摆在那儿。
埋点也简单:把压缩点之后读过的文件路径,跟压缩点之前的记录求个交集。
有了这个数,「哪类任务能激进压缩、哪类不能」就是查数据的事,不再是设计阶段的互相说服。这跟系列第一篇是同一个路子:先量,再改。
哪些地方得打折
这套东西还没上线,目前只到设计和埋点。
具体保留哪些字段、粒度多细,得看真实数据里哪类信息最常被重新捞回来。现在拍板容易拍错。
而且这只是一种做法。换个产品形态,边界画在哪、字段怎么定,答案可能完全不一样。那四条检查表能带走,具体答案不能。
系列的最后一篇聊自我反思:为什么 Agent 总结出来的经验,永远是「要更仔细」这种废话,以及关于它的输入里有什么、没有什么的一个挺意外的发现。