论文解读:Meta-Harness —— 让 AI 自动优化 AI 的"外壳"

TL;DR — 同一个 LLM,只改外围代码(harness:决定给模型看什么、记什么、怎么检索的那层代码),性能可以差 6 倍。Stanford 的 Meta-Harness 论文提出:把"如何优化 harness"这个问题本身交给 Coding Agent,让它读取所有历史候选方案的源码、得分和执行日志,然后自动写出更好的 harness。结果:文本分类超 SOTA 7.7 分且省 4× token,数学推理跨 5 个未见模型平均提升 4.7 分,TerminalBench-2 上 Haiku 4.5 排名第一。
论文信息
| 项目 | 内容 |
|---|---|
| 标题 | Meta-Harness: End-to-End Optimization of Model Harnesses |
| 作者 | Yoonho Lee, Roshen Nair, Qizheng Zhang, Kangwook Lee, Omar Khattab, Chelsea Finn |
| 机构 | Stanford, KRAFTON, MIT |
| 发表 | arXiv:2603.28052, 2026-03-30 |
| 项目页 | yoonholee.com/meta-harness |
| 代码 | github.com/stanford-iris-lab/meta-harness-tbench2-artifact |
一、问题:Harness 为什么重要
LLM 系统的性能不仅取决于模型权重,更取决于 harness —— 决定"存储什么、检索什么、呈现给模型什么"的那层代码。同一个 benchmark 上,仅更换 harness 就能产生 6× 的性能差距。
打个比方:LLM 就像一个能力很强的考生,harness 就是他的备考策略——同样的脑子,给他划重点、整理错题本、安排模拟考的方式不同,最终成绩天差地别。
但当前的 harness 设计几乎全靠手工:工程师查看失败 case、调整启发式规则、反复迭代少量方案。论文核心问的一个问题是:
这个手工调参过程本身能否自动化?
已有的文本优化方法(OPRO、TextGrad、AlphaEvolve 等)理论上可以做到,但它们有一个共同缺陷:压缩反馈太狠。有的只看当前候选方案,有的只参考标量分数,有的把反馈压成短摘要。在复杂的 harness 工程中,一个关于"什么时候存""怎么检索"的决策可能在很多步推理之后才暴露影响,被压缩的反馈丢失了追因所需的信息。
继续用备考类比:已有方法相当于只告诉你"这次考了 70 分",但不告诉你哪道题错了、错在哪一步。Meta-Harness 的做法是把每次模拟考的完整答卷、草稿纸、时间分配全都留下来,让下一轮改策略的人自己翻看。
二、方案:Meta-Harness 搜索循环
Meta-Harness 的核心思路极简:用一个 Coding Agent 作为 proposer,给它一个文件系统,里面存着所有历史候选 harness 的源码、得分和执行 trace,让它自己决定读什么、诊断什么、改什么。

搜索循环三步走:
- Proposer(Coding Agent)读取文件系统 — 通过
grep、cat等标准工具,自主检索历史候选方案的代码、得分和执行日志 - 评估新 harness — 在搜索集(search set)上运行新提出的 harness,记录分数和完整执行 trace
- 归档到文件系统 — 新的代码、得分、trace 全部写回,供下一轮 proposer 使用
与已有方法的根本差异:信息量
下表来自论文 Table 1,对比各类文本优化方法每次迭代能获取的上下文量:
| 方法 | 历史策略 | 日志内容 | 每步上下文 (MTok) |
|---|---|---|---|
| Self-Refine | 仅当前 | 输出 + 自我批判 | 0.001 |
| OPRO | 滑动窗口 | (方案, 分数) 对 | 0.002 |
| TextGrad | 仅当前 | 文本梯度 | 0.015 |
| MIPRO | 摘要 | 引导的程序 trace | 0.003 |
| AlphaEvolve | 滑动窗口 | 程序数据库 + 分数 | 0.022 |
| GEPA | 摘要 | 推理 + 工具 rollout trace | 0.008 |
| Feedback Descent | 摘要 | 成对比较 + 文本反馈 | 0.012 |
| TTT-Discover | 滑动窗口 | 前一方案片段 | 0.026 |
| Meta-Harness | 完整历史 | 所有日志和分数 | 10.0 |
关键洞察:Meta-Harness 每步可访问约 1000 万 token 的诊断信息,比已有方法多出约 400 倍。这不是暴力塞进 prompt,而是让 Coding Agent 按需检索——实验中 proposer 平均每轮读取 82 个文件,其中 41% 是历史源码、40% 是执行 trace。
形式化定义
论文给出了 harness 优化的形式化目标:
用大白话说:模型
当存在多个优化目标时(比如既要准确率高、又要上下文 token 省),论文用 Pareto 前沿 来评估——即找出一组方案,任何一个都无法在不牺牲某个指标的情况下改善另一个指标,类似于"性价比最优解集合"。
实现细节
- Proposer:Claude Code (Opus 4.6)
- 每个 harness:单个 Python 文件,修改任务特定的 prompting、检索、记忆和编排逻辑
- 典型运行:20 轮迭代,约 60 个候选 harness
- 引导方式:一份极简的 skill 文档描述目录结构、CLI 命令和输出格式,不限制诊断策略
三、实验结果
论文在三个差异极大的领域进行验证:在线文本分类、数学推理、Agentic Coding。
3.1 在线文本分类
设置:LLM 逐条接收标注样本,更新记忆,在测试集上评估。使用 GPT-OSS-120B,搜索 20 轮 × 每轮 2 个候选 = 40 个 harness。三个数据集:
- LawBench(215 类,刑事罪名预测)
- Symptom2Disease(22 类,症状→疾病)
- USPTO-50k(180 类,化学反应预测)
主要结果(论文 Table 2):
| Harness | USPTO | S2D | LawBench | 平均准确率 | 上下文 (K) ↓ |
|---|---|---|---|---|---|
| Zero-Shot | 12.0 | 63.2 | 7.0 | 27.4 | 0 |
| Few-Shot (32) | 13.0 | 72.2 | 21.0 | 35.4 | 7.9 |
| Few-Shot (all) | 15.0 | 78.3 | 29.0 | 40.8 | 12.3 |
| MCE | 14.0 | 83.0 | 23.0 | 40.0 | 28.5 |
| ACE | 16.0 | 77.8 | 29.0 | 40.9 | 50.8 |
| Meta-Harness | 14.0 | 86.8 | 45.0 | 48.6 | 11.4 |
亮点:Meta-Harness 准确率 48.6%,超过 ACE +7.7 分,超过 MCE +8.6 分。上下文仅 11.4K tokens,不到 ACE 的 1/4。增益主要集中在大标签空间任务:LawBench +16 分、S2D +9 分。
vs 其他优化器(论文 Table 4):
| 方法 | 中位数准确率 | 最佳准确率 |
|---|---|---|
| GEPA | 32.6 | 40.2 |
| Best-of-N | 34.0 | 44.2 |
| OpenEvolve | 39.1 | 43.3 |
| TTT-Discover | 34.1 | 45.6 |
| Meta-Harness | 50.0 | 56.7 |
Meta-Harness 仅用其他方法 1/10 的评估次数 就追平了它们的最终准确率,最终准确率超出 10 分以上。
消融实验(论文 Table 3)——逐个去掉组件看效果变化,找出什么信息最重要:
| Proposer 输入 | 分数 | 代码 | 摘要 | 执行 Trace | 中位数 | 最佳 |
|---|---|---|---|---|---|---|
| 仅分数 | ✓ | ✓ | × | × | 34.6 | 41.3 |
| 分数 + 摘要 | ✓ | ✓ | ✓ | × | 34.9 | 38.7 |
| 完整 Meta-Harness | ✓ | ✓ | - | ✓ | 50.0 | 56.7 |
结论:执行 trace 是最关键的成分。LLM 生成的摘要不仅无法弥补缺失的信号,甚至可能因为压缩掉诊断细节而有害(摘要条件下最佳准确率反而低于纯分数条件)。
OOD(Out-of-Distribution)泛化——在搜索过程中从未见过的新数据集上测试,验证策略是不是只在"考过的题"上有效:论文在 9 个全新数据集上评估,Meta-Harness 平均 73.1%,ACE 70.2%,在 6/9 数据集上表现最佳,说明发现的策略具有通用性,而非过拟合到搜索集。
3.2 检索增强数学推理
设置:给 LLM 一个包含 ≥50 万道已解题目的检索库,让它在做题前先"翻翻相似的题和解法"。关键问题是:检索什么、检索多少、怎么排序? 这就是检索 harness 要解决的。论文在 250 道奥赛难度搜索集上进化 40 轮,产生 109 个候选检索方案。选出最佳 harness 后,在 200 道 IMO(国际数学奥林匹克)级别 测试题上评估,且跨 5 个搜索期间未见过的模型:
主要结果(论文 Table 6):
| 方法 | GPT-5.4n | GPT-5.4m | Gem-3.1FL | Gem-3F | GPT-20B | 平均 |
|---|---|---|---|---|---|---|
| 无检索 | 23.0 | 28.8 | 28.6 | 42.6 | 47.6 | 34.1 |
| 随机 Few-shot | 23.1 | 24.5 | 31.0 | 40.4 | 41.8 | 32.2 |
| BM25 检索 | 30.2 | 29.2 | 32.8 | 46.6 | 48.9 | 37.5 |
| Meta-Harness | 31.7 | 30.4 | 34.9 | 46.3 | 50.6 | 38.8 |
亮点:单一发现的检索 harness 在 所有 5 个未见模型 上均有提升,平均 +4.7 分。该 harness 完全基于 BM25(一种经典的关键词匹配检索算法),没有引入额外的 embedding 模型,意味着部署成本几乎为零。
发现的检索策略非常有趣(论文 Figure 8):一个四路由的 BM25 程序,根据题目领域(组合、几何、数论、其他)自动切换不同的检索和排序策略:
| 路由 | 策略 |
|---|---|
| 组合数学 | 取 20 BM25 候选 → 去重到 8 → 按词法分数 + 难度重排 → 返回 top 3 |
| 几何 | 1 道 NuminaMath 高难度参考 + 2 道 BM25 近邻 |
| 数论 | 取 12 BM25 候选 → 按词法分数 + 难度 + "早期点明技法" 加分重排 |
| 默认 | 取 10 BM25 候选 → 自适应选取数量(取决于检索分数集中度) |
路由门控全部由轻量级词法谓词实现,无需额外 LLM 调用。这种精细的分领域策略不是人工设计的,而是 Meta-Harness 在 40 轮搜索中自动涌现的。
3.3 Agentic Coding — TerminalBench-2
设置:89 个 Docker 化任务(代码翻译、分布式 ML、系统编程、生物信息、密码分析),二元通过/失败,每个任务跑 5 次。从 Terminus 2 和 Terminus-KIRA 两个强基线出发搜索。
主要结果(论文 Table 7):
Claude Opus 4.6 排名:
| Harness | 通过率 (%) |
|---|---|
| Claude Code | 58.0 |
| Terminus 2 | 62.9 |
| TongAgents | 71.9 |
| MAYA-V2 | 72.1 |
| Terminus-KIRA | 74.7 |
| Capy | 75.3 |
| Meta-Harness | 76.4 |
| ForgeCode | 81.8 |
Claude Haiku 4.5 排名:
| Harness | 通过率 (%) |
|---|---|
| OpenHands | 13.9 |
| Claude Code | 27.5 |
| Terminus-KIRA | 33.7 |
| Goose | 35.5 |
| Meta-Harness | 37.6 |
Opus 4.6 上排名 #2(仅次于 ForgeCode,但 ForgeCode 的公开代码无法复现其报告分数),Haiku 4.5 上排名 #1,超出第二名 Goose +2.1 分。
发现的关键改进:环境引导(Environment Bootstrapping)
Meta-Harness 发现的核心优化只有约 80 行代码:在 agent 循环开始前,运行一个 shell 命令采集沙箱环境快照(工作目录、可用语言版本、包管理器、可用内存),注入到初始 prompt 中。这消除了 agent 通常花费的 2-4 轮探索环境的开销。proposer 在搜索日志中记录的假设是:
"难任务要求 agent 根据实际安装的工具来匹配策略。如果不做环境引导,agent 前 2-4 轮都在探索环境里有什么;对于轮数预算紧张的任务,或者早期错误假设会级联放大的任务,这几轮浪费可能就是通过和失败的分水岭。"
改进在 7/89 任务上产生增益,增益最大的任务有共同特征:需要特定领域工具但无法预先假设其可用性(生信库、渲染管线、国际象棋引擎、密码学工具、CoreWars 模拟器)。
四、Proposer 是怎么"思考"的——一个真实的搜索轨迹
这一节是论文最有意思的部分之一。Appendix A 完整记录了 TerminalBench-2 搜索过程中 proposer(Claude Code)的推理日志,展示了它如何像一个人类工程师一样做因果分析。
迭代 1-2:一次改太多,搞不清哪步错了
前两轮 proposer 同时做了两件事:(1) 修复了一个真实的 bug(清理标记污染);(2) 大幅重写了 prompt 模板。结果分数都大幅下降。问题是——到底是 bug 修复搞坏了,还是新 prompt 搞坏了?
迭代 3:proposer 自己发现了"变量没控制好"
proposer 回顾了前两轮的完整代码 diff 和执行日志,写下了这段推理(原文):
"前两次失败的共同因素不是各自的 bug 修复,而是它们共享的那次 prompt 大改写。"
原文:"The common factor across the first two failures is not the particular bugfix, but the cleanup-heavy prompt rewrite."
这是经典的控制变量法——proposer 通过对比两个失败方案,排除了各自独有的改动,锁定了共同改动(prompt 改写)作为嫌疑犯。
迭代 4-6:小心验证,继续碰壁
Proposer 回退了 prompt 改写、只保留 bug 修复,验证了自己的假设(回退幅度确实小了很多)。接下来几轮尝试更精细的控制流修改,但仍然不断回退。它甚至翻出了具体任务的执行 trace,发现某个任务的 agent 陷入了 30-60 步的"验证死循环"。
迭代 7:换思路——不改老代码,只加新信息
在连续六次回退后,proposer 做了一个关键转向:
"不碰之前那套脆弱的完成判断逻辑,改为在循环开始前注入有用的环境信息——这只对难任务有帮助,对简单任务无害。"
原文:"This avoids touching the previously fragile completion machinery and instead adds information that is useful mainly on hard tasks."
这就是最终获胜的"环境引导"方案的诞生。
为什么这很重要? proposer 不是在随机试错。它在 7 轮迭代中完成了一个完整的工程推理闭环:发现混淆变量 → 控制变量验证 → 确认修改脆弱区域风险高 → 转向安全的加性修改。如果只给它一个分数("这次 64 分"),它根本无法做出这种推理——正是因为能翻看所有历史方案的完整代码和执行日志,它才能像人类工程师一样做因果分析。
五、发现的 Harness 策略
论文描述了三个领域中发现的具体 harness 策略,这些策略本身就具有独立的实用价值。
文本分类:两阶段验证 vs 标签引导查询
Meta-Harness 发现了一个策略家族而非单一方案,形成了一条"准确率 vs. 上下文成本"的 Pareto 前沿——你可以在这条曲线上选择适合自己的平衡点:要省 token 就选左边的,要高准确率就选右边的(论文 Table 9):
| 变体 | 平均准确率 | 上下文 (K) |
|---|---|---|
| Draft Verification(最省上下文) | 40.1 | 5.4 |
| Error-Annotated | 40.2 | 22.3 |
| CoT Replay | 42.1 | 23.3 |
| Cluster Coverage | 43.9 | 31.2 |
| Cascade Retrieval | 44.9 | 39.2 |
| RRF + Contrastive | 47.5 | 41.4 |
| Relevance + Contrastive | 48.2 | 43.9 |
| Label-Primed Query(最高准确率) | 48.6 | 45.5 |
两个代表性端点:
Draft Verification(两阶段验证)——先猜再验:
- 第一轮:用 5 个最相似的历史样本做初步预测("我觉得是 A")
- 第二轮:根据初步猜测重新检索——找 5 个同为 A 的样本(支持证据)和 5 个不是 A 的相似样本(反面证据),让模型重新判断
核心巧思:第二次检索的方向取决于第一次的猜测结果,相当于"我猜了个答案,然后专门找正反两方面的证据来验证",而不是无差别地看最相似的样本。
Label-Primed Query(标签引导查询)——一次调用,三层结构:
- 标签引物:先列出所有可能的分类标签(比如 215 个罪名),让模型知道答案空间
- 覆盖块:每个标签挑一个与当前问题最相关的历史样本,确保模型见过每种类别
- 对比块:成对展示"长得很像但答案不同"的样本,帮模型看清容易混淆的边界
核心巧思:用 TF-IDF(词频统计)而非简单的最近邻检索,使得检索更偏向"与当前问题词汇重叠度高"的样本。
数学检索:四路由 BM25 程序
如前文所述,这是一个领域感知的检索路由器。值得注意的是,这个程序的所有设计选择——路由谓词、重排序项、去重阈值、每路由样本数——全部由外循环在 40 轮进化中自动选定。它还融合了两条独立搜索谱系的成果:一条贡献了更强的几何路由(基于原始 BM25),另一条贡献了更强的组合数学路由(基于去重和难度重排)。
TerminalBench-2:环境引导
在 Terminus-KIRA 基础上新增约 80 行代码,核心是一个带 15 秒超时的环境快照命令。静默失败不会破坏 agent。改进来源清晰且可检查——不是黑箱的权重调整,而是可读的代码变更。
六、实践启示
论文 Appendix D 提供了将 Meta-Harness 应用到新领域的工程经验,总结为以下要点:
| 建议 | 说明 |
|---|---|
| 写好 skill 文档 | skill 文本是调控搜索的主要杠杆;约束输出和安全行为,不约束诊断过程;迭代 skill 比调整迭代次数更有效 |
| 从 baseline 出发 | 写一个简单 baseline(如 few-shot),用 baseline 做错的样本构建搜索集 |
| 搜索集要小而难 | 50-100 个样本即可;快速且有区分度的 eval 比大 eval 更有价值 |
| 结构化日志 | 用 JSON 格式、层次化目录、一致命名,让 grep/cat 好用 |
| 可选:CLI 工具 | 提供列出 Pareto 前沿、diff 代码、对比结果的小工具,帮 proposer 省 token |
| 轻量验证 | 提交完整 eval 前先跑导入测试 + 小样本测试,几秒内过滤掉畸形方案 |
| 评估自动化 | 评估逻辑足够简单,不需要 proposer 来做,由独立脚本完成 |
七、讨论与展望
论文呼应了机器学习中的一个经典规律——Richard Sutton 的"苦涩的教训"(The Bitter Lesson):历史反复证明,一旦搜索空间变得可达,利用更多算力做搜索的通用方法,最终总会超越人类精心设计的手工方案。
论文作者在 Discussion 中指出几个值得关注的方向:
- 代码空间的可检查性:harness 过拟合比权重空间过拟合更容易检查——脆弱的 if-chain 或硬编码映射在代码审查中一目了然
- 策略的可迁移性:发现的 harness 可在模型间迁移(数学推理实验中跨 5 个模型),包括未来更强的模型
- 共同进化:下一步可以让 harness 和模型权重共同进化,让策略塑造学习、学习塑造策略
- Proposer 依赖:当前实验仅用了 Claude Code 一个 proposer,不同 proposer 的效果差异有待研究
论文自身也是一个 "meta" 的体现——Meta-Harness 本身就是一个 harness(因此得名),它决定了 proposer 模型在搜索过程中看到什么信息。
总结
Meta-Harness 的核心贡献可以浓缩为一句话:用文件系统代替压缩摘要,让 Coding Agent 像人类工程师一样诊断和改进 LLM 的外围代码。
这不是一个花哨的概念验证——它在三个实际场景中都产生了可观的性能提升,发现的策略可读、可迁移、可检查。对于正在做 harness engineering 的团队来说,这篇论文最直接的价值可能不是去复现 Meta-Harness 搜索循环(虽然代码已开源),而是论文中详细记录的 发现的策略本身:两阶段验证分类、四路由检索、环境引导——这些策略可以直接借鉴到自己的系统中。
对于更长远的视角,论文提出的范式转变值得深思:当 Coding Agent 足够强大时,"优化模型周围的代码" 本身就成为一个可以被自动化的搜索问题。 随着 Coding Agent 能力的持续提升,Meta-Harness 的效果也会水涨船高——这是一个正反馈循环。
参考资料