← 返回 2026-09-18

编码代理框架(Harness)设计的实证研究 An Empirical Study of Harness Design for Coding Agents

Run-Ze Fan, Zihao Zhang, Simin Ma, Yebowen Hu, Shouju Wang, Kaiqiang Song, Fei Liu, Hamed Zamani, Xiaoyang Wang 📅 2026-09-17 👍 68 2026-11-02 18:30
SWE-Bench Terminal-Bench harness设计 上下文管理 实证研究 编码代理

176组受控实验解析编码代理框架三大组件的条件效应:上下文管理、规划与动作空间

前置知识

Coding Harness(编码代理脚手架)

Harness 是包裹 LLM 的软件层,把模型能力转化为可执行的自主行为:它包含控制循环(如何组织推理-行动-观察)、动作接口(工具定义与调用协议)、上下文管理策略(有限窗口内保留哪些历史),以及权限安全、编辑后诊断、卡死检测等辅助组件。同一模型换不同 harness 成绩可能大幅变化,因此 harness 设计不是实现细节而是真正的性能变量。

全文的研究对象就是 harness 的三个核心组件,理解 harness 的构成是读懂消融设计与结论适用范围的前提。

ReAct 循环

ReAct 是代理最常用的执行模式:每一轮模型先产生推理(thought),再发出一个动作(tool call),环境返回观察(observation),观察追加进历史后进入下一轮。本文 harness 固定采用 ReAct 循环,每轮把系统提示、当前计划、受管理的历史组装成模型输入,每个任务最多 300 步,在 Docker/E2B 容器中执行工具。

论文的方法论是'固定执行循环、只变组件',必须知道循环本身包含什么、哪些部分被固定,才能理解每个消融估计的是什么效应。

上下文窗口与上下文压缩

上下文窗口是模型单次调用能看到的最大 token 数。长任务中交互历史不断膨胀,超出窗口会导致执行被截断而失败。上下文管理用有损手段(省略 elision、摘要 summarization)或无损手段(外部存储加按需检索 recall)压缩历史,使长轨迹能继续推进。本文用软阈值 $B_1$(窗口的 0.6)和硬阈值 $B_2$(0.85)分阶段触发不同压缩机制。

论文用 32k/64k/96k/128k 四档窗口预算和 T0–T4 五种管理策略,系统刻画了上下文管理价值随预算变化的规律,这是四条主结论之首。

SWE-Bench Verified 与 Terminal-Bench 2.1

SWE-Bench Verified 是 500 个人工核验的真实 GitHub issue 修复任务,要求在 Python 仓库中定位并修补代码并通过测试;Terminal-Bench 2.1 是 89 个端到端命令行任务,在容器里从零完成工作并以执行结果判定成败。两者都是长程任务,前者是仓库级修复、后者更偏 shell 中心,任务类型差异直接解释了论文中动作空间的条件效应。

所有实验结论都建立在这两个基准上,理解两者的差异是读懂'同一组件在不同任务上效应反转'这一关键发现的基础。

McNemar 检验与 Benjamini–Hochberg 校正

McNemar 检验用于配对的二值结果(同一任务在两种配置下分别成功/失败)的差异显著性检验;Benjamini–Hochberg 程序在大量同时进行的比较中控制假发现率(FDR)。本文对 176 个设置中的成功率对比使用双侧精确 McNemar 检验,并以 $q<0.05$ 判定显著,表格中带 * 的数字即表示与匹配基线差异显著。

论文主表中的显著性标记和'哪些结论站得住'的判断都依赖这套统计流程,不看懂它容易误读 Terminal-Bench 上不显著的对比。

研究动机

现有工作几乎都把 harness 当作不可分割的整体系统来评测。例如 Cao et al. (2026) 的跨 harness 评测发现 Claude-Opus-4.5 在 OpenHands 上表现最好,而 Claude-Sonnet-4.5 在 SWE-Agent 上最好,说明 harness 偏好随模型而变。但整体对比混淆了多个机制:两个代理系统之间的性能差无法归因于规划脚手架、工具设计、上下文管理策略,还是它们与底层模型的交互。同时,这些组件的效果很可能依赖模型能力(弱模型需要脚手架、强模型反被拖累)、任务类型(仓库级修复 vs 命令行任务)和资源预算(上下文窗口大小),而此前没有研究在设计层面同时操纵这三条轴,导致从业者不知道某个组件是否值得搬进自己的系统。

本文的目标是本文的目标是构建一个执行循环固定、三个核心组件可独立开关的轻量编码 harness,从而在受控条件下估计每个组件的条件效应。具体而言:在 4 个模型(Nemotron-3 家族的 30B/120B/550B 作为同家族能力轴,加 Mistral-Medium-3.5-128B 作跨家族对照)上,对 2 个长程基准(SWE-Bench Verified 500 题、Terminal-Bench 2.1 89 题)评估 5 种上下文管理策略(T0–T4)× 4 档窗口预算(32k/64k/96k/128k),并在 T4/128k 基线下单独消融规划(开/关)与动作空间(8 个预定义工具 vs 仅 bash),共 176 个匹配设置;再用轨迹级分析把每个效应归因到具体的行为变化。

与已有工作不同的是,本文的独特切入是'组件级 conditional 效应估计'而非系统排名。与最接近的工作相比:Liu (2026) 用全因子设计研究提示级脚手架,但停留在短程推理任务、不操纵窗口压力;AgentArch (Bogavelli et al., 2025) 报告了模型偏好差异但未拆到实现层组件。本文同时做到四件事:(1) 在实现层面拆解规划、工作区动作接口、上下文管理三类干预;(2) 显式扫描上下文窗口预算,让窗口成为真正的约束;(3) 提供同家族模型规模轴加跨家族对照的双轴能力刻画;(4) 用经 3 名人类标注者验证的 LLM judge(原始一致率约 94.2%、加权 Cohen's κ 0.929,覆盖 15,610 个标注单元)把聚合指标差异解释为轨迹长度、停止点与动作粒度的变化。

核心方法

直觉是:想知道每个部件值多少,就要让其他一切保持不动。作者从零构建轻量 harness:ReAct 循环,SGLang 本地 BF16 推理(温度 0、top-p 0.95、每轮输出上限 16,384 token),Harbor 管理任务容器与验证器,每任务最多 300 步。三个可变组件是:(1) 规划——启用时系统提示定义计划协议、首轮提醒创建计划,模型通过 update_plan 工具维护持久计划,计划每轮注入输入而不进对话历史;(2) 动作空间——预定义工具集(read_file、write_file、edit_file、list_files、glob_files、grep_text、web_fetch、bash,带类型化参数 schema 与自然语言描述)或仅 bash 一个接口;(3) 上下文管理——由省略(M1)、召回(M2)、摘要(M3)三个机制组合成 T0–T4 五档策略,在软阈值 $B_1=0.6$ 窗口和硬阈值 $B_2=0.85$ 窗口处分阶段触发。权限层、read-before-write 检查、编辑后 ruff/pyflakes 诊断、卡死检测等辅助组件全部固定,构成公共执行基底。

核心创新是把 harness 评测从'系统 vs 系统'改造为'组件的条件效应估计'。几个关键设计值得强调:其一,T4 分阶段策略——先用零成本的规则省略(超过 $B_1$ 触发,把中部区域大体积工具观察替换为 stub),再用昂贵的 LLM 摘要(超过 $B_2$ 才触发,把最旧事件折入运行摘要),序言和最近窗口(预算 0.3、至少 2 轮)始终保留原文;其二,T1 与 T2 只差召回机制 M2,构成对'无损召回是否值得'的天然匹配比较;其三,同家族三个规模(30B→120B→550B)作为能力轴、四档窗口作为预算轴,形成能力×预算的双轴扫描;其四,用人工验证过的 LLM judge 把每条轨迹的每一轮标注为 Localize/Reproduce/Fix/Verify/Other 等阶段,使成功率差异可以被解释为'轨迹被延长''停止点被改变''代码写入粒度被改变'三类行为机制。

方法步骤详情

每轮流程如下:(1) 组装输入——系统提示+工具 schema+当前计划(逐轮注入、不存入历史)+受管理历史 $H$;(2) 模型发出推理与工具调用,最多 8 个只读工具并行,在容器内执行,工具结果截断至 24k 字符后追加进 $H$;(3) 若本轮调用了 recall_event(id),从外部存储把原始观察读回 $H$(对应算法第 2–4 行);(4) 上下文管理——保留序言与预算化近期窗口原文,若 $\text{tokens}(H)\ge B_1$,对中部区域每个大体积工具观察先存外部存储(M2)再以短 stub 替换(M1);若仍 $\ge B_2$,把中部最旧事件摘要进运行摘要(M3,由同一被测模型在单独的无工具调用中生成,按 Goal/Files touched/Done/Pending 等固定标题增量更新);(5) 安全与纠错——工作区守卫拒绝逃逸路径,read-before-write 拒绝未读先写,卡死检测在连续 5 次相同调用时注入一次性提醒、连续 8 次相同失败调用时提前终止;(6) 任务结束或超 300 步后由基准验证器判定成败,token 按 OpenRouter 价格计费(如 Nemotron-3-30B 为 $0.05/$0.20 每百万输入/输出 token,Mistral-3.5 为 $1.50/$7.50)。

技术新颖性

技术新颖性有四点。(1) 模块化可组合的 harness:规划、动作空间、上下文管理可独立配置,权限、诊断、卡死检测等固定为公共基底——这与 OpenHands、SWE-Agent 等把设计选择耦合在一起的系统不同,使每个干预的效应可以单独识别。(2) 五种上下文管理策略按 M1/M2/M3 机制矩阵精确定义(Table 2),首次在长程编码任务上把'无损召回(外部存储+recall_event)是否比纯省略更好'变成可检验命题,并给出否定答案。(3) 显式窗口预算扫描(32k–128k)证明上下文管理的收益主要来自防止溢出截断而非提升单轮决策质量,且随窗口扩大而衰减——这为'何时需要上下文管理'给出定量边界。(4) 轨迹级归因框架:把三类干预对应到三种可区分的行为签名(管理延长轨迹、规划改变停止点、动作空间改变代码写入粒度),并通过 200 条轨迹、15,610 个单元的人工对比验证了 judge 的可靠性(κ 0.858–0.980)。

Overview of the coding harness. Top: the ReAct loop... Bottom: the T4 strategy. M1–M3 are the three context-management mechanisms.
Figure 2: Overview of the coding harness. Top: the ReAct loop... Bottom: the T4 strategy. M1–M3 are the three context-management mechanisms.

实验结果

论文有四条主结论。(1) 上下文管理的价值随窗口收紧而增大:管理档(T1–T4)与 T0 的平均成功率差距在 SWE-Bench 上从 32k 的 35.7 个百分点缩到 64k/96k/128k 的 15.9/5.5/2.7,Terminal-Bench 上从 9.5 缩到 7.5/4.8/2.8;同步地,T0 的窗口溢出失败率从 78.7% 降到 8.7%(SWE-Bench)、61.0% 降到 12.1%(TB),而所有管理档溢出率恒为 0——收益基本来自防止过早截断。(2) T4 提供最佳准确率–成本权衡:在 8 个模型–基准面板中的 7 个成本最低,成功率与其他管理档相当;其峰值上下文占比在所有预算下最低,M1 省略调用少于 T1/T2、M3 摘要调用少于 T3,说明早期廉价省略替代了昂贵的 LLM 摘要。(3) 召回几乎不被使用:T2 对 T1 在 32 组匹配比较中 15 胜 14 负 3 平,等权平均差 −0.36 个百分点;64 个启用召回的设置中 36 个(56.3%)从未调用 recall_event,平均调用率从 32k 的 0.540 次/任务跌到 128k 的 0.007。(4) 规划的角色随能力转换:30B 上规划使 SWE-Bench 成功率 +11.6 pp、TB +4.5 pp 但成本上升(SWE-Bench 轮数 +293.2%);550B/Mistral 上成本降约 30%/32%、成功率仅降 2.0/0.4 pp。轨迹证据:无规划时 30B 中位轨迹从 40 轮塌缩到 5 轮、68.6% 未编辑即终止(58.4% 卡在 Localize),有规划时 550B 中位从 108 缩到 74 轮、Mistral 从 68 缩到 53 轮,砍掉的几乎全是编辑后的冗余验证。(5) 动作空间效应:30B 上全工具比 bash-only 高 15.0 pp(SWE-Bench)/10.1 pp(TB),因 66% 的 bash-only TB 轨迹发出接口外工具调用而终止(平均轨迹 71→15 轮);550B 上 bash-only 反而 +3.6/+5.6 pp 且成本 −53%/−30%;Mistral 在 SWE-Bench 上全工具 +23.2 pp 但在 TB 上 bash-only +6.7 pp——它 71.9% 的 TB 动作走 bash(SWE-Bench 仅 40.4%),显示任务类型决定交叉点。(6) 粒度证据:bash-only 使重补丁数全模型下降(30B 3.3→0.4、550B 4.6→1.5),TB 上 create/replace 写文件占比上升(30B 28%→64%、550B 51%→76%),即可能力的模型用 shell 写更大粒度的代码。

Tools exposed by the harness.
Table 1: Tools exposed by the harness.
The five context-management tiers, each enabling a subset of elision (M1), recall (M2), and summarization (M3).
Table 2: The five context-management tiers, each enabling a subset of elision (M1), recall (M2), and summarization (M3).
Main results on SWE-Bench Verified, reporting success rate (SR, %) and mean cost per task ($).
Table 3: Main results on SWE-Bench Verified, reporting success rate (SR, %) and mean cost per task ($).
Main results on Terminal-Bench 2.1, reporting success rate (SR, %) and mean cost per task ($).
Table 4: Main results on Terminal-Bench 2.1, reporting success rate (SR, %) and mean cost per task ($).
Percentage change from planning off to planning on at T4, a 128k context-window budget, and the full tool set.
Table 5: Percentage change from planning off to planning on at T4, a 128k context-window budget, and the full tool set.
SWE-Bench runs terminated without an edit, and the subset stalled at localization.
Table 6: SWE-Bench runs terminated without an edit, and the subset stalled at localization.
Action granularity with the full tool set vs. bash-only.
Table 7: Action granularity with the full tool set vs. bash-only.
Failure-stage distribution of unresolved SWE-Bench runs at a 128k context-window budget.
Table 10: Failure-stage distribution of unresolved SWE-Bench runs at a 128k context-window budget.
Mean number of recall_event calls per task in the recall-enabled context-management strategies (T2 and T4).
Table 13: Mean number of recall_event calls per task in the recall-enabled context-management strategies (T2 and T4).
Success rate and window-overflow rate against the context-window budget.
Figure 3: Success rate and window-overflow rate against the context-window budget.
Success rate and cost across context-management tiers.
Figure 4: Success rate and cost across context-management tiers.
Context compression, mechanism use, and cost across context-window budgets.
Figure 5: Context compression, mechanism use, and cost across context-window budgets.
Absolute performance and cost with and without planning.
Figure 6: Absolute performance and cost with and without planning.
Effect of the action space.
Figure 7: Effect of the action space.
SWE-Bench trajectory profiles across harness configurations.
Figure 8: SWE-Bench trajectory profiles across harness configurations.
Terminal-Bench trajectory profiles across harness configurations.
Figure 9: Terminal-Bench trajectory profiles across harness configurations.
查看结构化数据
任务指标本文基线提升
SWE-Bench Verified(Nemotron-3 30B,32k 窗口,上下文管理价值) 成功率 SR(%) T3 23.8 / T4 21.2(管理档 20.6–23.8) T0 无管理 9.4 +11.8 至 +14.4 个百分点(McNemar 显著,q<0.05)
SWE-Bench Verified(Nemotron-3 550B,128k) 成功率 / 每任务成本 T4 65.8% / $2.33;bash-only 69.4% / $1.11 T0 59.8% / $2.08;全工具+规划 65.8% / $2.33 T4 较 T0 +6.0 pp;bash-only 较全工具 +3.6 pp 且成本 −53%
Terminal-Bench 2.1(Nemotron-3 550B,128k) 成功率 / 每任务成本 T4 44.94% / $2.43;bash-only 50.56% / $1.70 T0 34.83% / $1.65;全工具 44.94% / $2.43 T4 较 T0 +10.1 pp;bash-only 较全工具 +5.6 pp 且成本 −30%
SWE-Bench Verified(Nemotron-3 30B,T4/128k,规划消融) 成功率 / 中位轨迹长度 有规划 25.2% / 40 轮 无规划 13.6% / 5 轮 +11.6 pp;未编辑即终止率 68.6%→27.8%
SWE-Bench Verified(Mistral-3.5-128B,T4/128k,动作空间消融) 成功率(%) 全工具 68.6 bash-only 45.4 全工具 +23.2 pp(bash-only 使文件定位失败率 16.0%→41.4%、未编辑终止率 1.2%→32.8%)
SWE-Bench Verified(四模型平均,窗口扫描) 管理档–T0 成功率差距(pp) 128k 下仅 2.7 32k 下 35.7 随窗口扩大衰减 13 倍,对应 T0 溢出率 78.7%→8.7%

局限与改进

作者承认的局限:(1) 结论只适用于他们实现的具体组件——规划只有一种 prompt+update_plan 机制,上下文管理只有一种固定阈值的压缩策略,动作空间是捆绑干预(同时改变工具可用性、接口指令、文件状态跟踪和自动编辑后诊断),因此无法把工具数量或动作粒度的效应单独剥离出来;(2) 受算力限制,规划与动作空间只在 T4/128k 默认配置下消融,并非全因子设计,无法确认这些效应在其他组件组合与预算下是否保持;(3) 每个设置每任务只跑一次,且 Terminal-Bench 仅 89 题,许多对比未达 McNemar 显著,TB 上的结论依赖跨模型跨预算的方向一致性而非个别显著单元格;(4) SWE-Bench Verified 仅限 Python,模型规模只是能力的不完美代理。我的补充观察:温度 0 的单次运行使成功率估计携带未量化方差;$B_1=0.6$/$B_2=0.85$ 的阈值从未被扫描,T4 的优势可能对阈值敏感;成本按 OpenRouter 标价计算,与本地部署的真实成本结构不同;'bash 熟练度'这一关键解释变量是推断出来的,并未被独立度量。

独立分析的弱点

(1) 统计功效不足:单次运行加 TB 仅 89 题,作者自己承认大量对比不显著。改进方向:对关键对比每任务重复 3–5 次并报告 bootstrap 置信区间,或改用多次运行的通过率均值。(2) 动作空间是捆绑干预:预定义工具自带 read-before-write 强制、文件状态跟踪和自动 ruff/pyflakes 诊断,而 bash-only 缺失这些隐形脚手架,所以'预定义工具 vs bash'的效应混杂了'状态跟踪与诊断支持'的效应。改进:增加'只读预定义工具+bash 写入'或'无诊断的工具集'等中间条件,把接口功能逐项拆开。(3) 阈值策略未调参:$B_1=0.6$、$B_2=0.85$、近期窗口 0.3 都是单点选择。改进:对 $(B_1,B_2)$ 做小规模扫描或引入自适应阈值,验证 T4 优势的稳健性。(4) 模型覆盖窄:仅一个家族的三个规模加一个跨家族模型,未包含最强闭源模型;'bash 熟练度'无法直接测量。改进:纳入 2–3 个家族并为每个模型报告独立的 shell 能力指标,把动作空间交叉点表示为该指标的函数。(5) 摘要质量未被评估:M3 用被测模型自身做摘要,弱模型摘要质量差可能伤害后续决策,这一交互未分析。改进:用固定强模型统一做摘要作对照,分离摘要器质量与策略本身的贡献。

未来方向

作者提出的方向:(1) 全因子设计,验证规划与动作空间效应在其他组件组合和上下文预算下是否持久;(2) 把 crossover 规律外推到其他模型家族、harness 实现以及软件工程之外的任务类型前需先做验证;(3) 与学习型(RL 训练模型自主管理上下文)方法对比。基于成果可延伸的方向:(1) 构建'条件化 harness 自动配置器'——依据模型的 bash 熟练度与任务的 shell 中心度自动选择动作空间与管理档,把本文的手工结论变成决策规则;(2) 研究省略 M1 何时真正造成失败:识别模型'本应召回却没有召回'的场景,判断值得为哪些信息类型保留无损通道;(3) 把规划从固定 prompt 泛化为可学习策略,解释并利用其在强弱模型上的角色转换(续命 vs 省钱);(4) 在更长窗口(200k+)与多模态观察下重复窗口扫描,检验'管理价值随窗口增大而衰减'的边界;(5) 对 M3 的摘要链做质量评估与增量修正优化,弱模型是否需要外部摘要器值得单独研究。

复现评估

复现难度中等偏低,但工程量不小。有利条件:论文对复现极为友好——附录 A 完整复述全部系统提示与规划/摘要/卡死检测模板,附录 B 逐字给出 9 个工具的自然语言描述,附录 C.7 给出全部 judge prompt,Algorithm 1 给出 T4 伪代码;关键超参齐全:温度 0、top-p 0.95、输出上限 16,384 token/轮、300 步上限、$B_1=0.6$/$B_2=0.85$、近期窗口 0.3(至少 2 轮)、工具结果截断 24k 字符、只读工具最多 8 个并行、卡死检测阈值 5/8 次;基础设施为 LangGraph + SGLang + Harbor,模型本地 BF16 部署或按 OpenRouter 价格调用,轨迹级分析还提供了经人工验证的标注方案(κ 0.929)。障碍:(1) 需要 Nemotron-3 30B/120B/550B 与 Mistral-Medium-3.5 的权重及大量 GPU(550B BF16 需多卡),算力门槛高;(2) 176 个设置 × 589 个任务的全量复现成本可观(Mistral 全工具在 SWE-Bench 上约 $3+/题);(3) 论文未见明确的开源代码或轨迹数据声明,harness 需自行重建。务实的复现路径是先在 1–2 个开源模型、单基准上验证核心结论(T4 vs T0、规划消融、bash crossover),这个规模在单机多卡上可行。

相似论文推荐