Self-Harness: Harnesses That Improve Themselves

Self-Harness: Harnesses That Improve Themselves

一句话理解

Self-Harness 固定模型参数,让目标模型根据自身执行轨迹中反复出现的失败机制,提出对当前 Harness 的小幅修改,并且只有修改通过 held-in 与 held-out 回归测试后才予以保留。

它改进的是模型外部的执行协议,不是模型权重。

理解大纲

1. 论文要解决的问题

Agent 的行为由两部分共同决定:

$$
\text{Agent behavior}
=
\text{base model}
+
\text{harness}
$$

论文中的 Harness 是模型外部的非参数脚手架,包括:

  • System prompt 和动态指令。
  • 工具、工具适配器和工具使用策略。
  • Memory 与 state management。
  • Verification rules。
  • Runtime policy、失败恢复与 orchestration。
  • Subagent、skill 和 middleware 等结构。

不同模型具有不同的工具使用习惯、错误模式和指令敏感性,因此同一套 Harness 不一定适合所有模型。论文提出的问题是:

不依赖人工工程师或更强的外部 Agent,目标模型能否参与改进自己正在使用的 Harness?

2. 三种 Harness 改进范式

论文区分:

  1. Human Harness Engineering:人工观察失败并修改 Harness。
  2. Meta-Harness:更强的外部 Agent 优化目标 Agent 的 Harness。
  3. Self-Harness:目标模型根据自身行为证据,提出对自身 Harness 的修改。

Self-Harness 的边界是:模型 $M$、Evaluator $E$、任务协议和工具集合保持固定,只允许修改预先声明的 Harness 表面。

3. 基本数学对象

  • $M$:固定语言模型。
  • $h_t$:第 $t$ 轮使用的 Harness。
  • $x_i$:一个任务实例。
  • $\tau_i$:执行轨迹,包括消息、工具调用和 verifier 结果。
  • $y_i$:Agent 的最终输出。
  • $E$:固定 Evaluator。
  • $z_i=E(x_i,\tau_i,y_i)$:任务结果,例如 pass 或 fail。
  • $r_i=(x_i,\tau_i,y_i,z_i)$:一次完整运行记录。
  • $D_{\mathrm{in}}$:向弱点分析阶段暴露执行轨迹的 held-in 集合。
  • $D_{\mathrm{ho}}$:不向 proposer 暴露轨迹、只用于晋升门禁的 held-out 集合。

运行关系可以写成:

$$
(\tau_i,y_i)=\operatorname{Run}(M,h_t,x_i)
$$

$$
z_i=E(x_i,\tau_i,y_i)
$$

被持续更新的是:

$$
h_0\rightarrow h_1\rightarrow\cdots\rightarrow h_T
$$

模型参数始终不变。

4. 第一阶段:Weakness Mining

首先在 $D_{\mathrm{in}}$ 上运行当前 Harness $h_t$,形成:

$$
R_t={r_i}{i=1}^{|D{\mathrm{in}}|}
$$

只保留失败记录:

$$
F_t={r_i\in R_t\mid z_i=\operatorname{fail}}
$$

对每条失败记录构造失败签名:

$$
\phi(r_i)=(c_i,q_i,m_i)
$$

  • $c_i$:Verifier 最终拒绝的直接原因。
  • $q_i$:相关 Agent 行为在失败中的因果地位。
  • $m_i$:轨迹暴露出的可复用行为机制。

采用完全相同的签名聚类:

$$
C_{\phi}
=
{r_i\in F_t\mid\phi(r_i)=\phi}
$$

每个 cluster 记录规模、代表任务、共同轨迹症状、Verifier 证据和推断出的 Agent 机制。最后形成 Evidence Bundle:

$$
B_t=\operatorname{BuildEvidenceBundle}(R_t)
$$

重点不是把所有 timeout 归为一类,而是区分造成 timeout 的不同机制,例如无限探索、重复失败命令或没有及时创建交付文件。

5. 第二阶段:Harness Proposal

论文让同一个固定模型 $M$ 在当前 Harness $h_t$ 下切换到 proposer 角色。它获得:

  • 当前 Harness 的可编辑表面。
  • $B_t$ 中的失败模式。
  • 应当保留的成功行为。
  • 过去已经尝试过的修改摘要。

模型并行产生 $K$ 个候选:

$$
\mathcal P_t
=
{(\Delta_j,a_j)}_{j=1}^{K}
$$

  • $\Delta_j$:Harness 修改算子。
  • $a_j$:Audit record,说明目标失败、修改表面、预期行为和回归风险。
  • $h_t^{(j)}=\Delta_j(h_t)$:应用修改后的候选 Harness。

提案原则是:

  • 不同候选之间保持多样性。
  • 单个候选内部保持最小修改。
  • 修改必须对应有证据且可由 Harness 解决的失败机制。
  • 不允许借机重写整个控制架构。

6. 第三阶段:Proposal Validation

定义 Harness $h$ 在两个 split 上通过的任务数:

$$
P_{\mathrm{in}}(h),
\qquad
P_{\mathrm{ho}}(h)
$$

候选相对当前 Harness 的变化为:

$$
\Delta_{\mathrm{in}}^{(j)}
=
P_{\mathrm{in}}(h_t^{(j)})-P_{\mathrm{in}}(h_t)
$$

$$
\Delta_{\mathrm{ho}}^{(j)}
=
P_{\mathrm{ho}}(h_t^{(j)})-P_{\mathrm{ho}}(h_t)
$$

接受条件是:

$$
\Delta_{\mathrm{in}}^{(j)}\ge 0,
\qquad
\Delta_{\mathrm{ho}}^{(j)}\ge 0,
\qquad
\max\left(
\Delta_{\mathrm{in}}^{(j)},
\Delta_{\mathrm{ho}}^{(j)}
\right)>0
$$

含义是:

  • 至少一个 split 变好。
  • 另一个 split 不能变差。
  • 只提高总分但牺牲某个 split 的候选也要拒绝。

若没有候选通过:

$$
h_{t+1}=h_t
$$

若多个兼容候选通过,则合并 accepted edits,形成 $h_{t+1}$。

7. Algorithm 1 的状态转移

一轮循环可以概括成:

$$
h_t
\xrightarrow{\operatorname{Evaluate}}
R_t
\xrightarrow{\operatorname{Mine}}
B_t
\xrightarrow{\operatorname{Propose}}
{h_t^{(j)}}{j=1}^{K}
\xrightarrow{\operatorname{Validate}}
h
{t+1}
$$

完整算法执行 $T$ 轮,最终返回:

$$
h_T
$$

这不是任意自我改写,而是 evidence-driven、validation-gated 的有界状态迁移。

8. 实验设置

  • Benchmark:Terminal-Bench-2.0。
  • 原基准包含 89 个任务,论文使用固定的 64 个任务子集。
  • 排除依赖不稳定外网资源以及初始 Harness 不支持的多模态任务。
  • 每个任务在全新容器环境中启动。
  • 每个候选 Harness 通常重复运行两次。
  • 初始 Harness:极简 DeepAgent 配置,只有短 system prompt、文件和 shell 工具以及声明好的可编辑接口。
  • 模型:MiniMax M2.5、Qwen3.5-35B-A3B、GLM-5。

9. 主要结果

模型 Held-in Pass Held-out Pass
MiniMax M2.5 43.0% → 50.0% 40.5% → 61.9%
Qwen3.5-35B-A3B 15.1% → 36.0% 23.8% → 38.1%
GLM-5 47.7% → 57.0% 42.9% → 57.1%

论文报告最大绝对提升为 21.4 个百分点,最大相对提升为 138%。

10. 学到的修改具有模型特异性

MiniMax M2.5:

  • 更早创建任务要求的输出文件。
  • 正确形成结构化工具内容。
  • 长时间工具调用后主动重定向执行。

Qwen3.5:

  • 预检依赖和 import。
  • 避免重复执行完全相同的失败命令。
  • 打断只探索、不实现的循环。
  • 工具错误后优先恢复 Verifier 所需文件。

GLM-5:

  • 让 PATH 和已安装工具跨 shell session 持久化。
  • 约束大型外部下载或计算。
  • 更快从探索转向实现、测试和产物检查。

三者的共同主题是提高任务要求产物的可靠交付,但具体干预方式不同。

11. 与 STOP、MCE 的区别

  • STOP:用 Meta-Utility 评价候选 Improver,让 Improver 的代码跨轮改写自身。
  • MCE:外层进化 Context Engineering Skill,内层根据 Skill 优化 Context function。
  • Self-Harness:固定同一个目标模型,从自己的失败轨迹中提出对 declared harness surfaces 的修改,再通过回归测试决定是否晋升。

Self-Harness 的突出特点不是搜索范围更大,而是修改有证据、范围受限、结果可审计并有非退化门禁。

12. 论文能支持的结论

论文支持的是:

在固定 Verifier、有限任务集和有界 Harness 编辑空间内,同一个模型可以根据自身失败证据,参与搜索更适合自己的执行协议。

论文没有证明:

  • 模型可以开放式、无限地改进自身。
  • 模型能力或参数发生了改进。
  • Self-Harness 能泛化到所有 Agent 环境。
  • 每一个 accepted edit 都具有跨 Benchmark 的普适性。

13. 值得继续追问的问题

  1. Held-out split 每轮都参与 promotion gate,因此更接近验证集;论文没有第三个完全不参与选择的最终测试集。
  2. Weakness Mining 中的因果归因和 failure signature 具体怎样实现,是否自身也依赖较强的判断能力?
  3. Algorithm 1 只显式验证各个候选,再把 compatible edits 合并;合并后的组合没有同轮回归门,而且 compatible 没有形式化定义,交互效应如何控制?
  4. 为什么使用通过任务数,而不是置信区间或显著性检验?每个候选两次重复是否足够?
  5. 没有与人工优化、Meta-Harness、随机搜索等优化器直接比较,收益中有多少来自 Self-Harness 特有设计?
  6. Failure clustering、并行提案、最小修改约束和 held-out gate 各自贡献多少?论文缺少组件消融。
  7. 64 个 Terminal-Bench 任务上学到的规则,会不会把 Benchmark 特有模式写进 Harness?
  8. v1 没有披露 proposal width $K$、明确的轮数 $T$ 配置、split 的任务数与清单、随机种子、置信区间以及完整搜索成本。
  9. Proposal 的 diverse/minimal 只是文字约束,没有候选距离或 edit-size 指标;该约束如何稳定执行?
  10. arXiv v1 和论文正文没有反链代码;团队公开投稿文章将 qzzqzzb/Self-Harness 列为项目地址,但仓库本身没有声明 official,且缺少依赖锁文件和完整复现说明。

阅读问答

Q1:先怎么理解整篇论文?

先抓住三个层次:

  1. 优化对象是 Harness $h$,不是模型 $M$。
  2. 优化信号来自聚类后的失败轨迹,而不是 proposer 对修改的主观判断。
  3. 修改只有同时满足“至少一个 split 变好、另一个不退化”的回归门禁才进入下一版 Harness。

后续问题继续追加在本节。

Q2:Harness 是什么?是否可以理解成包含 Memory、Skill 和规约的 Agent 构建方式?

这个理解基本正确。更精确地说,Harness 是固定模型外部、负责把模型组织成可运行 Agent 的非参数执行脚手架:

$$
\text{Agent system}
=
\text{Model }M
+
\text{Harness }h
+
\text{Environment}
$$

对于任务 $x$:

$$
(\tau,y)=\operatorname{Run}(M,h,x)
$$

Harness $h$ 决定模型怎样从任务产生整条轨迹 $\tau$ 和结果 $y$,包括:

  • 模型每次调用前收到哪些 system prompt、规约和动态 Context。
  • 暴露哪些工具、API、Skill、Subagent 以及权限。
  • Memory 如何保存、检索、加载和压缩。
  • 多轮调用如何编排,何时重试、分解、停止或切换策略。
  • 工具错误、超时和缺失产物怎样恢复。
  • 结果如何验证,结束前必须执行哪些检查。
  • Token、工具调用次数和运行时间等预算如何控制。

因此 Memory、Skill 和规约通常都是 Harness 的组成部分,但 Harness 比它们更大:它还包括把这些组件组合起来并在运行时执行的代码、配置和控制逻辑。

需要区分:

  • Model:参数化的预测能力,权重属于模型,不属于 Harness。
  • Context:某一次模型调用实际看到的内容,是 Harness 运行后产生的输入之一。
  • Skill:可按需加载的能力说明、知识和操作流程,是 Harness 可以管理的一类组件。
  • Memory:跨步骤或跨任务保存与取回信息的机制,也是 Harness 的一个子系统。
  • Harness:管理上述组件并控制整条 Agent 执行轨迹的运行层。
  • Agent architecture:更宽泛的设计概念;Harness 是其中真正落地并驱动模型运行的可执行部分。

论文 Figure 3 的初始 Harness 具体声明了 system prompt、memory sources、subagents、skills、bootstrap/execution/verification/failure-recovery instructions 和 runtime-control policy。Self-Harness 修改的正是这些声明好的表面,而不是模型权重。

Q3:对于单个 Agent,也存在 Harness 吗?

存在。Harness 不以多 Agent 为前提。对于一个最小的工具型 Agent,仍然需要运行代码完成:

$$
\text{任务输入}
\rightarrow
\text{构造模型 Context}
\rightarrow
\text{调用模型}
\rightarrow
\text{解析 Tool Call}
\rightarrow
\text{执行工具并回填观察}
\rightarrow
\text{继续或停止}
$$

负责上述循环的代码、Prompt、工具 schema、历史管理、错误处理和停止条件,就是该单 Agent 的 Harness。Subagent 或多 Agent orchestration 只是 Harness 可选的扩展能力。

需要区分:

  • 只有一次输入输出的裸模型调用,可以不称为 Agent,其外围驱动也可能非常薄。
  • 一旦系统让模型持续观察、调用工具、更新状态并决定下一步,就已经存在某种 Harness,即使它只有几十行代码。
  • 多 Agent 系统是在 Harness 中进一步加入 Agent 创建、任务分配、通信和结果聚合机制。

论文使用的初始 DeepAgent 就是单 Agent Harness:它只有短 system prompt、默认文件和 shell 工具,subagents=[]skills=[],但仍然具有 Agent 执行循环。因而“没有 Subagent”不等于“没有 Harness”。

在工程实现中,Harness 经常被封装在名为 Agent 的类或框架内部,所以代码表面上看不见独立的 Harness 对象;这是实现封装,不代表概念上的运行层不存在。

Q4:Agent 是否就是 Model、Harness 和 Environment 在某个模块上的子集?

接近,但更严格的边界是:

$$
\text{Agent }A=\operatorname{Instantiate}(M,h)
$$

$$
\text{Agent–Environment System}=A+\operatorname{Environment}
$$

Environment 通常不是 Agent 本体的一部分,而是 Agent 观察和作用的外部对象。交互循环是:

$$
o_t
\xrightarrow{A=(M,h)}
a_t
\xrightarrow{\operatorname{Environment}}
(s_{t+1},o_{t+1})
$$

  • Model $M$ 提供推理与生成能力。
  • Harness $h$ 把历史和观察组织成模型输入,把模型输出翻译成 Action,并控制工具循环、状态、验证和停止。
  • Environment 保存外部状态,接收 Action,并返回新的 Observation。

工具需要按边界拆开理解:工具的 schema、调用策略、权限和 adapter 通常属于 Harness;Shell、文件系统、数据库或远程服务的真实状态通常属于 Environment。

如果讨论特定业务模块或任务域 $d$,可以写成:

$$
A_d
=
\operatorname{Instantiate}
\left(M,h_d,\operatorname{toolScope}_d,\operatorname{permissionScope}_d\right)
$$

$A_d$ 更适合称为通用 Agent 系统在领域 $d$ 中的配置实例或运行切片,而不是集合论意义上的“子集”。它复用同一个模型,但具有该领域自己的 Prompt、Memory、Skill、工具范围和权限。

在 Self-Harness 论文中,可以理解为:

$$
A_t=(M,h_t)
$$

Terminal-Bench 容器是 Environment。每轮保持 $M$、Environment、Evaluator 和任务协议不变,只把 $h_t$ 更新为 $h_{t+1}$;因此模型没变,但 Agent 的运行行为发生了变化。

为避免歧义,前文“Agent system = Model + Harness + Environment”应理解为完整的 Agent–Environment 运行系统,而不是严格的 Agent 本体定义。

Q5:是否可以把除 Model 以外的所有部分都理解为 Harness?

可以作为第一层近似:

$$
\text{Agent}\approx\text{Model}+\text{Harness}
$$

但不能把完整系统里所有非模型组件都归入 Harness。更准确的判定标准是:

某个非参数组件如果负责控制固定模型怎样观察、记忆、行动、验证、恢复或停止,它通常属于 Harness;如果它是 Agent 操作的外部对象、任务来源或裁判,则不属于 Harness。

组件 是否通常属于 Harness 原因
System prompt、规约 控制模型行为
Context 构造与历史压缩 决定模型看到什么
Memory 检索与写入机制 控制信息怎样跨步骤保存
Skill loader 决定何时加载能力说明
Tool schema、adapter、调用策略 决定模型可执行哪些 Action
重试、超时、预算、停止规则 控制执行循环
Verification 与失败恢复逻辑 控制 Agent 怎样自检和纠错
文件系统、数据库、外部 API 的真实状态 属于 Environment
用户给出的任务实例 属于 Task input
Benchmark Verifier / Evaluator 通常否 是外部裁判
模型权重与网络结构 属于 Model

Tool 需要拆成两部分:工具的 schema、权限和调用 glue code 属于 Harness;工具实际操作的服务和状态属于 Environment。

Self-Harness 论文的优化对象还更窄:它不是修改所有非模型代码,而只修改 Harness 中预先声明的 editable surfaces。Environment、Evaluator、任务划分、模型参数以及 Benchmark 协议都固定。

Q6:Trajectory 一般怎样记录?

Trajectory 是一次 Agent episode 中按因果和时间顺序发生的可观察事件序列:

$$
\tau
=
(o_0,a_0,o_1,a_1,\ldots,o_T,y)
$$

  • $o_t$:Agent 在第 $t$ 步得到的 Observation。
  • $a_t$:Agent 在第 $t$ 步执行的 Action,例如文本回复或 Tool Call。
  • $y$:最终输出。

LLM Agent 中通常需要记录:

  1. Task start:任务 ID、输入、环境版本和 Harness 版本。
  2. Model request:模型名称、可见 messages、工具 schema 和采样参数。
  3. Model response:可见文本、Tool Call、token usage 和 finish reason。
  4. Tool execution:tool name、call ID、参数、开始/结束时间和权限信息。
  5. Tool result:stdout/stderr、exit code、返回值、耗时、超时或截断状态。
  6. State event:Memory 读写、Context 压缩、Skill 加载和 Subagent 创建。
  7. Error/recovery:异常、重试、策略切换和预算变化。
  8. Finalization:最终答案、产生的 artifacts 和停止原因。
  9. Evaluation:Verifier 结果、score 和失败原因。

工程上通常使用 JSONL 或 tracing span 记录,每个事件具有统一 envelope,例如:

{
  "trace_id": "tr-42",
  "span_id": "sp-7",
  "parent_span_id": "sp-3",
  "seq": 12,
  "timestamp": "2026-07-23T15:20:00Z",
  "event_type": "tool.result",
  "actor": "agent",
  "payload": {
    "call_id": "call-9",
    "tool": "shell",
    "exit_code": 0,
    "duration_ms": 184
  }
}

trace_id 关联整次任务,span_idparent_span_id 表示调用关系,seq 保留逻辑顺序。单 Agent 串行运行时可以看成列表;存在并行工具或 Subagent 时,整体更接近一棵树或 DAG。

通常不会把所有大文件或超长工具输出直接塞入 trace,而是记录 artifact URI、摘要、hash 和截断标记。还应记录模型、Prompt、Harness 和 Environment 版本,才能复现同一运行。

安全上需要对 API key、Token、Cookie、个人信息和业务敏感字段进行脱敏。Trajectory 记录的是系统可观察事件,不应假设能够取得或保存模型隐藏的内部 Chain-of-Thought。

Self-Harness 中一次运行记录为:

$$
r_i=(x_i,\tau_i,y_i,z_i)
$$

其中 $x_i$ 是任务,$\tau_i$ 记录 messages、Tool Calls 和 Verifier evidence,$y_i$ 是最终输出,$z_i$ 是 pass/fail。论文随后从失败记录中提取 failure signature,用于 Weakness Mining。

Q7:论文是否有 GitHub?本地能否运行?

找到高可信论文项目仓库:

https://github.com/qzzqzzb/Self-Harness

本地以 Git submodule 固定到:

prjs/Self-Harness
commit 2720dbb3f52283684f4b85a1065d642df1779dd8

官方性需要保守表述:仓库标题、arXiv ID、论文图片、实验结果和目录结构均与论文一致,论文团队的公开投稿文章也把它列为项目地址;但 arXiv v1、论文正文与作者主页没有反向链接,仓库 README 也没有使用 official 字样。

2026-07-24 使用 Python 3.12.13 完成最小运行验证:

  • 5,823 行 Python 源码全部通过 compileall
  • Acceptance、Proposer、Materializer、Harbor Eval、Workflow 五个 CLI 均能正常解析 --help
  • 用两条相同 failure signature 的合成失败记录执行 Weakness Mining,正确聚成一个大小为 2 的 cluster。
  • 构造两个 Proposal route,成功生成 3,064 字符的 proposer prompt。
  • 用合成结果执行 Acceptance Gate:train pass rate 增加 0.25,held-out 不变,结果为 accepted: improved train with no split drops

完整 Terminal-Bench-2.0 实验尚不能按仓库直接复现,原因是:

  • 仓库没有 requirements.txtpyproject.toml、lockfile 或版本化安装说明。
  • 当前环境缺少 deepagentsharbor
  • 示例配置依赖仓库外部的 eval project、Docker/Harbor 任务环境和模型服务。
  • 论文中的本地 Qwen3.5-35B-A3B 配置使用四张 NVIDIA H200。

因此当前结论是:仓库核心的 diagnosis、proposal construction 和 acceptance 逻辑能够本地执行;论文的完整 64-case 模型实验需要额外重建环境,不能把 smoke test 等同于论文结果复现。