模型之外,能力之内,重读 Harness Engineering for Self-Improvement
同一个模型为什么会在不同代理系统里表现悬殊。这篇长文从执行循环、上下文、持久状态、工具、评测与回滚出发,读懂 ACE、MCE、Meta-Harness、ADAS、AFlow、STOP 与 Self-Harness 怎样把 harness 变成可检查、可搜索、可持续改进的软件系统。
我第一次读 Lilian Weng 的《Harness Engineering for Self-Improvement》时,最先停下来的地方很朴素。同一个基础模型放进聊天框、代码代理和带实验回路的研究系统,表现会像三个不同的模型。聊天框里,它只能根据眼前消息作答。代码代理可以找文件、改代码、运行测试,再根据错误继续修。研究系统还会保存实验状态,比较多条路线,把失败记录交给下一轮。模型参数没有变化,能完成的事情已经完全不同。
这类差异很容易被归到提示词。提示词确实重要,可真实系统里的问题很快会越过一段文字。工具执行十分钟后超时,谁来接住进程。上下文塞满了日志,哪些信息该留下。模型说任务完成了,谁去打开产物、运行测试、检查外部状态。一次改动让当前样例变好,却使旧任务退步,系统能否回到上一版。它们都发生在模型周围,也都直接决定结果。
Weng 用 harness 概括这层系统。中文很难找到完全贴合的一个词。把它叫脚手架,容易让人以为工程结束后就能拆掉。把它叫运行框架,又容易漏掉记忆、权限、评测和版本管理。我更愿意保留英文。它指向一组共同工作的机制,负责把模型接到任务、环境和证据上。
我把文章和它引用的几条一手论文重新对了一遍。ACE、MCE、Meta-Harness、ADAS、AFlow、STOP、Harness Updating Is Not Harness Benefit 和 Self-Harness 处理的对象各不相同。它们放在一起以后,有一条线很清楚。模型可以生成候选方案,系统必须记录候选从哪里来,拿什么标准验收,失败后怎样退回。Harness 的价值也落在这条线上。
第一章 Harness 管的是一次回答之外的事情
一次模型调用有清楚的输入和输出。代理任务往往没有这么整齐。用户给出目标以后,系统要先找资料,随后调用工具。工具返回新的环境状态,模型据此决定下一步。任务可能经过几十次调用,中间会产生文件、终端进程、浏览器页面、测试报告和人工确认。最终答案只占整个过程的末端。
早期代理常被概括成模型、记忆、工具、规划与行动。这组词仍然有用,harness 把注意力往运行细节推了一步。它关心循环如何开始和停止,工具结果怎样进入下一轮,哪些状态必须持久保存,权限在何处生效,评测怎样拦住假完成。写进系统提示词的原则只有在运行时能被执行,才算系统能力。
这张图里最容易被忽略的是最后一步。模型提出动作,环境只负责产生后果。后果能不能证明任务完成,需要另一套检查。一次命令退出码为零,只能说明进程正常退出。它没有证明文件内容正确,也没有证明网页已经发布,更没有证明改动没有破坏别处。Harness 要把完成条件翻成可以执行的证据。
下面四层经常混在一起。分开以后,很多争论会简单不少。
| 层次 | 它直接修改什么 | 常见例子 | 它无法单独保证什么 |
|---|---|---|---|
| 提示词 | 当前调用里的文字指令 | 角色、格式、步骤提醒 | 长任务状态和外部执行结果 |
| 上下文工程 | 每次调用看见的信息 | 检索片段、示例、历史摘要 | 工具权限和循环控制 |
| 工作流 | 多次调用的连接方式 | 规划、执行、反思、投票 | 持久状态的质量和版本回滚 |
| Harness | 模型周围的运行系统 | 工具、状态、权限、评测、恢复 | 基础模型没有的领域知识 |
Harness 的边界没有统一标准。论文和产品会用 scaffold、agent framework、context engineering 或 runtime 表示相邻概念。名称可以宽一点,工程判断要具体。只要一个机制决定模型看见什么、能做什么、怎样继续、何时算成功,它就在影响代理的实际能力。
第二章 执行循环决定模型能走多远
代码代理提供了最容易观察的例子。一个普通循环会让模型先读任务,再搜索仓库,打开相关文件,提出补丁,运行测试。测试失败以后,错误输出回到上下文,模型继续定位。循环直到验证通过、预算耗尽或遇到需要人工决定的事情才结束。
这段流程听起来平常,细节却会不断改变结果。搜索工具是否支持正则和文件过滤,会影响模型找到证据的速度。编辑工具按整文件覆盖还是按补丁修改,会影响误伤范围。终端调用能不能保留进程句柄,会决定模型是否能处理长任务。系统是否在每轮提醒未完成事项,也会影响它在长上下文里是否遗失目标。
循环还需要明确的停止语义。模型很擅长生成自然语言结论,它也可能在证据不足时给出一个读起来完整的收尾。Harness 可以要求完成前运行测试、检查工作树、打开生成文件,或者等待外部任务返回最终状态。停止因此成为一种受约束的状态转换,不能只靠一句“已经完成”。
常见的代理循环至少有五个状态。准备阶段装入任务与权限。执行阶段调用工具。观察阶段解析结果。修正阶段决定继续、换路或回滚。完成阶段收集证据并交付。真实系统还会有等待、请求批准、恢复和取消等分支。它们写得越含糊,模型越容易把异常当作普通文本吞下去。
循环设计也会暴露模型差异。有的模型在工具失败后会不停重复同一条命令,有的模型搜索很久却迟迟不动手。还有一些模型改完文件会忘记生成用户要求的产物。Self-Harness 后来的实验正是从这些轨迹里挖出模型特有的弱点,再把依赖检查、产物检查、重试纪律和工具错误恢复写进 harness。通用提示无法同时照顾所有模型,运行轨迹能告诉系统眼前这一个模型究竟卡在哪里。
工作流的连接方式也会改变能力。顺序流程适合依赖关系稳定的任务,上一项输出能直接成为下一项输入。路由流程先判断任务类型,再选择工具和技能,适合入口统一但处理方法不同的系统。并行流程让多个执行者各自调查,随后由主代理合并,适合证据来源可以独立读取的任务。反馈流程让生成者和检查者反复往返,适合能够快速验证的代码、结构化数据和数学题。
这些模式没有一种普遍占优。并行会增加调用成本,也可能产生互相矛盾的结果。反馈循环若没有最大轮数和停止条件,会把同一处问题来回改写。路由器判断错一次,后面的工具再强也用不上。Harness 需要让每条边都有清楚语义。输入从哪里来,谁拥有当前状态,失败返回哪一步,预算耗尽时交付什么,最好都能从代码和轨迹里看到。
长任务还会遇到局部成功。一个代理已经查完资料,另一个代理仍在等待外部作业。系统此时不能把整个任务标成完成,也不该丢掉已完成部分。可恢复的循环会为每个子任务保存状态与产物,主流程只根据依赖关系推进。进程中断以后,它从最后一个经过验证的节点继续,不必让模型凭聊天记录猜上次做到哪里。
第三章 上下文有生命周期,消息列表没有
短任务可以把全部历史放进消息。长任务会让这种办法迅速失效。工具输出很长,重复日志很多,早期决定逐渐离开注意范围。简单截断会丢掉约束,简单摘要会丢掉失败细节,把所有东西原样保留又会挤占真正有用的上下文。
状态管理首先要回答一个问题。以后还需要用到什么。当前命令的原始输出可能只在接下来的两轮有用。用户给出的边界条件要一直保留。一次失败的完整轨迹未必进入每次调用,却应该留在可检索文件中。已经通过的验证结果要和对应代码版本绑定,免得后面拿旧测试替新改动背书。
文件系统在这里很有吸引力。它能容纳远超单次上下文的内容,也允许代理用搜索、目录和局部读取挑出需要的部分。文件还能被版本控制,差异清楚,出错后容易恢复。Weng 把文件系统视为持久记忆的一种常见模式,Meta-Harness 后来把它推进得更远。优化器可以查看每个候选 harness 的源码、分数和执行轨迹,自己决定读哪些文件。
文件本身不会自动变成好记忆。文件名混乱、内容没有来源、多个代理同时覆盖同一份状态,都会制造新问题。可用的状态通常要带四样东西。它记录了什么,来自哪次执行,对应哪个版本,什么条件下应该失效。多代理系统还要说明谁能写、谁只能读,以及冲突怎样合并。
| 状态类型 | 典型内容 | 合适的保存位置 | 常见失效方式 |
|---|---|---|---|
| 会话状态 | 当前目标、刚得到的工具结果 | 消息与短期缓存 | 上下文截断后消失 |
| 任务状态 | 计划、检查清单、阻塞原因 | 结构化文件或任务数据库 | 多个写入者互相覆盖 |
| 证据状态 | 原始日志、截图、测试报告 | 带版本的产物目录 | 与当前代码版本脱节 |
| 程序性状态 | 技能、操作步骤、恢复策略 | 可检索的技能文件 | 规则变长却从未被调用 |
| 组织状态 | 权限、所有权、审批记录 | 外部控制平面 | 模型把旧权限当成现状 |
这也是 ACE 和 MCE 关心的问题。它们把上下文看成会演化的对象。增量更新需要保留有用细节,也要防止内容只增不减。后面会展开这两项工作。眼下先记住一个判断。长上下文扩大了可见范围,状态生命周期决定其中哪些东西仍然可信。
上下文装配通常要经过选择、排序和压缩。选择决定哪些候选有资格进入,排序决定模型先看到什么,压缩决定每条材料保留到什么粒度。三步都要依赖任务。解决一个具体报错时,最近一次失败日志和相关源码比项目总览重要。做架构决策时,历史约束、已有接口和旧方案失败原因又会提前。
检索分数不能代替来源。一个片段语义相近,可能已经过期,也可能来自失败实验。可用的上下文条目应带时间、版本、任务范围和证据指针。装配器还要保存自己选了哪些条目。任务失败以后,人才能判断模型推理出了问题,还是相关材料从未进入上下文。
摘要需要保留可回到原文的指针。摘要适合告诉模型某处发生过什么,细节决定下一步时再打开原始记录。把摘要当成原始证据,会让一轮不准确的概括在后续不断复制。Meta-Harness 的消融结果很能说明这一点。压缩后的反馈看起来整齐,原始轨迹里的诊断线索已经找不回来了。
状态还要有清理机制。相同规则积累十个版本,会让检索返回互相冲突的答案。系统可以合并重复条目,把过期内容标成只供追溯,并定期用当前模型和工具重新跑关键经验。删除也要留下记录。未来看到行为变化时,研究者需要知道哪条记忆在何时退出了活跃集合。
第四章 工具接口会把小差异放大
模型通过工具接触外部世界。一个工具定义里通常有名称、说明、参数模式和返回结构。模型必须先判断何时调用,再填对参数,随后理解结果。任何一环模糊,都会在长流程里反复收费。
文件搜索就是个好例子。只提供一个通用 shell,模型可以自己拼命令,灵活性很高,也会遇到转义、平台差异和输出过长。提供结构化搜索工具,参数更容易校验,系统也能限制目录和结果数量。代价是工具设计者必须提前定义常见操作。成熟 harness 往往同时保留专用工具与受控 shell,让高频动作稳定,让长尾动作仍有出口。
工具返回值同样重要。自然语言错误“好像没有成功”很难进入自动恢复。结构化结果可以明确区分退出码、标准输出、标准错误、超时和仍在运行。浏览器工具还需要区分页面加载完成、元素可见、点击已发出和服务器状态已经改变。模型看到的每一步都应尽量接近环境事实。
权限控制不能只写在提示词里。删除文件、发布内容、发送邮件和修改线上配置都有真实后果。Harness 可以把动作分为只读、可逆写入、需要确认的外部写入和高风险操作。真正的门槛由工具层执行。模型提出请求,系统根据范围和当前授权放行或拒绝,审计记录随动作保存。
子代理与后台任务扩展了并行能力,也引入了新的状态问题。主代理要把任务边界、输入材料和交付格式交清楚。子代理完成后,主代理还要验证结果能否合并。后台进程则需要句柄、状态查询和取消机制。只把工作“交出去”没有意义,harness 必须知道工作后来发生了什么。
工具说明最好写清前置条件和失败语义。一个上传工具若要求文件已经存在,系统应在调用前校验路径。一个查询工具可能返回空集合、权限拒绝或网络超时,三种结果对应的下一步不同。把它们都塞进一段字符串,模型只能靠猜。结构化错误码、可重试标记和关联 id 能让恢复逻辑落到代码上。
幂等性会影响自动重试。读取文件重复执行通常没有副作用,发送消息重复执行会让用户收到两份内容。Harness 应知道哪些动作可以安全重试,哪些动作在重试前必须查询外部状态。带幂等键的接口、提交前预览和执行后确认,都能减少模型因为一次超时重复写入。
工具输出还可能携带不可信文字。网页、仓库 issue 和用户文件里都可能出现要求模型改变规则的内容。Harness 需要区分系统指令与外部数据,限制外部内容能影响的操作层级。高风险工具要在独立权限边界后面,输入再有说服力,也不能越过真实授权。
多代理合并同样需要契约。子代理应返回结论、依据、未解决项和修改范围。主代理要能追到原始证据,不能只收到一句“检查完了”。两个代理同时改文件时,系统需要隔离工作区或串行合并。否则并行节省的时间,很快会在冲突和误覆盖里花回去。
第五章 可观察性让失败变成材料
代理失败时,最后一句回答经常解释不了原因。模型可能在十轮以前读错文件,也可能拿到一个格式异常的工具结果,随后一直在错误前提上继续。只保存最终分数,工程师只能知道它失败了。保存轨迹以后,失败才有可定位的位置。
一条有用的轨迹会记录模型当时看见的上下文摘要、工具调用、环境返回、状态写入、验证结果和停止原因。敏感数据需要脱敏,庞大输出需要外置保存。轨迹仍应保留足够的关联信息,让人能从一次错误回到对应输入和代码版本。
可观察性并不等于把所有 token 永久存下来。系统要先定义调试问题。若要判断工具重试为什么失控,就需要动作类型、错误类别、重试次数和停止原因。若要判断检索是否有效,就需要查询、候选、实际装入的片段和下游结果。记录应服务于归因,不能变成没有读者的日志堆积。
Self-Harness 的 Weakness Mining 给了一个很具体的做法。系统在 held-in 任务上运行当前 harness,收集有验证结果的失败轨迹,再把相似失败聚类。提案者看到的是重复出现的行为模式,也会同时看到应当保留的成功行为。候选修改因而能够指向产物缺失、无效重试、依赖检查或状态读取等具体机制。
Meta-Harness 展示了另一种尺度。一个候选评测最多能产生约一千万 token 的诊断信息,固定长度摘要很难预先知道该保留什么。它把历史放进文件系统,让编码代理按当前假设搜索源码和原始轨迹。论文报告,在最复杂的设置中,提案者每轮读取文件数的中位数为 82,并会参考二十多个历史候选。这里的能力来自选择性读取,完整历史仍在,当前上下文只取眼前有用的部分。
轨迹设计要兼顾重放。模型调用本身有随机性,外部服务也会变化,完全复现往往做不到。系统仍可以保存模型版本、解码配置、工具版本、输入摘要、环境镜像和随机种子,把可控部分固定下来。无法固定的外部状态要记录读取时间和响应摘要。这样至少能判断差异来自候选 harness,还是运行环境已经改变。
只看失败轨迹也会误导。一个规则可能阻止了某类错误,却同时让原本成功的任务变慢。提案者需要看到成功样例,知道哪些行为不可破坏。Self-Harness 把 passing behaviors 放进有界 proposal context,Meta-Harness 则让编码代理自己比较多轮候选。两种办法都在保护旧能力,只是历史接口不同。
可观察性最后要进入日常调试。每次失败都让人手工翻整条轨迹,规模一大就行不通。Harness 可以先按工具错误、产物缺失、验证失败、权限阻塞和无进展循环聚合,再让工程师打开代表样例。自动聚类给入口,原始轨迹保留决定权。
第六章 Evaluator 决定系统学会什么
Harness 可以让模型生成更多候选,也可以让搜索自动运行很久。系统最后会朝哪里走,取决于 evaluator。单元测试奖励通过测试的代码,基准分数奖励适配基准的策略,模型裁判奖励它偏好的表达。指标覆盖不到的东西会被忽略,指标里有漏洞的地方会被利用。
Evaluator 至少承担三项工作。它判断一次任务是否成功,比较多个候选的优劣,也决定某个改动能否进入下一版 harness。三项工作可以共享证据,门槛通常不同。一次探索只要发现方向就有价值,发布候选需要更完整的回归测试。
| 评测层 | 要回答的问题 | 适合的证据 | 主要风险 |
|---|---|---|---|
| 结果检查 | 用户要求的产物是否存在且正确 | 单元测试、结构校验、外部状态读取 | 只检查格式,漏掉语义错误 |
| 过程检查 | 代理是否遵守权限与操作边界 | 工具审计、策略断言、人工审批记录 | 结果正确掩盖危险过程 |
| 回归检查 | 新 harness 是否损害旧能力 | 固定回归集、held-out 集、重复运行 | 对搜索集过拟合 |
| 成本检查 | 改进是否值得额外资源 | token、延迟、调用次数、失败恢复成本 | 高分由不可接受的成本换来 |
| 长期检查 | 改动是否增加维护负担 | 可读性审查、所有权检查、线上监测 | 短期基准看不见后续代价 |
随机性会让比较更难。一次运行通过,下一次可能失败。候选差距很小时,单次分数不足以证明改进。重复运行、置信区间和配对任务能减少误判。资源有限时,系统可以先用小型冒烟集淘汰明显失败者,再把完整回归预算留给少数候选。
评测集还要和提案过程隔离。Self-Harness 把 held-in 轨迹交给提案者,用 held-out 任务守住推广门槛。论文的接受规则要求候选在两部分都不退步,至少一部分有提升。这个规则很保守,正适合会修改运行系统的过程。新点子很便宜,错误发布很贵。
研究任务尤其难评。代码能否编译、数学答案是否匹配、工具状态是否达到目标,都有相对清楚的检查。研究问题的价值、实验解释和长期影响更难压成一个数。Weng 提到研究品味、负结果、奖励投机和长期成功,这些问题会限制自动循环。一个系统可以把实验跑通,仍然没有回答值得问的问题。
评测协议要在搜索前尽量固定。候选出现以后再修改题目、阈值或计分方法,容易把正常波动解释成进步。确实发现 evaluator 有缺陷时,应给 evaluator 升版本,用新协议重新跑基线和候选。旧结果保留,不能和新结果混成一条曲线。
任务泄漏也会让搜索分数失真。提案者如果看到 held-out 轨迹,回归门槛就失去意义。更隐蔽的泄漏来自共享记忆。某次评测的答案进入全局状态,后续候选会间接拿到。每个候选要在干净环境里开始,允许共享的历史只包含设计经验,不能包含保密评测答案。
成本指标应随正确率一起看。一个 harness 把通过率提高两个点,却让调用次数增加十倍,未必适合线上任务。成本也不只算 token。等待时间、GPU 使用、外部 API 费用、人工审批和失败清理都应进入记录。Meta-Harness 在分类实验里把准确率与上下文用量一起比较,得到一条可选择的 Pareto 前沿,这比只追最高分更接近部署决策。
安全评测需要覆盖成功路径。权限系统若只在故意攻击样例上测试,普通任务中的组合动作仍可能越界。代理先下载文件、再解压、随后执行脚本,每一步单看都常见,组合起来风险已经变化。过程检查要能理解动作序列,也要在真正产生外部影响前阻断。
人工评测也有位置。开放回答、研究设计和视觉质量很难完全自动化。人工打分要有清楚 rubric、盲测和分歧记录。模型裁判可以承担预筛,关键候选仍应保留人的复核。Harness 把证据整理好,让人集中判断具体差异,无须重新阅读整个运行历史。
第七章 ACE 让上下文按证据增量生长
ACE 的全名是 Agentic Context Engineering。它把上下文当作持续演化的 playbook。每次执行产生结果以后,Generator 从轨迹中提出可复用的经验,Reflector 检查这些经验是否有根据,Curator 再把经过筛选的内容增量写入现有上下文。
增量很关键。把整份上下文反复压缩重写,容易出现 brevity bias 和 context collapse。前者偏爱短而整齐的总结,后者会让多轮重写逐渐磨掉细节。ACE 保留条目结构,只对局部做新增、更新或去重,经验可以积累,也比较容易追踪来源。
ACE 在论文摘要中报告,代理任务相对强基线提升 10.6%,金融领域提升 8.6%,并能利用自然执行反馈,在没有标签监督的情况下适配。数字要按论文设置理解,它们不能直接外推到所有代理。更重要的贡献在方法上。上下文不再是一段一次写完的提示,它有条目、有更新动作,也有保留细节的机制。
这种方法仍然依赖预先设计的生成、反思和整理流程。条目结构、更新格式和调用时机都来自人。任务变化很大时,固定流程可能成为限制。MCE 从这里继续往外走。
第八章 MCE 同时演化技能与上下文产物
Meta Context Engineering 把问题写成双层过程。Base-level agent 执行当前 context engineering skill,根据训练轨迹更新上下文文件或代码。Meta-level agent 查看技能历史、执行过程和评测结果,再通过 agentic crossover 产生新的工程技能。上层改“怎样改上下文”,下层用这个方法去改具体上下文。
这个分层处理了一个长期问题。固定的反思模板会把所有任务塞进相同更新方式。MCE 允许更新方法本身发生变化。某类任务可能需要维护示例库,另一类任务更适合生成检查程序,还有一类任务需要重组检索和记忆文件。Skill 规定操作过程,artifact 保存具体结果,两者共同演化。
MCE 在五个不同领域、在线与离线设置中评测。论文摘要报告,相对现有 agentic context engineering 方法的提升范围为 5.6% 到 53.8%,均值为 16.9%。范围很宽,说明不同任务上的收益差异明显。它也提醒我们,所谓上下文优化已经越过一句提示词,进入文件、代码和执行过程。
ACE 与 MCE 都把模型权重保持不变。变化发生在调用时可见的信息及其生成过程。它们适合解决知识怎样积累、技能怎样更新。工具权限、停止逻辑、恢复路径和外部评测仍需要更完整的 harness 承担。
两项工作的差异可以从一个分类代理想起。ACE 会把误分类轨迹转成新的判别规则,整理进 playbook。MCE 还允许上层 agent 改写这套整理方法。它可以决定维护反例集合,或者写一个程序按类别抽样,也可以改变旧规则的合并方式。前者演化内容,后者连同生产内容的技能一起演化。
双层演化增加了归因难度。下层 artifact 变了,上层 skill 也变了,收益来自哪一处,需要额外消融。技能还可能在当前领域变得很专门,迁移到新任务后失效。MCE 用跨领域实验检验适应性,真实部署仍需要保存每轮 skill、artifact 和执行轨迹,让退步能回到具体变化。
上下文系统还有容量与调用成本。规则越多,装配器越要会选择。技能越复杂,执行一次更新越贵。把经验永久累加会把维护问题推迟到以后。可靠系统需要给每条经验设用途和证据,也要允许它在新评测下退出。
第九章 ADAS、AFlow 与 STOP 把工作流变成搜索对象
当工作流写成代码,它就可以被生成、执行和比较。ADAS 提出的研究问题叫 Automated Design of Agentic Systems。论文把系统拆成三部分。搜索空间规定什么样的代理能被表示,搜索算法决定怎样探索,评价函数负责给候选打分。Meta Agent Search 用一个 meta agent 编写新的代理程序,再把成功候选放回 archive,供后续设计参考。
论文从简单代理开始,包括 Chain-of-Thought 和 Self-Refine 等方案。Meta agent 先写高层设计,再把设计实现成代码,并进行两轮自我修改。候选在任务上评测,通过后进入不断扩大的 archive。它在代码、科学、数学和多任务基准上展示了自动设计的可能,也测试了跨领域和跨模型迁移。
AFlow 把代理工作流表示成图。节点调用模型,边用代码表达条件和控制关系。它用 Monte Carlo Tree Search 选择值得扩展的候选,让模型结合历史表现修改工作流,随后执行和评测新版本。搜索在 top-k 平均分趋于平稳或达到预算时停止。论文在六个基准上报告相对强基线平均提升 5.7%,部分任务中,小模型工作流超过 GPT-4o,推理美元成本为后者的 4.55%。
STOP 走得更早,也更直接。它从一个 seed improver 开始。Improver 接收待改程序、utility function 和黑盒模型,返回更好的程序。研究者随后让 improver 改写自己,下一轮再用改过的版本继续。实验中出现了 beam search、遗传算法、模拟退火、温度变化和树搜索等策略。
STOP 的边界写得很清楚。基础模型没有更新,作者不把它称作完整的递归自我改进。改进对象是调用模型的脚手程序。GPT-4 设置下,平均下游表现随迭代改善;较弱模型的结果会退步。循环能运行不等于循环能产生改进,底层模型能力和 utility function 一起限制结果。
三项工作的共同点是把系统设计从手工规则变成可执行候选。差异落在表示和搜索上。ADAS 的空间较开放,meta agent 可以发明代码结构。AFlow 把工作流限制为图,并用 MCTS 管理探索。STOP 直接优化 improver。空间越开放,潜在创新越多,评测成本和安全边界也越难控制。
搜索空间的表示会提前决定系统能够发现什么。图结构很适合表达分支、循环和并行,也便于统计节点级成本。代码表示可以容纳缓存、异常处理、文件协议和任意控制逻辑,代价是候选更难比较。纯文本规则容易生成和审阅,遇到需要真实状态转换的任务时又显得太弱。设计搜索系统以前,最好先列出允许变化的表面。哪些提示可以改,哪些工具可以增删,控制流能否改变,状态模式是否允许迁移。这个清单同时定义创新空间与风险边界。
搜索算法还要处理父代选择。永远从最高分候选继续,会很快聚到一个局部模式。只追新奇度,又可能浪费大部分评测预算。ADAS 的 archive、AFlow 的搜索树和 STOP 的迭代 improver 都在用不同方式保存历史。一个实用做法是同时保留高分候选、行为差异大的候选和能解释关键失败的候选。分数回答目前谁表现好,行为描述帮助系统看见尚未尝试的方向。
信用归因是工作流搜索里最难的一环。一个候选同时改了规划提示、工具顺序和重试次数,分数上涨以后,很难知道哪项变化有效。下一轮若把无效部分一起继承,系统会积累偶然复杂度。候选生成器应优先做小而有身份的修改,也可以对成功候选补跑消融,把变动逐项拿掉。搜索阶段允许大胆探索,进入稳定版本以前仍要把因果关系尽量拆清。
跨模型迁移也需要重新评测。某个流程可能利用了强模型的长上下文与工具遵循能力,换成较弱模型就会陷入循环。另一个流程在小模型上靠严格模板获得收益,强模型却被过度约束。论文里的跨模型结果能说明候选存在迁移可能,不能替代目标环境的验证。Harness 与模型组成一个整体版本,发布记录里应同时写下两者身份。
第十章 Meta-Harness 搜索完整的 harness 代码
文本优化器通常接收一个候选及其分数,再根据简短反馈改下一版。Harness 的诊断信息要大得多。一次执行可能跨许多任务,产生源码、工具轨迹、错误日志和局部评测。先把这些材料压成摘要,会在不知道下一轮问题的情况下丢掉细节。
Meta-Harness 选择了一个很工程化的办法。它把历史候选的源码、分数和轨迹存进文件系统,提案者使用编码代理。编码代理可以搜索目录、打开局部文件、运行检查,也能直接修改 harness 代码。每轮通常生成多个候选,评测结果继续写回。基础模型在各领域实验中保持冻结,搜索只改变 harness。
在线文本分类实验里,Meta-Harness 找到的 harness 比 ACE 高 7.7 个百分点,同时只使用约四分之一的上下文 token。和 MCE 的直接比较中,选出的 Meta-Harness 达到 48.6% 准确率,ACE 为 40.9%,MCE 为 40.0%。上下文量分别约为 11.4K、50.8K 和 28.5K token。这些数字来自论文的同一实验设置,说明有效策略可能来自更好的选择与组织,堆入更多上下文不会自动改善结果。
消融实验更能说明原始轨迹的作用。只给分数时,候选的中位与最好准确率为 34.6 和 41.3。加上自动摘要后为 34.9 和 38.7。允许访问原始执行轨迹,结果升到 50.0 和 56.7。摘要在这里没有补回诊断信息,最好结果反而下降。提案者需要根据当前问题回到材料,不能永远接受上一步提前写好的解释。
数学检索实验搜索了 109 个候选 harness,最后选出一个四路 BM25 程序。这个程序在五个 held-out 模型和 200 道未见过的 IMO 难度问题上,相对无检索平均提升 4.7 个百分点。TerminalBench-2 上,搜索出的 harness 也超过了手工设计基线。论文还给出失败轨迹。提案者曾把结构修复和提示词改写捆在一起,结果退步。它查看历史后拆开干预,最后转向更安全的增量修改。
这段过程很像正常的软件调试。改动需要有清楚身份,多个变量同时变化会让归因失效。文件系统保存了可恢复的实验上下文,提案者得以比较失败,随后把假设缩小。
Meta-Harness 的外循环可以看成一套自动实验管理。每个候选都需要能安装、启动和执行同一批任务。评测器把任务级结果、总分和资源用量写回独立目录。提案者随后读取历史,选择一个或多个父版本,再生成下一批代码。候选若连基本接口都无法满足,会在便宜的启动检查里淘汰,昂贵任务只留给能够正常运行的版本。这种分级预算让开放代码搜索不至于把资源全耗在语法和依赖错误上。
论文里的四路 BM25 harness 也提醒了一个容易遗漏的事实。被搜索出来的系统未必复杂。优化器有能力写任意代码,最后仍可能选择一组简单、互补的检索路线。判断标准来自 held-out 模型和未见题目的结果,代码的表面复杂度并不构成证据。自动搜索的意义在于比较更多可执行假设,最终产物完全可以比搜索过程朴素。
成本指标会改变搜索方向。只按准确率排序时,候选可以无限增加检索、反思和调用轮数。把 token、延迟或美元成本写进 evaluator 以后,搜索会面对多个目标。Meta-Harness 报告的分类结果同时给出准确率与上下文量,允许部署者在 Pareto 前沿上选点。研究系统还应保存完整预算消耗,因为一次幸运运行的低成本不能代表稳定工作负载。
编码提案者拥有读写与执行工具,权限边界也随之扩大。实验目录应和生产环境隔离,候选只能访问明确提供的数据,外部写入默认关闭。评测结束以后,系统要清理残留进程和临时资源。搜索得到高分并不授予发布权。候选从研究目录进入活跃 harness,仍要走独立的审查与回归流程。
第十一章 会更新 Harness,不等于会用好它
《Harness Updating Is Not Harness Benefit》把能力拆成两个轴。Harness-updating 指模型能否根据执行证据写出有用的持久修改。Harness-benefit 指任务代理能否在后续执行中调用并遵守这些修改。论文的实验发现,两项能力并不同步。
从 Qwen3.5-9B 到 Claude Opus 4.6,不同能力层模型写出的更新带来相近收益,updating 随基础任务能力变化较平。Benefit 呈现非单调关系。弱模型获益少,中等能力模型最多,强模型又少于中等模型。弱模型的典型失败有两种。它可能没有激活相关 skill 或 memory,也可能激活以后没有持续遵循。
这项区分解释了许多记忆系统的尴尬。系统确实存下了一条好经验,代理下次没有检索到。检索到了,规则在十轮工具调用后又被忘掉。更新器看起来很聪明,任务表现没有变化。继续要求更新器写得更漂亮解决不了调用和遵循问题。
Harness 因此要记录技能的触发条件,也要在运行时提供可观察的激活信号。关键规则可以转成检查器,让遵循从自然语言意愿变成外部约束。长任务还需要在阶段边界重新装入重要条件。Benefit 最终由整条执行链决定。
第十二章 Self-Harness 用回归门槛约束自我修改
Self-Harness 让目标模型参与修改自己的运行 harness。它不依赖更强的外部模型,也不让提案者任意重写整个系统。每轮包含 Weakness Mining、Harness Proposal 和 Proposal Validation。
Weakness Mining 从 held-in 轨迹里找有验证依据的重复失败。Harness Proposal 使用相同基础模型,根据失败模式提出一组多样但幅度小的修改,每项修改都绑定一个具体机制。Proposal Validation 在 held-in 与 held-out 任务上重新运行候选。两个部分都不退步,且至少一部分提升,候选才进入接受集合。多项修改同时通过时,系统合并它们,生成下一版 harness。
论文在 Terminal-Bench-2.0、SWE-bench Verified 和 AppWorld 上使用 MiniMax M2.5、Qwen3.5-35B-A3B 与 GLM-5。九种模型与基准组合的最终 harness 在 held-in 和 held-out 上都提高了通过率。相对增益最高为 132%,出现在 AppWorld 的 Qwen3.5 设置。绝对增益最高为 40.6 个百分点,出现在 AppWorld 的 GLM-5 设置。
具体改动比总分更有意思。MiniMax 的 harness 学会更早创建要求的产物,更谨慎处理结构化工具内容,也会结束没有进展的工具循环。Qwen 的改动集中在提前检查依赖、避免重复失败命令、打断无休止探索,并在工具错误后重新确认产物。GLM 的 harness 更注意在 shell 命令之间保存环境设置,也更快从探索转入实现和测试。
这些修改很小,也能读懂。模型、评测器、任务划分和工具保持固定,实验试图隔离 harness 变化的效果。论文也承认限制。它研究的是固定基准下的有界修改,仍可能学到基准特有模式。更高风险的系统需要更强的接受门槛,单纯通过率不够。
Weakness Mining 的价值在于把修改起点落到重复证据上。一条失败轨迹可能来自偶然采样,十条相似轨迹反复缺少产物检查,就更像稳定弱点。聚类时既要看最终错误,也要看失败前的动作序列。相同的“任务未通过”可能分别来自没有开始实现、实现后忘记测试,或测试通过却没有提交目标文件。修改应对准最早能改变结局的那个环节。
提案阶段需要守住有界表面。目标模型可以改重试策略、依赖检查、阶段提醒和产物验证,却不能顺手换掉评测器或偷看 held-out 数据。边界越清楚,接受结果越容易解释。多样提案也不等于大范围改写。系统可以围绕一个失败模式生成几种机制不同的最小干预,例如调用前检查、失败后恢复、阶段末断言,再让评测决定哪一种更有效。
合并多个通过候选会产生新的风险。两项修改单独有效,放在一起可能重复触发,或把上下文挤得太长。Self-Harness 的循环会在合并后重新得到一版 harness,现实实现应把组合视为新候选,再跑完整门槛。候选谱系要记录父版本与组成修改,出现退步时才能先撤掉最可疑的一支。
模型特异性也值得保留。MiniMax、Qwen 和 GLM 得到的改动并不相同,轨迹暴露出的行为差异不能按实验噪声处理。统一 harness 可以降低维护成本,模型专用层则能处理稳定弱点。两层最好分开版本化。共同安全规则放在基础层,模型特有恢复策略放在适配层,换模型时只重新评测后者还远远不够,整条组合仍需回归。
第十三章 候选生成为什么必须经过验证
生成很适合扩大搜索面。面对一条失败轨迹,模型可以提出多种解释。依赖没有安装,工作目录错误,命令和平台不兼容,前一步产物为空,都可能导致相同的表面错误。只沿一条解释继续,系统很容易在最先想到的原因上耗完预算。多个候选能保留不同路径。
候选本身还没有知识地位。它是一项等待检验的提议。系统要把候选和证据需求绑在一起。若假设是依赖缺失,就读取锁文件并执行版本检查。若假设是产物路径错误,就列出目录并核对调用参数。若候选修改了 harness,就在固定任务上重新运行,比较行为有没有按预期改变。
验证要尽量独立于候选生成。让同一个模型提出方案、解释结果并决定自己成功,会放大确认偏误。单元测试、状态校验和独立评测器可以承担硬门槛。开放任务仍需人工判断,系统至少应把原始证据和变化范围交清楚。
候选数量也要受预算约束。更多候选会增加覆盖,也增加评测成本和偶然高分的机会。搜索系统要记录总评测次数,必要时修正多重比较带来的偏差。先用便宜检查缩小范围,再做昂贵验证,通常比把全部候选跑到底更稳。
我最在意的生成用途就在这里。生成可以提出反例、替代解释、检查问题与程序修改。理解来自候选和证据的往返。一个候选被否决同样有价值,它缩小了可能空间,也给下一轮留下可复用的失败条件。Harness 负责让这段往返发生,并阻止未经验证的文字直接变成系统状态。
一项可操作的验证记录至少包含五部分。先写假设,说明候选准备改变哪种失败。再写干预,只列出实际修改的字段、代码或流程。随后固定任务、随机性与环境,记录预期观察。实验结束后保存原始结果与统计摘要,最后给出接受、拒绝或信息不足的决定。少了第一步,系统只知道分数变了。少了原始结果,未来无法复核。少了信息不足这一项,噪声会被迫解释成胜负。
最小实验适合排查机制,完整回归负责判断能否发布。比如代理经常漏掉最终产物,可以先加阶段末文件断言,在一小组相关任务上确认行为确实发生变化。这个结果只能证明机制有作用。候选随后还要进入跨任务回归,检查断言是否误伤无文件产物的任务,是否增加无意义调用,是否在工具故障时造成死循环。局部解释与整体收益需要两套证据。
统计波动会制造假进步。候选很多时,总会有几个靠随机性排到前面。可靠流程会给所有候选相同运行次数,保存每道任务的配对结果,关注提升来自多少任务,而不只看平均分。分差接近噪声范围时,可以扩大样本或保持旧版。发布门槛没有义务在每轮都选出赢家,暂不更新也是一种正常结果。
验证还应尝试反驳候选。假设一条新规则减少无效重试,就专门构造网络抖动、永久错误和可恢复错误三类场景。若规则只在永久错误上有效,却让暂时错误过早停止,它的适用条件要收窄。让检查者主动寻找失效边界,能够把一句泛化经验改成带条件的程序性知识。
理解也可以被写成可执行探针。系统怀疑代理没有读取某项状态,可以在受控任务里放入唯一标记,并检查后续动作是否依赖它。怀疑规则被检索却未遵循,可以分别记录激活事件和行为断言。抽象问题由此变成两个可测节点。Harness Updating 与 Harness Benefit 的区分,正适合用这类探针定位断点。
第十四章 回滚把改进变成可逆的发布
Harness 修改会影响后续所有任务,风险高于一次回答。改动进入活跃版本以前,应该像软件发布一样经过版本、测试和批准。每项候选需要记录父版本、改动内容、目标失败模式、评测集、结果和接受理由。缺少这些信息,下一轮很难判断收益来自哪里。
回滚不只是恢复一份旧提示词。状态模式可能已经改变,新版写入的记忆未必能被旧版读取。工具权限和外部资源也可能发生变化。可靠回滚要考虑代码、配置、状态迁移和副作用。已经发送的消息无法撤回,已经删除的数据也未必能恢复,发布前的权限边界仍然最重要。
| 发布阶段 | 必须保存的证据 | 通过条件 | 失败后的动作 |
|---|---|---|---|
| 候选生成 | 父版本、修改 diff、目标失败模式 | 改动范围清楚且可执行 | 拒绝不可归因的大改 |
| 冒烟测试 | 关键工具和最小任务结果 | 没有语法、权限与启动错误 | 修复或废弃候选 |
| 回归测试 | 固定任务、重复运行、成本统计 | 旧能力不出现不可接受退化 | 回到父版本 |
| Held-out 检查 | 未交给提案者的任务结果 | 改进能离开搜索样例 | 标记过拟合并拒绝 |
| 灰度运行 | 线上监测、人工反馈、异常率 | 真实任务表现稳定 | 自动停止并回滚 |
版本管理还让负结果有地方可放。没有通过的候选不应被悄悄删掉。保留失败原因可以避免后面重复尝试,也能让研究者看到哪些规则只对特定模型或基准有效。负结果进入可检索历史,搜索才真正积累经验。
回滚路径需要在发布前演练。能够指向旧版本号,不代表旧版还能启动。依赖包可能已经升级,状态结构可能完成了不可逆迁移,旧工具凭据也可能失效。团队可以定期从稳定快照恢复一个隔离实例,跑最小任务并核对读写。恢复时间和数据损失范围也应成为发布指标。
状态迁移适合采用向前兼容的两阶段做法。新版先学会读取旧格式,并用新格式写入。稳定观察一段时间后,再停止旧格式写入。若需要回滚,旧版仍然可能无法理解新增字段,因此关键数据可保留双写或转换脚本。任何转换都要留下数量校验、哈希或抽样检查,防止回滚成功启动却悄悄丢失记忆。
灰度发布要有明确的停止条件。系统可以先把少量低风险任务分给候选,比较错误率、人工接管、成本和延迟。出现权限异常、不可恢复副作用或核心回归时立即停止。一般性能波动则依据预先设定的窗口判断,不能看见一次坏结果就频繁来回切换。切换本身也会影响状态与缓存。
外部副作用要求补偿策略。已经发送的邮件无法真正撤回,系统可以在发送前保存草稿并要求确认。已经创建的资源可以登记 id,失败后自动关闭。无法补偿的动作应放在最窄权限与最后阶段。回滚解决未来使用哪个 harness,补偿处理过去已经发生的影响,两者要分别设计。
第十五章 几项工作的边界放在一起看
这些论文都讨论固定模型周围的可变系统,优化对象和证据接口差别很大。把它们压进同一个“自我改进”标签会漏掉关键边界。
| 工作 | 主要优化对象 | 候选怎样产生 | 主要反馈 | 保留历史的方式 |
|---|---|---|---|---|
| ACE | 上下文 playbook | Generator、Reflector、Curator | 执行反馈与任务指标 | 结构化增量条目 |
| MCE | CE skill 与 context artifact | 双层 agentic crossover | 五领域在线与离线评测 | 技能和产物历史 |
| ADAS | 代码表示的代理设计 | Meta Agent Search | 多领域任务分数 | 成功代理 archive |
| AFlow | 图表示的工作流 | LLM 修改与 MCTS | 六个基准的执行反馈 | 工作流搜索树 |
| STOP | Improver 程序 | Improver 递归改写自身 | Meta-utility | 迭代版本 |
| Meta-Harness | 完整 harness 代码 | 编码代理读取历史后改代码 | 分数、成本、源码与原始轨迹 | 文件系统里的全部候选 |
| Harness Updating Is Not Harness Benefit | 更新能力与利用能力 | 跨模型对照实验 | 更新收益、调用与遵循行为 | 实验轨迹与技能产物 |
| Self-Harness | 目标模型自己的有界 harness 表面 | 弱点挖掘后并行提案 | Held-in 与 held-out 回归门槛 | 接受和拒绝的候选谱系 |
ACE 和 MCE 更接近上下文及技能的持续维护。ADAS、AFlow 和 STOP 关心工作流或程序搜索。Meta-Harness 把可编辑面扩到运行代码,并让提案者选择性查看完整历史。Self-Harness 把提案角色交给目标模型自身,同时用固定评测器和回归规则约束发布。Harness Updating Is Not Harness Benefit 则提醒我们,写出更新和从更新获益是两件可分开的事。
它们仍有共同依赖。候选必须能执行,结果必须能评,历史必须能找到,改动必须能比较。缺少其中任何一项,循环就会退回到凭感觉改提示词。
第十六章 现实系统还缺哪些东西
第一项困难是 evaluator。开放任务很少有一个完整分数。研究代理可以找到更高的 benchmark 数字,也可能利用了数据泄漏。代码代理可以通过现有测试,同时留下难维护的实现。多目标评测会更接近现实,也会带来权重选择和冲突处理。
第二项困难是长期状态。记忆会增长,环境会变化,旧技能会失效。系统需要淘汰、合并和重新验证机制。一次有效经验不能获得永久通行证。模型版本、工具接口或组织政策改变以后,相关条目应重新评测。
第三项困难是搜索多样性。Evaluator 会把候选拉向已知高分模式,早期表现差的路线很容易被淘汰。开放研究需要保留一部分探索预算,也要记录候选之间真正的差异。生成一百个措辞相近的版本不算多样性。
第四项困难是奖励投机。单元测试有漏洞,代理会找到让测试变绿的捷径。模型裁判有偏好,候选会学会迎合它。Held-out 测试、独立评测、轨迹审计和人工检查能够增加成本,却无法一次消除问题。Evaluator 本身也要被版本化和评测。
第五项困难是人应该在哪一步出现。人不必手工调整每条提示,但高影响决策仍需要责任主体。人可以定义目标和不可触碰的边界,审核评价函数,在异常与分布变化时决定是否继续。自动化适合处理大量可复现比较,责任不会随调用次数一起自动消失。
第六项困难是分布变化。工具版本升级、模型服务更新、任务类型变化以后,旧回归集可能仍然全绿,线上行为已经不同。Harness 应记录输入分布、工具错误类型和人工接管原因的长期变化。监测发现漂移时,先冻结自动推广,再补充代表新环境的评测。继续沿用旧分数,会让搜索优化一个已经不存在的世界。
第七项困难是评测资产本身的治理。保密任务、人工标注和真实失败轨迹都可能泄漏。提案者只获得生成候选所需的部分,独立评测器保留未公开答案。随着轮次增加,还要检查历史文件里是否混入评测内容。数据边界一旦失守,后续高分很难再解释。
第八项困难是维护者能否读懂自动生成的系统。候选代码可能通过测试,却使用晦涩控制流或复制大量规则。上线前应检查模块边界、注释、依赖和删除旧逻辑的机会。复杂度可以进入评价函数,也可以作为人工门槛。Harness 是长期运行的软件,下一次故障发生时,维护者仍要能找到负责那项行为的代码。
最后还有一个朴素限制。Harness 能释放模型已有能力,也会放大模型的习惯与缺点。STOP 在较弱模型上的退步、Benefit 实验里的激活与遵循失败,都说明外层系统无法无限补偿内层能力。过度复杂的 harness 还会增加上下文负担和维护成本。每加一条机制,都该问它解决了哪种可复现失败,验证是否证明它值得留下。
第十七章 我现在怎样理解 Harness Engineering
Harness Engineering 处理的是模型和现实任务之间的那段距离。任务怎样被拆开,证据怎样进入上下文,工具怎样受控执行,状态怎样跨轮保存,结果怎样通过检查,失败以后怎样恢复,这些事情共同决定一个代理能否可靠工作。
文章读到最后,我留下的判断很具体。生成可以帮助系统理解问题,因为它能同时提出几条有差异的解释和方案。验证负责逐条碰证据,状态系统保存哪些路径已经走过,回滚让错误候选不会永久改坏后续行为。四件事接起来,模型才有机会从一次运行里学到可复用的东西。
这条路线也把“更聪明”拆成了可研究的问题。系统是没提出正确候选,还是没有找到相关记忆。它找到了规则却没遵循,还是 evaluator 没看见真正的错误。Harness 让这些失败出现在轨迹、代码和版本里。问题一旦能被定位,就能做实验。
下一步值得做的工作,大概会继续围绕三件事展开。让候选保持差异,让验证真正触到任务事实,让状态在长时间里仍有来源和有效期。它们不华丽,却决定自动改进是一串漂亮文字,还是一套可以信任的软件过程。