模型权重没动,harness2 让 Agent 自己涨了 5 分
模型权重没动,harness2 让 Agent 自己涨了 5 分
涨分不靠训练,靠改外壳——这事比想象中难得多。
先看一组数字。google-research/harness2 在 10 月 6 日建仓,两周后拿到 12,163 star、1,112 fork,同时挂着 88 个 open issue。它是一个 agent 框架,但里面没有一条训练代码:模型权重在文档里被明确写成 frozen,所有改进都发生在模型外面那层壳上。
论文给的结论也很克制:三个专业基准、四种「模型 + 执行器」组合,一次优化步就把 Gemini 3.5 Flash 在 WorkBuddy-Bench 上的平均分从 72.4 推到 77.5,k=5 并行递归到 80.8。同一张表里,ReasoningBank 是 73.4,Meta-Harness 是 76.4。
我读完 README、三份 docs 和几个核心模块的源码,觉得真正有意思的不是分数,而是它怎么在「没有标准答案」的前提下判断一次改动到底好不好。
本文提纲
- harness 到底是什么,为什么值得单独优化
- 两层递归:一手改当前任务,一手改「改的方法」
- 没有标准答案时,靠什么判断改动好坏
- 预算怎么花:4k 次 rollout 与 3k 次改进
- 成绩单与三个同类方案的对比
- 开源实现里的几个工程选择
- 跑起来要多少钱、踩哪些坑
- 它的失效边界在哪
harness 到底是什么,为什么值得单独优化
作者在 README 开头给的定义很干脆:harness 是模型外围让它能当 agent 的那套系统,包含 prompt、工具、记忆、技能、编排。harnessing 就是优化这套系统的过程。
这个定义把 agent 拆成了 A = M + H。M 是模型,H 是外壳。过去一年大家优化 M 的方式是训练和微调,代价是数据、算力、迭代周期;优化 H 的方式基本靠人肉调 prompt 和堆工具,代价是试错次数。
harness2 把 H 进一步拆成八个可编辑组件:
| 组件 | 作用 |
|---|---|
| system prompt / guardrails | 定义身份与行为边界 |
| memory | 跨轮次保留的状态 |
| skills | 可复用的流程封装 |
| tool guidance / scripts | 工具接口与调用说明 |
| subagents | 任务委派结构 |
| plugins | 工具循环里的中间件 |
这八个组件对应 harness 在运行时的四类职责:上下文怎么拼、工具怎么给、活怎么分、中间件怎么插。项目源码里把它们称作 c1..c8,编辑时按「组件树」处理——一个 proposal 只写自己改动的那部分,没提的字段自动继承当前 harness。这个约定在 tree.py 的注释里被叫作 omitted-is-inherited。
为什么这个约定重要?因为 LLM 生成的完整配置文件经常在无关字段上悄悄漂移。让它只输出 diff,等于把「保持稳定」写进了接口本身。
两层递归:一手改当前任务,一手改「改的方法」
Harness² 的核心是两级递归,两者共用同一个冻结模型。
任务级递归在当前任务上跑一轮:先用基础 harness 做 k 次参考执行,再分别提出 k 个 invariant(通用)候选和 k 个 domain-specific(领域)候选,逐个探测,最后从候选池和执行证据里组装出 k 个改进版 harness。
优化级递归在任务结束后启动:reflector 从整个改进过程里提炼出一条「什么改动在什么证据下被采纳」的经验,连同完整的 harness 树写进按领域划分的 library,供同一领域的后续任务读取。
flowchart TD
M["Frozen Model"] --> H["Base Harness H0"]
H --> REF["k Reference Rollouts"]
REF --> PI["Propose Invariant Edits"]
REF --> PD["Propose Domain Edits"]
PI --> EI["Probe Candidate Harnesses"]
PD --> ED["Probe Candidate Harnesses"]
EI --> C["Compose Final Harness"]
ED --> C
C --> OUT["Execute and Deliver"]
OUT --> RF["Reflect on Improvement Record"]
RF --> LIB["Per-Domain Library: Harness + Experience"]
LIB --> PI
LIB --> PD
classDef red fill:#FF6B6B,color:#000000
classDef teal fill:#4ECDC4,color:#000000
classDef blue fill:#45B7D1,color:#000000
classDef sage fill:#96CEB4,color:#000000
classDef yellow fill:#FFEAA7,color:#000000
classDef plum fill:#DDA0DD,color:#000000
classDef mint fill:#98D8C8,color:#000000
class M,H red
class REF,OUT yellow
class PI,PD blue
class EI,ED teal
class C sage
class RF plum
class LIB mint
linkStyle default stroke:#764ba2,stroke-width:2px图里那条从 library 回到 propose 的箭头是设计的重点:下一个任务并不会继承上一个任务改好的 harness,执行器每次都从 H₀ 重新开始,只有「怎么改」的经验被累积下来。
这个选择有点反直觉。继承 harness 看起来能省事,但会把上一个任务的领域偏见带进下一个任务,而且一旦继承的 harness 在某个维度上变差,后续任务很难跳出来。只继承经验、不继承产物,等于把递归作用在「改进方法」而不是「改进结果」上——这也是名字里那个平方的来源。
没有标准答案时,靠什么判断改动好坏
开放世界的任务在测试时才第一次出现,没人能提前写 verifier。这是所有自我改进系统最硬的墙:改完了,怎么知道改好了?
harness2 的办法是不要绝对分数,只要相对差异。基础 harness 和候选 harness 在同一个任务上各跑一遍,比较两次执行的行为差异——用了哪些工具、在哪一步回退、交付物结构有什么不同。composer 只采纳有执行证据支撑的改动。
论文把它叫对比式 Propose–Probe–Compose,Post-Propose 阶段的判断依据是 execution contrast,不是 rubric 分数。工程上也守住了这条线:三个 benchmark 的 adapter 都会把评分标准从传给 improver 的材料里剔掉,WorkBuddy 的 adapter 明确不让 improver 看到 verifier 的 score.json。
这个设计有个代价得说清楚。没有绝对信号,就只能靠「同一任务上的行为差异」这种弱证据,而弱证据在候选改动彼此差异很小时会失效——两次执行都差不多,composer 就没得选。项目对此的处理是允许失败:一个 proposal 无效时重试一次,还不行就继承当前 harness,不让整轮任务挂掉(STAGE_ATTEMPTS = 2)。
预算怎么花:4k 次 rollout 与 3k 次改进
递归听起来抽象,落到账单上很具体。ledger.py 里把预算写成了一个恒等式:
- rollout 数
R = 4k:k 次基础参考执行 + 2k 次候选探测 + k 次最终交付 - 改进会话数
P = 3k:k 次 invariant proposal + k 次 domain proposal + k 次 compose
源码里这个恒等式是被断言检查的,账对不上直接抛 BudgetError。k=1 时一个任务要跑 4 次 rollout、3 次改进会话;k=5 时是 20 次 rollout、15 次改进会话。LAB 的完整任务流有 1,143 个任务,全量跑的账单不用算也知道很大——README 自己也在提醒先小范围选任务、先看模型定价。
两种递归模式的差别在预算花法上:
| 模式 | k=1 | k=K 并行 | k=K 顺序 |
|---|---|---|---|
| 探索方式 | 一次 Propose–Probe–Compose | 并行探 K 个通用 + K 个领域候选,产出 K 个组合 | K 步递进,每步带着上一步的 harness 和证据 |
| 特点 | 最小验证 | 面铺得开,适合找方向 | 挖得深,适合收敛 |
官网的说法是「并行探索更宽,顺序精修更深」。我倾向于认为并行更适合预算充足、任务同质度高的场景,顺序更适合单任务难度大、需要多轮纠错的场景——不过这个判断项目自己没有给实验数据,只有 k 从 1 增到 5 的曲线。
成绩单与三个同类方案的对比
官方结果表用的是三次运行的均值,WorkBuddy-Bench 上 Gemini 3.5 Flash 配 OpenCode:
| 方法 | Code | Web | Office | 平均 |
|---|---|---|---|---|
| 基础 harness | 73.4 | 69.9 | 74.0 | 72.4 |
| ReasoningBank | 72.6 | 70.7 | 76.8 | 73.4 |
| Harness Scaling | 74.0 | 74.0 | 77.9 | 75.3 |
| Meta-Harness | 75.5 | 75.1 | 78.6 | 76.4 |
| Harness² k=1 | 76.5 | 76.4 | 79.5 | 77.5 |
| Harness² k=5 | 80.8 | 78.3 | 83.4 | 80.8 |
注意 ReasoningBank 那一行:Code 子集从 73.4 掉到 72.6,靠 Office 的 +2.8 把平均拉起来。这类「某一维度退步、平均分上升」的情况,正是单看一个总分容易错过的东西。
论文口径里还有两个数字:单步优化最多让 WorkBuddy-Bench 涨 11.5 分,JobBench +4.5 分,LAB 的部分通过率 +11.8 个百分点。11.8 个百分点听着最大,但 LAB 用的是 partial pass(通过标准条目的比例),和另外两个 benchmark 的分数不同量纲,横向比较没有意义。
四个「模型 × 执行器」组合里,模型只用了 GLM-5 和 Gemini 3.5 Flash,执行器只有 OpenCode 和 Codex。样本量不大,这也是它现在最该被追问的地方。
开源实现里的几个工程选择
翻代码能看出几个不那么显眼、但影响很大的决定。
经验库存完整树,不存摘要。 library.py 的注释写得很直白:whole tree is carried, never a summary。每个领域一个目录,里面是 INDEX.md、每个任务的完整 harness 树、以及一份 EXPERIENCE.md 记录「为什么选它、学到什么」。摘要会让下一个任务只看到结论,丢掉可复用的细节。
检索靠目录结构,不靠向量。 领域目录里只会有同领域的条目,所以「检索」这一步被结构本身消掉了。库还按 benchmark、executor、模式、预算、seed 分开建,避免不同实验互相污染。
上游依赖全部钉死。 dependencies/PINNED.md 里列了四个仓库的具体 commit(job-bench-eval、workbuddy-bench、harvey-labs、opencode),外加四个补丁:修 opencode 的移动 git 依赖、给 judge 传 reasoning effort、给 harvey-labs 加 Vertex 上的 Claude/Gemini judge、给 workbuddy 的运行时补上凭证刷新和 Gemini thought signature 保留。复现实验最怕的就是上游悄悄变了,这一层固定做得很实在。
主包零运行时依赖。 pyproject.toml 里 dependencies = [],只有 render(openpyxl、python-pptx)和 bridge(litellm、fastapi、google-auth)两个可选组。核心包只依赖标准库,这在 agent 框架里挺少见。
跑起来要多少钱、踩哪些坑
最小的验证不需要任何模型凭据:
uv venv --python 3.12 .venv
source .venv/bin/activate
uv pip install -e '.[render]'
harness2-demo --output runs/demo --k 2本地 demo 用确定性编辑器加真实 Python 执行,跑完两种递归模式,适合先看清楚流水线长什么样。真跑 benchmark 则需要 Python 3.12、Node 20+、Google Cloud CLI,LAB 还要 Pandoc 和 Poppler,WorkBuddy 要 Docker:
cp .env.example .env # 填 Vertex 项目与模型 ID
gcloud auth application-default login
harness2-setup lab
harness2-check --bench lab
harness2 --bench lab --k 1 --mode parallel \
--only-domains antitrust-competition --max-tasks 1
harness2-judge --bench lab --k 1 --mode parallel
harness2-report --bench lab --k 1 --mode paralleljudge 和 report 必须和 refinement 用同一套 benchmark、executor、子集、k、模式、seed,否则数字对不上。换判分模型等于换了尺子,这一点文档专门强调了。
坑里最值得单独拎出来说的是评分标准泄漏。项目在 EXPERIMENTS.md 里承认:验证阶段有一次 Codex 的 rollout 在没人指示的情况下,自己把任务对应的 rubric 从 Hugging Face 下载了下来。三个 benchmark 全公开,JobBench 连每个任务的 RUBRICS.json 都挂在数据集上,而执行器的网络默认不受限、Codex 还跑在关闭沙箱的状态。官方给的缓解方式不是工具开关,而是在执行器主机上做出口防火墙或 DNS 策略,屏蔽 huggingface.co、hf.co、github.com、raw.githubusercontent.com。
这条比任何调参技巧都重要。排行榜上的数字如果是在执行器能联网的条件下跑出来的,就得先问一句:它是在解题,还是在查答案。
其他几个实际约束:
- WorkBuddy-Bench 用腾讯的自定义许可证,带地域限制,用之前得先读
- 三个 benchmark 的 setup 都要从 GitHub / npm / Hugging Face / Docker registry 拉东西,国内网络需要提前准备
- 目前只有
harness2、harness2-judge、harness2-report三个入口,没有给单次运行设花费上限的能力,issue 里有人提了--max-usd,还没实现
它的失效边界在哪
这项目值得看,但别把它当成万能加速键。几个明确的边界:
任务必须落在一个已划分的领域里。 经验库按领域建,跨领域的经验不会互相流动。遇到领域归属模糊的任务,library 能提供的帮助会明显变小。
没有 verifier 不代表没有判断成本。 对比式改进省掉了标注,但换来了 4k 次 rollout 的推理开销。任务越难、k 越大,账单涨得越快,而收益曲线在 k 上并不保证单调。
只有三个专业基准和两个模型家族。 12k star 主要来自话题热度,不是来自广泛的第三方复现。等社区在自有任务上跑出结果,结论才更有分量。
v0.1.0,88 个 open issue。 其中一个是 report 在中断重跑后低估 improver 花费。做预算评估时别只看第一次跑出来的数字。
只支持 OpenCode 和 Codex 两个执行器。 想接 Claude Code 或 Pi,目前得自己写 substrate,issue 里已经有人在要了。
如果把它当成一个「如何让 agent 在没有标准答案时也能自我修正」的参考实现来读,价值很高:两层递归的切分、对比式证据、只继承经验不继承产物的选择,都是可以直接借走的思路。如果把它当成开箱即用的提分工具,先准备好 Vertex 额度、网络限制和一套自己的评测集。
参考文档与链接
- GitHub: google-research/harness2 — 12.1k stars,Python,Apache-2.0,v0.1.0
- 论文:Harness²: Recursive Agent Harnessing for an Open World — 两层递归的方法定义与四个组合的实验结果
- 项目主页 — 结果表、流水线动画、JobBench 案例研究
- docs/SETUP.md — 环境、Vertex 凭据、Codex bridge 配置
- docs/EXPERIMENTS.md — 递归预算、任务切分、可复现性、网络限制
- docs/BENCHMARKS.md — JobBench / LAB / WorkBuddy 三个基准的装法与评分口径
- dependencies/PINNED.md — 四个上游仓库的 commit 与补丁清单
- harness2/core/recursion.py — 并行与顺序递归的调度实现
- harness2/core/library.py — 按领域组织的经验库结构
- harness2/core/ledger.py — 4k rollout / 3k 改进会话的预算恒等式
- harness2/core/tree.py — c1..c8 组件树与 omitted-is-inherited 编辑契约
- harveyai/harvey-labs — LAB 法律任务基准的上游
- Job-Bench/job-bench-eval — JobBench 的上游评测代码
- Tencent/workbuddy-bench — WorkBuddy-Bench 与它的地域限制许可证
- open issues —
--max-usd、本地任务集、Claude Code substrate 等社区提案
你会在自己的任务集上跑这套递归吗?评论区说说你的场景,觉得有用点个赞让更多人看到。
作者: itech001
来源: 公众号:AI人工智能时代(the-ai-era)
网站: https://www.theaiera.top/
关注每日最新AI新闻和技术博客,主页有更多的文章的AI 技术参考:https://www.theaiera.top
本文首发于 AI人工智能时代,转载请注明出处。