编码 Agent 跑长任务,为什么越来越慢?一篇 harness 论文讲清取舍
跑长时任务的编码 Agent(Claude Code、Codex、各种开源 harness)几乎都碰到过同一个问题:会话越长,模型越”笨”,最后卡在某个上下文溢出上。一篇今年 9 月发在 arXiv 的论文《An Empirical Study of Harness Design for Coding Agents》(论文摘要)把这件事拆开看了——它把 harness 当成可拆组件,固定执行循环,只变化 planning、action space、context management 三件,分别测了 176 个组合,覆盖 4 个模型 × SWE-Bench Verified + Terminal-Bench 2.1。本文挑出”上下文管理”这块的发现,并把它翻译成可执行的工程取舍。
论文关键发现(一句话总结)
上下文管理的真正价值不是”省 token”,而是”避免上下文溢出失败”。换句话说:当窗口预算紧的时候,做不做上下文压缩,模型能不能跑完长任务的差别,远比”省了多少 token”大。
五种策略里,谁最强
论文摘要里写明:在五种上下文管理策略里,先把规则性省略(rule-based elision)放在 LLM 摘要之前,综合效率最强。同时它明确指出,”把被裁掉的内容做成可恢复索引”这件事模型很少回头用,也没带来精度增益。
这个结论反直觉的地方是:直觉上”可恢复”听起来更稳——万一模型要回头查呢?但论文的实测说明模型并不查。可恢复索引是典型的”为人写的安全网”,不是”为模型写的安全网”。
五种策略的工程取舍(这张表是本文按工程经验补的,不是论文给的)
再次强调:论文摘要里没有给出五种上下文管理策略的具体名称,也没给每个策略的具体分值。下表是本文按摘要的描述 + 工程经验划分的五条互不重叠的策略线,不是论文给出的对照表,不应被当作论文结论。具体分值、消融数据、置信区间在 arXiv 摘要页里没有披露——论文 HTML 全文版 虽然公开可读,但本文这次没有逐节对照,要看完整结论的读者可以自行翻。
| 策略 | 主要做法 | 适合场景 | 风险点 |
|---|---|---|---|
| 全量保留 | 不压缩,全程塞进上下文 | 窗口足够大、任务短 | 预算紧时直接溢出 |
| 仅 LLM 摘要 | 触发阈值后整段让 LLM 摘要 | 历史冗长但窗口较松 | 摘要可能固化错误中间态 |
| 仅规则裁剪 | 按规则删低密度内容 | 日志/构建输出占主体 | 删过头会丢失败堆栈 |
| 规则裁剪 → LLM 摘要(论文发现) | 先规则,再触发 LLM | 多种密度混杂的历史 | 摘要触发的时机需要精细 |
| 可恢复省略 | 删原文 + 索引入库 | 怕返工、要求可回看 | 模型很少回查,没有精度收益 |
工程含义其实很直观:先用廉价、确定性的规则去掉低密度内容(重复构建日志、旧命令回显、长输出尾部、可重现的中间文件列表)。规则裁剪完如果已经低于预算,就不调用 LLM。只有当规则裁剪后仍然超预算时,才让 LLM 对剩余内容做摘要。这种”先规则、再触发模型”的取舍在 remote agent 的工程实践里也能看到,比如 Mistral 官方对 Vibe remote agents 的设计介绍 也是把高确定性的过滤放在前面,把昂贵的模型调用留给真正需要的判断(这是工程做法对照,不是论文结论的佐证)。
可落地的伪代码与一个预算推算
下面是本文采用的一种上下文压缩流程示意,不是论文给出的代码,也不是某个官方库的 API:
# 上下文预算控制:本文采用的做法
def compact(history, budget):
# 第 1 步:规则裁剪,不可恢复地删除低密度内容
history = rule_elide(history)
if token_estimate(history) <= budget:
return history
# 第 2 步:仅当仍超预算时,才对剩余内容做 LLM 摘要
history = llm_summarize(history)
# 第 3 步:如果摘要后仍超预算,再按固定规则截断最旧帧
return truncate_oldest(history, budget)
配一个按工程习惯的预算推算(论文摘要里没有给出这些数字,仅作示例):假设窗口是 128k token,固定开销预留 8k,则留给上下文的预算是 120k。如果原始历史约 180k token,就要先靠规则裁剪去掉至少 60k;如果规则裁剪后还在 120k 以上,再调用 LLM 摘要把剩余内容压进去。
失败边界:什么不能裁
论文说上下文管理主要避免的是溢出失败,但裁剪本身会引入新的失败模式。下面这几条边界是从论文结论 + 工程经验里抽出来的,不分先后:
- 失败堆栈不能裁。一条堆栈可能只出现一次,却是定位问题的关键。裁掉它,agent 可能在同一个错误上反复打转。
- 最近几轮命令的原始输出要保留。远历史的日志可以省,但当前决策依赖的退出码、stderr 尾部必须留原文,否则 LLM 在错误中间态上继续执行。
- 不要给”可恢复索引”投入太多。论文明确说模型很少回查、没精度收益。先省下这套机制。
- 预算越紧,越要把规则裁剪前置。论文发现上下文管理在预算紧时价值更大;当窗口明显不够时,应提高规则裁剪的比例,而不是一开始就全量摘要。
一个反方观点
业内对”上下文压缩”有一种乐观假设:只要不丢信息,模型不会变笨。但这篇论文的发现间接否定了这一点——可恢复索引”理论上有信息”,但模型不回查。这说明模型对”看不到”的信息的处理能力比想象中差,给模型留一条能看到的、可执行的提示,比给它留一份”理论上可恢复但需要它主动查询”的数据更可靠。
这条反方对工程上的含义是:如果你的 harness 设计是”全量保存 + 按需查询”,可以重新评估一下模型实际查询的频率——很可能远低于你的预期。
FAQ
Q:什么时候不要做上下文压缩?
任务短、窗口够用、token 不值钱时不要做。压缩是有成本的:规则裁剪要写规则、要调阈值、要处理误删;LLM 摘要要额外调用、要承担摘要错误的风险。如果任务短到 2~3 轮交互就能做完,做压缩是负优化。
Q:规则裁剪的”规则”怎么写?
按低密度 + 高重复的维度写。比如 kubectl apply -f 的成功回显、构建工具的进度条、pip install 的下载百分比,这些都可以被安全裁掉。例外:失败的 stack trace、错误码、文件路径、commit hash 这些不能裁,因为它们是后续决策的直接依据。
Q:LLM 摘要应该怎么触发?
一种工程做法是按预算剩余比例触发,比如规则裁剪后仍超预算 30% 时才触发摘要。这样可以避免”窗口还够用就开始摘要”的过早优化。论文摘要没给具体阈值,所以这条是工程经验,不是论文结论。
参考来源
- An Empirical Study of Harness Design for Coding Agents(arXiv 摘要) — 本文主要依据
- 同篇论文 HTML 全文版 — arXiv 官方渲染版,含完整正文
- Remote agents in Vibe. Powered by Mistral Medium 3.5. — Mistral 官方关于 remote agent 设计的资料,提供另一种 harness 工程取舍的对照
评论区
登录后可评论。