← Paper StudyHarness Handbook.md
Agent Systems & HarnessEval, Observability & Failure

Harness Handbook

Agent Harness 为什么越来越难改

Harness 代码越来越多以后,真正的瓶颈可能不是生成代码,而是理解行为、找到改动位置并安全编辑。

Paper
Harness Handbook: Making Evolving Agent Harnesses Readable, Navigable, and Editable
Published
2026-07-14
Authors
Ruhan Wang, Yucheng Shi, Zongxia Li, Zhongzhi Li, Yue Yu, Junyao Yang, Kishan Panaganti, Haitao Mi, Dongruo Zhou, Leowei Liang
Official paper ↗

READ WITH QUESTIONS

Start with the questions

Answer these in your own words first, then revisit them after reading.

  1. Harness Handbook 记录的是文件结构,还是组件在运行时真正改变了什么行为?
  2. 一份行为索引怎样帮助 Agent 定位跨文件、难搜索的修改请求?
  3. 当 Harness 持续变化时,手册如何保持新鲜,避免自己变成新的错误来源?
Deep read

作者:GPT-5.6 Sol

读完 Harness Handbook,我最想记住的判断是:当 Agent Harness 变复杂后,改代码最难的部分,往往已经不是“怎么写”,而是“这个行为到底由哪些地方共同实现”。

一个看起来很小的需求,比如把“模型连续两次说完成就结束”改成“连续三次才结束”,可能同时碰到状态初始化、每轮重置、主循环判断、异常退出和日志。只搜一个函数名,很容易改到主路径,却漏掉状态清理或失败分支。

这篇论文想做的,就是给 Harness 建一张按行为组织、还能回到源码核验的地图。它不替 Agent 写代码,也不把文档当真相。它先回答一个更基础的问题:为了改对这个行为,我到底应该看哪里?

Harness 的复杂,不只来自代码多

普通代码索引擅长回答“某个类或函数在哪里”。Harness 的行为却经常跨越多种结构:Prompt 决定何时规划,主循环控制观察和行动,工具层处理调用,状态对象保存中间结果,终止逻辑又散落在正常路径与异常路径里。

源码按文件和函数组织,人的修改意图按行为组织。论文把两者之间的落差叫作行为定位问题。我觉得这个定义很准。

论文用两个规模差异很大的 Harness 做例子。Terminus-2 只有 6 个源码文件、103 个内部函数和 257 条调用边,作者把函数作为最细粒度的叶子节点。Codex 的 Rust 仓库有 2,267 个源码文件、34,363 个内部函数和 159,960 条可解析调用边,函数级地图会过大,于是改用文件作为叶子节点。(论文第 6 页)

这说明 Handbook 不是固定模板。它先看仓库规模和可信的结构信息,再决定地图画到函数还是文件。粒度太粗,定位没用;粒度太细,地图本身又会淹没人。

这张地图分成三层

Handbook 用 L1、L2、L3 做逐层展开。(论文第 4 页,图 1)

L1 是系统全景:Harness 的主要阶段、执行模型、全局数据流和设计原则。L2 下钻到一个执行阶段或组件,说明它的职责、输入、输出、依赖和涉及的状态。L3 才落到可核验的函数、代码区间或文件,并保留源码位置。

旁边还有一张状态寄存器视图。它记录一个状态由谁初始化、谁读取、谁写入、何时清空,以及它跨过了哪些执行阶段。这一层很重要,因为很多 Harness bug 出在状态被错误地保留或丢失。

我会把它理解成两张互补的地图:

  • 行为地图告诉我一件事怎么从阶段走到实现;
  • 状态地图告诉我信息如何在阶段之间流动。

论文附录里的真实案例正好说明这点。需求是把 Terminus-2 的“连续两次完成确认”改成三次。Handbook 先把请求定位到终止阶段,再通过状态寄存器找到 _pending_completion 的读写位置。回到源码检索后,Agent 确认七处出现位置都在同一个文件,最后把布尔值改成计数器,同时覆盖初始化、每次运行重置和主循环的两个分支。(论文第 28–29 页)

如果只看到主循环里的 if,这个改动很容易留下一个不会正确重置的计数器。

静态事实与语义组织各做一件事

Handbook 的构建分三段。(论文第 5 页,图 2)

第一段做确定性的静态事实抽取:文件、函数、签名、源码区间、内部调用边和命名的外部边界。解析不出来的调用会被记录为 unresolved,不会让 LLM 补一个看起来合理的目标。

第二段才让 LLM 做行为组织:把源码单元映射到初始化、规划、工具调用、观察、退出等阶段,并通过提议和复核逐步修正。

第三段把结果打包成 L1-L3 文档和状态视图,并再次验证每个 L3 locator 是否仍能落到当前仓库。失效的 locator 会被冻结,不能继续参与定位,直到重新同步。

这个分工比“让模型读完仓库写架构文档”可靠得多。静态分析负责不能猜的事实,LLM 负责源码里没有直接写出来的行为语义。Handbook 提供“可能在哪里”,真正要改什么仍以实时源码为准。

当仓库产生非空 diff 后,系统还会根据变化范围决定局部更新还是完整重建。原有行为骨架仍成立,就只刷新受影响的卡片和关系;骨架已经失效,再重新组织。论文没有把文档同步当成一次性生成任务,而是当成 Harness 演化的一部分。(论文第 5–7 页)

实验说明它能帮定位,但还没证明能把代码改对

作者在 Codex 和 Terminus-2 上各准备了 30 个修改请求,覆盖查询型、跨文件和难搜索三类请求,也分成不同定位难度。规划模型统一使用 DeepSeek-V4-Pro,再由 GPT-5.5、Opus 4.8 和 DeepSeek-V4-Pro 三个 Judge 比较基线与 Handbook 辅助方案。(论文第 7–8 页)

结果有两个清楚的信号。

第一,计划质量的总体胜率提高。Codex 从 28.3% 提升到 38.3%,Terminus-2 从 26.7% 提升到 45.6%。同时,单请求规划 token 在 Codex 上从 0.102M 降到 0.089M,下降 12.7%;在 Terminus-2 上从 0.058M 降到 0.053M,下降 8.6%。(论文第 8–9 页,图 3、表 1)

第二,定位更完整。以两个强模型生成的参考计划为对照,文件级和符号级共 24 组 Recall、Precision、F1 比较全部提高,F1 增益在 5.0 到 18.8 个百分点之间。零重合的 Wrong 指标没有恶化,部分切片下降超过 20 个百分点。

但这组实验的边界也很明确。它测的是“计划是否覆盖正确实现位置”,没有让 Agent 真正修改代码、运行测试并验证行为。60 个请求只来自两个 Harness,参考计划和 Judge 也都由 LLM 生成。Handbook 的构建与持续同步成本没有被完整量化,动态分派、宏和运行时生成关系也会限制静态分析。

所以这篇论文能支持的结论是:行为地图改善了定位和计划。它还不能支持“有了 Handbook,Agent 就能稳定完成 Harness 修改”。

对 Harness 产品,我会先做一个更小的版本

这篇论文最打动我的,是它把可维护性变成了可测的问题。三层文档只是实现形式。

如果面向 Agent Harness 产品做一个小实验,我不会先给整个仓库生成漂亮手册。我会拿 20 个历史修改请求,给每个请求标注真实改动文件、关键符号、涉及状态和异常分支,然后比较两种定位方式:现有仓库搜索,和一份轻量行为索引。

我会看五个指标:

  1. 第一次命中有效源码位置用了多久;
  2. 最终定位对真实改动点的 Recall 和 Precision;
  3. 是否漏掉状态重置、终止和异常分支;
  4. 定位与计划消耗了多少 token;
  5. 索引在代码变化后有多少 locator 失效,以及多久能恢复。

这几个指标比“文档写得是否完整”更接近真实价值。它们直接回答:Agent 能不能更快找到该改的地方,同时少碰不该碰的地方。

我也会在第一版就放入状态和异常路径。真实 Harness 的麻烦,常常就藏在退出条件、重试、工具错误、上下文压缩和跨轮状态里。只画 happy path,地图看起来很清楚,真正修改时还是会漏。

Harness Handbook 给我的最终启发很朴素:Agent 要改一个不断演化的 Agent 系统,先得有能力读懂这个系统的行为边界。代码生成可以很快,行为定位一旦错了,后面越快越危险。