An Empirical Study of Harness Design for Coding Agents 论文解读

arXiv ID: 2609.20804([cs.AI],v1 提交于 2026-09-17) 论文标题: An Empirical Study of Harness Design for Coding Agents 中文标题: 编码智能体支架(Harness)设计的实证研究 作者: Run-Ze Fan, Zihao Zhang, Simin Ma, Yebowen Hu, Shouju Wang, Kaiqiang Song, Fei Liu, Hamed Zamani, Xiaoyang Wang 机构: UMass Amherst、Zoom、Emory University、UNC Charlotte(部分工作完成于 Zoom 实习期间) 论文链接: https://arxiv.org/abs/2609.20804


一、研究背景与核心问题

大模型驱动的编码智能体(coding agent)并不是只有模型本身——模型外层还有一层"支架"软件,即 harness:它负责把模型的推理翻译成可执行动作、管理上下文、注入系统指令、处理工具调用等。harness 的形态决定了模型能力如何转化为长程软件工程任务上的实际表现。

然而,现有工作通常把 harness 当作一个单体系统来评估(例如直接比较某个 agent 框架的整体得分),无法回答:harness 里到底哪个组件在起作用?这些组件是普遍有效,还是其有效性取决于模型能力、任务类型和资源预算

本文的核心贡献就是:固定执行循环,只变化三个组件——规划(planning)、动作空间(action space)、上下文管理(context management),在 4 个模型 × 2 个基准上评估了 176 个匹配实验设置,进行严格的组件级消融,得出一系列"条件性"(而非普适性)结论。


二、方法:模块化 Coding Harness 设计(§2)

harness 基于经典的 ReAct 循环(Yao et al., 2022),每轮由推理(reasoning)、动作(action)、观察(observation)组成。实现基于 LangGraph,通过 Harbor 框架驱动基准任务。权限处理、编辑后诊断、卡住检测等支撑组件在所有消融中保持固定。

2.1 Planning(规划组件)

  • 由模型维护一个显式、持久的任务进度计划
  • 开启时:系统指令定义规划协议,第一轮提醒要求先制定初始计划,模型通过 update_plan 工具维护计划;后续每轮把当前计划注入模型输入,但不写入对话历史。
  • 关闭时:移除所有规划指令、提醒、计划注入和 update_plan 工具,其余组件完全不变。
  • 注意:该设计估计的是"持久规划脚手架"的效果,而非"规划作为通用推理策略"的效果。

2.2 Action Space(动作空间)

两种条件:

  1. 预定义工具集(predefined tools)read_filewrite_fileedit_filelist_filesglob_filesgrep_textweb_fetchbash。只读工具可在一轮内并行执行;写工具修改工作区或 harness 状态。预定义文件工具强制执行先读后写检查、更新 harness 文件状态、并在支持的编辑后触发自动诊断。排除网络搜索,因为 SWE-Bench 任务来自公开 GitHub issue,搜索可能泄露 ground-truth patch。
  2. bash-only:移除预定义的文件、搜索、web 工具,只保留 bash 进行通用环境交互。

作者强调:该干预是完整动作接口的变化(包括工具可用性、接口指令、状态跟踪、验证支持),而不只是工具数量或动作粒度的孤立效应。

2.3 Context Management(上下文管理)—— 核心设计

三种可组合机制

机制 名称 功能
M1 Elision(省略/折叠) 把过期的工具观察正文替换为短 stub(占位符),便宜但丢失细节
M2 Recall(召回) 把被省略的观察存入外部文件系统,暴露 recall_event 工具按需读回,使省略可逆
M3 Summarization(摘要) 把最旧的消息折叠进一个滚动自然语言摘要;由同一模型以单独的无工具调用生成

双阈值策略:软阈值 B₁ 和硬阈值 B₂。前导部分(系统提示 + 初始任务描述)和最近窗口(至少 2 轮)保持逐字不变,只压缩中间区域:

  • 历史超过 B₁ → 对中间区域的臃肿工具观察执行 M1+M2(存外部 + 留 stub)
  • 仍超过 B₂ → 对最旧的中间事件执行 M3(摘要)

五个策略层级

Tier M1 Elision M2 Recall M3 Summarization 说明
T0 无管理,超出窗口即报错终止
T1 仅省略(不可逆)
T2 省略 + 可召回
T3 仅摘要
T4 完整三机制,先省略后摘要的分级策略

2.4 固定组件

  • Safety:工作区守卫(拒绝逃逸项目根目录的路径,含符号链接)、先读后写检查(内容哈希检测外部修改)、权限层(allow/ask/deny 分类);工具错误作为观察返回而非抛出异常。
  • Post-edit diagnostics:编辑/写入 Python 文件后,用 ruff、pyflakes 或纯语法回退做快速只读检查。
  • Stuck detection:监控相同工具名+相同参数的连续调用 streak;达到 5 次注入一次性提醒;相同失败 streak 达 8 次则提前终止运行。

三、实验设置(§3.1)

模型(4 个)

模型 定位 价格(每 1M 输入/输出 tokens,OpenRouter)
Nemotron-3 30B 家族内小模型 $0.05 / $0.20
Nemotron-3 120B 家族内中模型 $0.08 / $0.45
Nemotron-3 550B 家族内大模型 $0.50 / $2.20
Mistral-Medium-3.5-128B 跨家族对照 $1.50 / $7.50

Nemotron-3 三个尺寸构成家族内能力轴,Mistral 用于检验结论是否跨家族泛化。

基准与实现

  • SWE-Bench Verified:500 个人工验证的真实 GitHub issue(仓库级 issue 解决,纯 Python)。
  • Terminal-Bench 2.1:89 个命令行环境的端到端任务。
  • 指标:任务成功率(SR)每任务平均成本($)
  • SGLang 本地推理,BF16 精度;temperature = 0,top-p = 0.95;每轮输出上限 16,384 tokens;每任务最多 300 步;软/硬上下文阈值分别为可用窗口的 0.6 / 0.85;逐字最近窗口预算 0.3 且不少于 2 轮;工具结果截断至 24k 字符;每步最多 8 个只读工具并行。

消融设计与统计

  • T0–T4 × 4 种上下文窗口预算(32k、64k、96k、128k)= 每个模型-基准对 20 个设置(全部使用预定义工具 + 开启 planning)。
  • T4/128k 为基线,再做两个单组件消融:−plan(关闭规划)、bash-only(替换动作空间)。
  • 合计每个模型-基准对 22 个设置 × 4 模型 × 2 基准 = 176 个实验设置
  • 统计检验:任务配对的双侧精确 McNemar 检验,Benjamini–Hochberg 控制 FDR = 0.05。

四、主要结果(§3.2)

4.1 上下文管理的价值随窗口收紧而增大

  • 管理策略(T1–T4 均值)与 T0 的成功率差距:SWE-Bench 上从 32k 的 35.7 pp 缩至 64k 的 15.9、96k 的 5.5、128k 的 2.7 pp;Terminal-Bench 上从 9.5 → 7.5 → 4.8 → 2.8 pp
  • 机制解释:T0 的窗口溢出失败率从 32k 的 78.7%(SWE-Bench)/ 61.0%(Terminal-Bench)降至 128k 的 8.7% / 12.1%;而所有管理层级在所有预算下溢出率为 0
  • 结论:上下文管理的主要收益是防止窗口溢出导致的过早终止;窗口越大,边际收益越小且更依赖模型。

SWE-Bench Verified 关键数字(T0 → T4)

窗口 30B 120B 550B Mistral
32k 9.40 → 21.20% 11.40 → 42.20% 6.40 → 55.60% 12.60 → 63.80%
128k 24.80 → 25.20% 59.80 → 65.80%(显著) 67.40 → 68.60%

Terminal-Bench 呈相同趋势:32k 时 Mistral T0 21.35% → T4 42.70%;128k 时 550B T4 44.94%(显著高于 T0 34.83%)。

4.2 T4(先省略后摘要)性价比最优

  • T4 在 8 个模型-基准面板中的 7 个取得最低成本,成功率与 T1–T3 相当。
  • 32k 时 T1/T2 轨迹仍逼近满窗口,T3/T4 的峰值上下文显著低于窗口上限;T4 在所有四个预算下峰值上下文比率最低。
  • T4 在 32k/64k 比 T1/T2 更少调用 M1 省略,且在所有预算下比 T3 更少调用 M3 摘要——早期省略在需要摘要前就解决了多数情况,减少了昂贵的 LLM 摘要调用

4.3 Recall(M2)很少被使用且无准确率增益

  • T2 vs T1 的 32 个对比中:15 胜、14 负、3 平;平均差 −0.36 pp
  • 64 个 T2/T4 设置中,36 个(56.3%)从未调用 recall_event,中位调用率为 0;平均每任务调用从 32k 的 0.540 降至 128k 的 0.007;T4/128k 的 16 个 planning/动作空间设置中召回调用为 0
  • 使用最多的是 Nemotron-3 30B 在 Terminal-Bench 32k T2(平均每任务 4.326 次),但该配置反而比 T1 低 3.37%。
  • 结论:无损存储增加了模型很少使用的机制,取回被省略内容并不能稳定转化为任务完成

4.4 Planning:弱模型的准确率脚手架 → 强模型的成本节约器

在 T4/128k + 全工具下对比 planning 开/关:

  • Nemotron-3 30B(弱模型):planning 使成功率 +11.6 pp(SWE-Bench)、+4.5 pp(Terminal-Bench),但成本更高。
  • Nemotron-3 120B:成功率无一致增益。
  • 550B 与 Mistral(强模型):planning 在 SWE-Bench 上分别降成本约 30% 和 32%,成功率仅降 2.0 和 0.4 pp。

planning 开 vs 关的变化百分比(T4/128k,轮数 / 工具调用 / 平均输入 tokens)

模型 SWE-Bench Terminal-Bench
30B +293.2% / +474.0% / +104.1% +66.7% / +83.8% / +24.0%
120B +20.1% / +42.7% / +10.3% −15.0% / −23.1% / −12.0%
550B −24.3% / −24.5% / −12.4% +6.8% / +7.9% / −1.7%
Mistral −23.2% / −23.3% / −15.1% −22.5% / −21.9% / −13.0%

4.5 动作空间:预定义工具支撑弱模型,bash-only 利好强模型

  • 30B:预定义工具 +15.0%(SWE-Bench)、+10.1%(Terminal-Bench)。bash-only 时模型发出训练中学到的工具调用模式,harness 无法解析——Terminal-Bench 上 66% 的 bash-only 轨迹因接口外调用终止,平均轨迹从 71 轮缩至 15 轮。
  • 120B:增益缩至 +1.6% / +4.5%,但预定义工具让运行更短(SWE-Bench 101→77 轮,Terminal-Bench 96→70 轮)。
  • 550B:bash-only 反而 +3.6%(SWE-Bench)、+5.6%(Terminal-Bench),成本降 53% / 30%;调用次数减少 32% / 24%——强模型能把多个操作打包进复合 shell 命令。
  • Mistral(揭示任务类型边界):全工具在 SWE-Bench 上 +23.2%,但 bash-only 在 Terminal-Bench 上 +6.7%。Mistral 在 Terminal-Bench 上 71.9% 的工作区动作经由 bash(SWE-Bench 仅 40.4%);且 bash-only 时 32.8% 的 SWE-Bench 运行未编辑任何文件就结束(全工具仅 1.2%)。

五、轨迹级分析(§4)

  • 上下文管理只延长轨迹、不改变行为:32k 时 T0 中位轨迹仅 20–30 轮,多数死于 Localize 阶段;管理策略延长至约 50–180 轮,阶段顺序和比例基本保持。128k 时各层级差异大幅缩小。
  • Planning 对弱模型是"续命"机制:关闭 planning 后,30B 在 SWE-Bench 上"未编辑即终止"比例从 27.8% 飙至 68.6%,停滞在定位阶段的比例从 10.4% 飙至 58.4%,中位轨迹从 40 轮崩至 5 轮;强模型(550B、Mistral)几乎不受影响。
  • Planning 缩短强模型轨迹的机制是减少编辑后验证:550B 中位轨迹 108→74 轮、Mistral 68→53 轮,减少的主要是 Verify 阶段而非定位或修复。Terminal-Bench 上 planning 同时"救活过早终止"和"截断过长尾部",净效应决定成本变化。
  • 动作粒度:bash-only 使重复修补(re-patch)次数全面下降(550B 4.6→1.5、Mistral 3.0→1.3);Terminal-Bench 上"创建/整体替换"式写文件占比大幅上升(550B 51→76%、Mistral 28→57%)。550B 在 Terminal-Bench 上中位轨迹 47→31 个动作,Write-code 占比 16%→27%。

六、图表速览

图表 内容
Figure 1 论文总览:三个组件的系统消融,揭示四个条件性效应
Figure 2 harness 架构:ReAct 循环 + T4 双阈值上下文管理示意
Figure 3 成功率与窗口溢出率随上下文预算变化
Figure 4 各 tier 成功率胶囊图 + 平均成本,T4 高亮
Figure 5 (a) 峰值上下文/标称预算比;(b) M1/M3 每任务调用次数;(c) 每任务平均成本
Figure 6 planning 开/关对比(成功率与成本)
Figure 7 动作空间对比:成功率、成本、经 bash 发起的调用占比
Figure 8 / 9 SWE-Bench / Terminal-Bench 轨迹剖面(按阶段分解的堆叠面积图)
Table 1 / 2 工具清单;五个上下文管理层级的机制组合
Table 3 / 4 SWE-Bench / Terminal-Bench 主结果(McNemar+BH 校正显著性)
Table 5 / 6 / 7 planning 开关的轨迹变化;未编辑即终止比例;动作粒度统计
Figures 10–30 附录:系统提示、planning 提示、各工具完整描述原文

七、结论与启示

harness 设计是一个条件性系统问题,而非"组件全开就是最好":

  1. 上下文管理在窗口紧张时最关键(本质是防溢出失败);T4(先规则省略、后选择性 LLM 摘要)以相近成功率取得最低成本;而让省略内容可召回(M2)增加的机制模型很少使用,无准确率增益——简单的不可逆省略即可
  2. Planning 的价值取决于模型强度:对弱模型是提升成功率的脚手架(维持轨迹活到首次编辑);对强模型主要是省成本(削减冗余的编辑后验证),成功率几乎不变。
  3. 动作空间取决于模型的 bash 熟练度与任务类型:预定义工具支撑 bash 能力弱的模型;bash 能力强的模型用 bash-only 接口反而更准、更省,尤其在命令行中心任务上。
  4. 实践建议:组件选择应针对目标模型、任务类型和资源预算做匹配,而非默认全开;本文的模块化 harness 也可作为评估未来 harness 组件的框架。

局限:组件实例化方式单一(一种 planning 提示、一种阈值策略);planning 和动作空间仅在 T4/128k 下消融;每设置只跑一次且 Terminal-Bench 仅 89 个任务(很多对比未达统计显著);SWE-Bench 仅覆盖 Python;模型规模是能力的不完美代理,交叉点结论迁移前需验证。