论文:LongHorizon-Harness: Advancing Long-Horizon Agents for Real-World Tasks 作者:Ziyu Ma, Hailang Huang, Shun Zou, Yong Wang, Shidong Yang, Yiming Hu, Fei Wei, XiangXiang Chu(DreamX Team, Alibaba Group) arXiv:2608.01964(2026-08-03) GitHub:AMAP-ML/LongHorizon-Harness Website:lh-harness.pages.dev
1. 任务状态与 MEA 循环
LongHorizon-Harness 把长任务从一段不断增长的对话, 改写成可验证的任务状态转移. Manager 维护目标与进度, Executor 在 fresh context 中执行一个有界子任务, Auditor 再从环境读取证据.
三个角色的数量并非关键, 未经验证的执行声明不能进入任务事实才是 MEA 循环的约束. 角色分工、状态合约和审计门共同阻止一次错误自评沿后续轮次传播.
执行轨迹为何会发生状态漂移,LLM Agent 承担 long-horizon 任务时, 需要持续推理、反复调用工具, 并在相互依赖的步骤之间修正方案. 许多 Agent Harness 却把任务执行、任务状态和完成度评估放在同一个不断增长的上下文中. 上下文越长, 模型越难区分已验证事实与自己的推测.
错误自评还会沿轨迹传播. Agent 一旦误判「已经完成」, 后续计划就会建立在错误状态上, 形成 state drift. 模型决定单轮能做什么, Harness 决定结果能否被验证、保留并继续推进, 论文的改动集中在后一个问题.
1.1. Manage-Execute-Audit 的状态分工
论文把 long-horizon 执行重新定义为一个任务状态管理问题(task-state management problem):
- 任务状态显式地放在执行之外维护;
- 状态只允许用从环境独立验证过的事实来更新;
- Agent 不再「边执行边自我评估」,而是由外部机制客观判定环境里发生了什么。
核心机制是 Manage-Execute-Audit(MEA) 三角色循环:
| 角色 | 职责 | 关键点 |
|---|---|---|
| Manager | 维护原始目标、已验证进度、下一子任务 | 基于审计事实重新规划,而非凭上下文里的自我感觉 |
| Executor | 执行当前子任务 | 全新(fresh)上下文执行,避免被长历史污染 |
| Auditor | 只读验证环境结果 | 检查文件、界面、日志、测试,产出 audit report |
跨轮决策只读取结构化 task state 与 audit reports。Manager 依据审计过的事实做下一轮规划,这就切断了「错误自我评估」的传播链。Executor 的原始交互轨迹不会直接进入下一轮执行上下文;持久记录仍可保留轨迹供复查,但它不能绕过审计门成为任务事实。 论文还提出轻量 AgentAdapter:在不修改原生 agent loop 的前提下,可插拔互换模型与 harness 后端(Claude Code、Codex 等),且 Manager / Executor / Auditor 可分别配置不同模型或后端,以平衡质量、速度与成本。GUI 交互通过外部 computer-use MCP 提供,harness 本身不捆绑特定实现。
三类基准上的收益与开销,同一 backbone(Qwen 3.7-Plus)+ 同一执行后端(Claude Code)对比:
| 基准 | 指标 | 基线 | LongHorizon-Harness | 提升 |
|---|---|---|---|---|
| WeaveBench(114 任务) | PassRate | 51.8% | 80.7% | +28.9 pt |
| WeaveBench | Overall | 0.702 | 0.835 | +0.133 |
| OSWorld 2.0(108 任务) | Binary | 2.8% | 8.3% | 3.0× |
| OSWorld 2.0 | Partial | 21.5% | 35.2% | +13.7 pt |
| Terminal-Bench 2.1 | Success rate | 69.7% | 77.2% | +7.5 pt |
跨模型迁移:Claude Opus 4.7 在 OSWorld 2.0 34 任务子集上,binary 从 20.0% → 34.3%,partial 从 55.8% → 66.9%。Codex + GPT-5.6 Luna 在 Terminal-Bench 2.1 上达 83.1%。 Token 分解显示 Manager 仅占 WeaveBench / OSWorld / Terminal-Bench 总 token 的 2.8% / 8.1% / 2.0%,Auditor 占 19.4% / 24.8% / 38.1%——独立验证是主要额外成本,但 Terminal-Bench 上总 token 反而减少 24% 且成功率更高,说明框架不施加固定 token 倍数,而取决于底层模型需要多少执行与恢复轮次。 WeaveBench 覆盖 14 类真实任务域(Web 前端、数据分析、运维调试、设计、游戏、文档、空间推理、桌面设置、科研教育、创意生产、工程计算、个人服务、行政合规、商业金融、医疗等),八个子域 PassRate 全面提升,增益不集中在单一类别。
独立审计的成本与边界,独立 Auditor 提高了状态可信度, 也引入额外推理、环境读取和工程依赖. 这些成本随任务类型变化: CLI 任务可以复用确定性测试, GUI 任务往往需要更多观察和更长输出.
实验结果还没有把所有长任务都变成高成功率问题. OSWorld 2.0 的 binary 成功率仍为 8.3%, 因此 MEA 更适合被理解为状态控制机制, 而不是替代底座模型能力的通用解法.
- 绝对成功率仍低:OSWorld 2.0 binary 8.3% 说明全桌面长任务远未解决;harness 是倍增器而非银弹。
- 审计开销:每轮一次环境验证,Auditor token 可达总量近四成;复杂 GUI 任务成本显著上升(Qwen 3.7-Plus 在 OSWorld 上 output token 从 28.9K → 104K)。
- 跨轮记忆压缩:只留 audit report 可能丢失 Executor 轨迹中的细微上下文;Manager 规划能力本身仍有上限。
- 工程依赖:需要可用的 computer-use MCP、CLI agent 运行时(claude / codex)、以及 per-run 隔离目录与 Dashboard 等人机协同设施。
- 训练无关:纯推理期 harness 改造,不改模型权重;与 RL 训练 agent 的上限仍由 backbone 决定。
1.2. 状态合约与执行闭环
单轮数据流. LongHorizon-Harness 的单轮数据流可形式化为:
- Manager 读取 task state (S_i) 与累积 audit reports (V_{i-1}),构造有界子任务合约 (c_i)(目标、验收标准、边界约束、相关先验证据);也可走 ask 路由请求用户信息或授权。
- Fresh-context Executor 在预算内(默认 1800s/轮)执行 (c_i),将环境从 (e_{i-1}) 变为 (e_i),返回 execution report (o_i);原始轨迹随后丢弃。
- Read-only Auditor(默认 300s/轮)通过只读工具检查 (e_i),产出 audit report (v_i)。
- Manager 将 (v_i) 并入 (S_{i+1}),判定是否满足原任务、是否还有可推进子任务、是否需要用户输入,或是否耗尽 round budget(默认 (N_{\max}=25))。
每轮 run 落盘于 runs/<run-id>/:task state、event stream、audit reports、三角色 trajectories、workspace 产物、final report——使进度可检查、可恢复、可复现。
用户任务 T
│
▼
┌──────────────────────────────────────┐
│ Manager:S_i + V_{i-1} → 子任务 c_i │
└──────────────┬───────────────────────┘
▼
┌──────────────────────────────────────┐
│ Executor(fresh context):e_{i-1}→e_i │
└──────────────┬───────────────────────┘
▼
┌──────────────────────────────────────┐
│ Auditor(read-only):环境 → v_i │
└──────────────┬───────────────────────┘
▼
Manager 更新 S_{i+1}
│
└── 循环直至完成 / 阻塞 / 预算耗尽
三个角色怎样交换状态合约. MEA 用输入、输出和写权限分隔三个角色。Manager 生成合约,Executor 改变环境,Auditor 再从环境中读取结果。若三者都能随意修改 task state,增加角色只会把同一种自我确认重复三遍。
| 角色 | 主要输入 | 主要输出 | 不应拥有的权力 |
|---|---|---|---|
| Manager | 原始目标、当前 task state、历史 audit report、轮次与预算 | 一个有界 subtask contract,或完成、阻塞、询问用户的路由决定 | 不能把未经检查的 execution report 直接写成事实 |
| Executor | 当前 subtask contract、必要的已验证事实、工作环境和可写工具 | 环境改动、产物以及 execution report | 不能宣布整个任务已经通过,也不能改写历史审计结论 |
| Auditor | subtask contract、验收条件、改动后的环境和只读检查工具 | 带证据的 pass、fail 或 inconclusive,以及发现的偏差 | 不应修复产物,否则检查者同时变成被检查者 |
subtask contract 至少应包含本轮目标、允许修改的对象、不可越过的边界、所需先决事实和验收条件。Executor 返回的 execution report 只是一份定位线索,例如「修改了 A 文件并运行了 B 检查」。Auditor 随后直接读取 A 和 B 的真实结果。两份报告即使文字一致,证据等级也不同:前者是执行者声明,后者才是允许 Manager 提交状态的依据。 task state 也不宜写成一大段自由文本。一个最小结构可以分成:
goal:原始目标和用户后来确认的变更;constraints:不能修改的范围、权限和资源预算;verified_facts:审计已经确认、带来源的环境事实;completed:已满足的验收条件,而非已经调用过的工具;open_items:尚未满足的条件、依赖和风险;current_contract:当前唯一生效的子任务;status:running、waiting、completed、failed等可枚举状态;checkpoint:与本轮事实对应的工作区或外部资源版本。
这样的结构使 Manager 能够做滚动计划。它不必在第一轮预言全部二十五轮动作,只需要在每次审计后,根据尚未满足的验收条件选择下一个子任务。设 是第 轮后仍未满足的条件, 是当前已核实的依赖,那么下一合约可以写成:
其中 是原始任务, 是最新审计, 是剩余预算。若审计发现依赖并不成立,Manager 应先修订 和后续顺序;若只是执行失败但目标仍然可达,可以缩小子任务或换一条路径;若缺少用户授权,就进入 waiting,不能把等待伪装成完成。
验证门与状态提交. Auditor 给出的结果至少应区分 pass、fail 和 inconclusive。pass 表示验收条件已有充分证据;fail 表示证据明确反驳完成声明;inconclusive 表示工具不可用、环境异常或现有检查不足以得出结论。第三种结果很重要。把「无法验证」自动当成成功会污染 task state,把它一律当成任务失败又会把基础设施故障归咎于 Executor。 状态提交可以理解为一个验证门:
只有 中带有环境证据的事实能够进入 verified_facts。若结果为 fail,Manager 记录失败模式和仍有效的局部产物,再生成修复合约;若结果为 inconclusive,则保存当前 checkpoint,优先恢复检查能力。这里的「提交」不要求进度只能增加。审计可能发现之前通过的条件被新改动破坏,此时对应完成项必须撤销。跨轮记录保持的是证据链可追溯,不是虚假的单调完成率。
验证门还需要与子任务边界对齐。例如合约要求「修复解析器并保证旧格式测试不回归」,Auditor 只确认新样例通过,就不能给整份合约 pass。反过来,验证器也不能自行扩张范围,把与当前目标无关的告警都判成任务失败。验收条件决定检查什么,环境证据决定条件是否成立,二者共同限制 Auditor 的裁量。
一个逐轮状态例. 考虑任务「修复 CSV 导入中的引号解析,并让相关测试通过」。初始状态 只包含目标、禁止改动公共 API 的约束和空的已验证事实。
- 第 1 轮规划:Manager 生成合约 ,要求定位失败样例和解析路径,只读调查,不修改代码。Executor 找到复现命令并报告某个转义分支可疑。Auditor 独立运行该样例,确认错误可以稳定复现,并记录失败输出。 新增的事实是「样例确实失败」和「调用路径经过该解析器」,而不是「根因已经找到」。
- 第 2 轮执行:Manager 基于 要求修复解析分支,边界是保留公开接口。Executor 修改实现并称新样例已通过。Auditor 运行目标测试后发现成功,但现有回归测试有一项失败,于是返回
fail,同时保存目标样例已经修复这一局部事实。 记录回归症状,完成状态仍未提交。 - 第 3 轮修订:Manager 不再重复原修复,而是生成只处理回归的合约。Executor 调整边界条件。Auditor 同时运行目标样例、相关回归测试和接口检查,全部满足后返回
pass。 才把该验收条件标为完成。 - 最终门:Manager 对照原始目标发现所有条件已覆盖,生成 final report;若全量检查又暴露新问题,就撤销完成判断并进入下一轮。
这个例子里,Executor 每轮都可以使用 fresh context,因为定位信息、失败证据和约束已经进入外置状态。跨轮保存的是「哪个样例在什么命令下失败」「哪个修改通过了哪组检查」这些可重新核实的事实,对话语气不参与下一轮决策。
checkpoint、rollback 与错误传播. 论文的 run 目录保存 task state、报告、轨迹和产物,为恢复提供了材料。但可恢复不等于机械重放。一次可靠 checkpoint 应把 task state 与环境版本绑定:本地任务可以关联 workspace 快照或 commit,GUI 任务需要记录可重新读取的页面状态,外部 API 写入还应保存资源标识。进程中断后,系统先读回环境并核对 checkpoint,再决定继续、回滚或重新规划。 rollback 也有边界。代码和版本化文件通常可以回到旧快照;已经发送的消息、已经触发的远端操作往往只能补偿,不能真正撤销。因此,Manager 在生成合约时需要区分可逆写入和不可逆副作用。Auditor 的只读约束可以防止检查阶段再引入新副作用,却不能自动解决 Executor 已经产生的外部写入。
MEA 切断错误传播主要靠两个门。第一道门是 fresh-context Executor:前一轮的猜测不会作为完整聊天历史自动进入下一轮。第二道门是 Auditor:执行声明必须经过环境验证才会写入 task state。不过,错误仍可能从三个地方穿过:Auditor 使用了过弱的验证器,Manager 错误解释了正确的 audit report,或者环境本身发生了未记录的外部变化。因此系统要保留验证命令、观察结果和环境版本,使后续轮次能够推翻旧结论,而不是只保存一句「已通过」。
开销与对照实验应怎样看. MEA 增加了 Manager 和 Auditor 调用,也增加了环境检查与进程启动成本。论文的 token 分解说明 Manager 占比较小,Auditor 是主要额外开销;但 token 只是其中一项。评估系统成本还应报告墙钟时间、模型调用次数、工具调用次数、环境重置成本、失败后的重试轮数,以及每个成功任务的总消耗。某个框架总 token 更少,可能来自更早停止,也可能来自减少无效恢复;仅看平均输入长度无法区分。
要判断提升来自哪里,对照实验必须尽量固定 backbone、执行后端、工具权限、任务集合和预算。至少需要比较:单会话基线与完整 MEA;保留 Manager 但没有独立 Auditor;有 Auditor 但 Executor 继续继承完整历史;以及不同验证强度下的结果。指标除了最终成功率,还应包含误报完成率、因 inconclusive 退出的比例、平均轮数和成功任务成本。若同时更换模型、Harness 和预算,成绩提升就不能单独归因于任务状态管理。
角色消融也要避免一个误区:三角色优于单角色,并不能推出「角色越多越好」。决定能力的是权限分离、信息边界和验证门。若把 Auditor 合并为一个确定性的测试程序,只要它仍然独立读取环境,也可能保留关键收益;反之,即便增加五个模型角色,只要它们共享同一段未经核实的叙事,错误仍会沿着上下文继续传播。
1.3. 长任务的压力、漂移与停止条件
长任务到底长在哪里. 把轮数拉长,任务并不会自动变成 long-horizon。一个网页按钮连续点一百次,交互很多,状态却几乎没有分叉;修复一个跨包依赖问题可能只调用十几次工具,但中间要保留约束、等待构建、判断回归、撤销错误修改,还要在失败后从可信位置继续。后者对 harness 的要求高得多。更合适的描述由四个量共同组成:依赖深度 、状态分支数 、跨轮约束数 和不可逆动作数 。 可以把某个任务的执行压力粗略写成:
这里引入 帮助分析,论文没有使用这个指标。它揭示了一个容易被步数掩盖的事实:二十步全是只读查询,与二十步里夹着迁移数据库、发送邮件和修改远端权限,难度相差很大。前者失败后重跑即可,后者每次重试都要先确认环境里已经发生了什么。LongHorizon-Harness 把 task state 放到执行上下文之外,正好对准了 和 带来的压力。
依赖深度也不能用工具调用总数替代。若十个子任务可以并行,它们的关键路径可能只有两层;若第十步必须读取第九步生成的版本号,再把它写进远端配置,关键路径就是十层。Manager 规划时应保存依赖图,而非只有一列待办项。一个节点只有在其前驱经过审计后才可进入 ready,这样才能避免「上游只是声称完成,下游已经开始消费」的连锁错误。
从任务目标到可审计条件. 用户目标往往写成「把项目修好」「整理完材料」或「部署到可用」。这些句子可以启动工作,却不能直接交给 Auditor。验证需要把目标拆成可以从环境读取的谓词。例如「修好导入功能」至少可以落成三类条件:目标样例成功、旧格式没有回归、公开接口保持兼容。记验收谓词为 ,完成状态应由它们的合取决定:
若其中某项只能由人判断,例如视觉稿是否符合品牌气质,状态中要明确保留 human_review,不能让模型生成一句赞美就把它算作通过。若某项依赖外部服务,审计报告还要记录观测时间和资源标识,因为今天存在的远端对象,明天可能已经被别人修改。 验收谓词的粒度同样重要。「所有测试通过」看似严格,实际可能把仓库里长期存在的无关失败一起带进来;「新测试通过」又可能漏掉回归。比较稳妥的做法是给合约同时写目标检查与保护检查。目标检查验证本轮希望改变的行为,保护检查验证明确不能破坏的边界。Auditor 的结果随后按条件返回,而非只给一句总评:
| 条件 | 观察 | 结论 |
|---|---|---|
| 带转义引号的 CSV 可导入 | 目标样例退出码 0,字段值匹配 | pass |
| 旧格式保持兼容 | 相关回归集 37/38 | fail |
| 公共 API 未变化 | 导出签名与基线一致 | pass |
这张表会让下一轮计划自然收缩到那一个失败项。没有逐条件证据时,Manager 只能重新阅读整段叙述,随后很容易把「大部分通过」误写成「已经完成」。
轮次时间线与恢复语义. 长任务的时间线至少含四个时刻: 生成合约, 执行动作, 完成验证, 提交状态。环境可能在任意两个时刻之间中断。只保存轮末摘要,无法处理「动作已经发生,状态还没提交」这类最麻烦的窗口。
t_p t_x t_v t_c
规划 ────────── 执行写入 ────────── 独立验证 ─────── 状态提交
▲ ▲
中断点 A 中断点 B
中断点 A 恢复时,系统先检查动作的幂等键和环境版本。若目标文件已经是预期哈希,就进入验证,不能再写一次;若环境仍是旧版本,才重新执行。中断点 B 表示验证可能完成,但报告尚未提交。恢复程序需要读取验证产物的时间戳、输入版本和校验和,确认它仍对应当前环境;对应不上就重新验证。恢复围绕状态转移进行,对话记录只提供复查线索。 墙钟时间也要分开记。设一轮规划、执行、审计和环境启动分别耗时 ,串行总时延为:
Auditor 的 token 占比不能直接推出它占据相同的墙钟比例。文件检查可能 token 很少却等待构建十分钟,GUI 截图判断可能 token 较多却数秒返回。真正决定吞吐的是关键路径上的墙钟时间;真正决定费用的是各角色模型调用、沙箱占用和外部工具成本。部署时应同时画出两条曲线:成功率随预算的变化,以及每个成功任务的平均成本。只报其中一条,容易把昂贵重试制造的增益误认成架构效率。
Auditor 会怎样失效. 只读并不等于可靠。Auditor 可能读错位置、拿到缓存结果、用过期的测试命令,或把「进程正常退出」错当成「业务结果正确」。一个常见陷阱是验证器与 Executor 共享同一份错误假设:Executor 修改了错误的配置副本,Auditor 又恰好读取那份副本,两者意见一致,真实服务仍未改变。 缓解方法是把证据和目标对象绑定。文件类任务记录规范化绝对路径与内容哈希;服务类任务记录 endpoint、资源 ID 与响应中的版本;GUI 任务除了截图,还可读取可访问性树或后端状态。对于缓存敏感的检查,报告中保存运行命令、开始时间、结束时间和输入 checkpoint。证据越接近用户真正关心的结果,越不容易被中间产物骗过。
第二类失效来自验证覆盖不足。假设任务有五项独立条件,Auditor 每项正确检查的概率均为 。在一个极简独立假设下,整体验证全部可靠的概率约为 。即使 ,结果也只有约 。真实条件当然不独立,但这个算例足以说明:长任务会累积验证风险,不能因为单项检查看起来很强,就默认总体验收同样可靠。高风险条件可安排两个异构检查,例如测试结果配合最终状态查询;低风险条件则不必重复调用昂贵模型。
第三类失效是 Auditor 被要求判断它看不到的事实。没有网络权限却要确认远端部署、没有账户权限却要确认邮件已发送,都只能返回 inconclusive。这个结果不会让系统显得漂亮,却保护了状态。把不可见当成功,后续所有计划都会建立在空地上。
预算分配和停止条件. 轮次上限 只是收尾阶段一道保险。更实用的停止判断需要观察边际进展。设第 轮后新增通过的验收权重为 ,花费为 ,则单位成本进展为:
连续几轮 ,可能表示执行策略卡住、验证器不可用,或目标需要用户授权。Manager 此时应切换策略、缩小合约或进入等待,不应原样重复同一轮。若进展存在但成本快速上升,可以把剩余条件按风险排序:先完成决定任务成败的硬条件,再处理低风险修饰项。 角色模型可以按职责分档。Manager 的输入结构化且输出短,通常可以使用较小模型;Executor 面对代码、桌面或复杂工具,能力要求最高;Auditor 的选择取决于验收方式。能由确定性程序完成的检查直接运行程序,涉及语义或视觉判断时再调用模型。论文的 AgentAdapter 允许按角色替换后端,使预算随职责分配,省下三份同档模型的固定开销。
环境漂移与并发写入. MEA 默认每轮都能从环境中读取事实,但真实环境未必静止。用户可能在 Agent 工作期间手动修改文件,另一个服务可能更新远端对象,网页内容也会自行刷新。若 Manager 把 时刻的审计结论直接带到 ,中间变化没有被记录,所谓 verified fact 已经失效。 因此审计事实应带作用域和版本。文件事实绑定内容哈希,数据库事实绑定事务版本或更新时间,API 事实绑定资源 ID 与 ETag。下一轮合约消费某条事实前,先核对它的版本条件。设审计得到事实 时环境版本为 ,动作要求的前置条件可以写为:
版本不一致时,正确状态是 stale,随后重新读取和规划。继续执行会覆盖别人的修改;把全部外部变化都当失败,又会让系统在活跃环境里寸步难行。Manager 要判断变化是否触及当前合约的读写集合:无关文件改变可以忽略,输入对象改变则必须撤销计划。 并发执行还会产生另一类问题。两个 Executor 都从版本 出发,一个写成 ,另一个稍后写成 ,后者可能吞掉前者结果。仅在轮末审计,已经来不及恢复丢失更新。解决办法是写入时使用 compare-and-swap、文件基线哈希或资源版本条件;冲突应回到 Manager,而非让 Executor自行选择覆盖。
GUI 环境最难版本化。截图只能证明某一瞬间的像素,不能稳定标识后台状态。可以组合窗口标题、可访问性节点、页面 URL、关键资源 ID 和截图哈希,得到一个近似 checkpoint。它仍然比代码仓库的 commit 弱,所以高风险 GUI 写入需要更窄的合约,并在动作后立即审计。
人工接管的状态协议. 长任务里有些决定天然需要用户:授权付款、选择两种都合理的产品方向、确认不可逆删除,或提供系统无法读取的凭证。Harness 若把这些情况统一记成 failed,会混淆能力不足与权限边界;若为了保持自动化率自行猜测,又会越权。 waiting 状态至少保存四项:已经验证的进度、等待用户回答的问题、不同答案会影响的后续分支,以及环境是否需要保活。用户返回后,Manager 不能把整段任务从头重播,只需把回答作为新的约束写入 task state,再核对等待期间发生的环境漂移。若远端会话已经过期,则先恢复环境,随后继续原依赖图。
提问也要有边界。能从环境读取的事实不应反复问用户;技术实现细节通常由执行层决定;只有答案会实质改变结果、权限或不可逆成本时,才值得中断。这样的协议把人工接管限制在真正需要决策的位置,避免 Agent 一遇到不确定性就把工作抛回来。 最终报告同样属于状态机。它应从已验证条件生成,列出完成项、未完成项、仍然存在的风险和可复查证据。Executor 的过程描述可以帮助定位,却不能直接进入完成清单。若任务在预算耗尽时结束,报告应保留可继续的 checkpoint,状态是 stopped_with_progress 或同类枚举,而非用一段乐观措辞把半成品包装成完成。
1.4. 最小实现、适用边界与复用方式
一份最小 MEA 实现. 不采用完整仓库,也可以用一个很小的状态机保留核心语义。循环每轮只做一次规划、一次执行和一次审计:
while state.status == "running":
contract = manager.plan(state)
if contract.requires_user:
state.wait(contract.question)
break
checkpoint = environment.snapshot(contract.scope)
execution = executor.run(contract, fresh_context=True)
audit = auditor.verify(contract, environment, read_only=True)
if audit.status == "pass":
state.commit(audit.facts, checkpoint=environment.version())
elif audit.status == "fail":
state.record_failure(audit, checkpoint)
else:
state.record_inconclusive(audit, checkpoint)
短短十几行隐藏了几个必须由实现守住的不变量。fresh_context=True 要确保 Executor 没有偷偷继承上一轮聊天;snapshot(scope) 只覆盖合约涉及的资源,避免昂贵的全环境复制;verify 的工具权限必须在运行时限制为只读;commit 还要检查审计所依据的环境版本仍是当前版本。缺掉任何一项,代码看起来仍像 MEA,语义却已经变了。 测试这段循环时,可以准备固定的假 Manager、Executor 与 Auditor。让 Executor 声称成功但不改环境,状态不能前进;让它修改环境后超时,恢复逻辑应进入验证;让 Auditor 返回 inconclusive,完成项不能增加;让环境在审计后提交前改变,commit 必须拒绝旧报告。这样的测试比让三个模型自由聊一百轮更能证明 Harness 是否真的实现了审计状态转移。
何时不值得使用 MEA. 一次只读查询、几秒内完成且没有副作用的任务,三角色循环可能比任务本身还贵。验收条件无法从环境观察、只能依赖同一个模型主观判断时,独立 Auditor 的收益也有限。还有一类任务,环境变化快到 checkpoint 立即过期,若系统没有版本控制能力,外置状态只会保存大量陈旧事实。 可以用风险来决定是否启用完整循环。动作可逆、依赖浅、验证便宜时,单执行体加终局检查已经足够;依赖变深或需要跨会话恢复时,加入外置 task state;出现不可逆动作、多人并发或高昂失败成本,再启用逐轮 Auditor 和严格版本门。Harness 不该把每个问题都做成一场仪式,它的价值来自让验证强度跟风险匹配。
评测里再补两条曲线. 最终成功率把整条轨迹压成 0 或 1,看不出系统是在第一轮就跑偏,还是推进到九成后死在一个外部故障上。对长任务,可以记录经过审计的加权进度:
把 随轮次画出来,会得到进度曲线。曲线持续上升但最终未通过,说明系统能推进却缺少收尾或恢复;曲线反复下降,通常意味着新动作破坏旧条件,checkpoint 与保护检查需要加强;曲线很早变平,则要检查 Manager 是否不断生成相似合约。 第二条是未核实声明率。设 Executor 报告中共有 个可检验声明,其中 个未经 Auditor 支持就进入 task state,则:
理想的验证门应使 。这个指标比统计 Agent 说了多少次「完成」更接近问题本身,因为语言模型可以换一种措辞表达同样的自我确认。实现时不必对所有自然语言逐句分类,只需检查进入 verified_facts 和 completed 的记录是否都有 audit evidence ID。 恢复能力则可用故障后的有效进展损失衡量。若注入故障前进度为 ,恢复稳定后为 ,损失为 ;再记录恢复所需轮数与成本。好的系统不一定零损失,例如不可逆外部变化可能迫使它撤回一项进度,但应能解释损失来自哪里。只报告恢复后最终成功率,会掩盖系统是否把大量已完成工作重做了一遍。
这三组数字与论文已有的 PassRate、Overall、token 分解并不冲突。成功率回答「收尾阶段做成没有」,进度曲线回答「中间怎样推进」,未核实声明率回答「状态是否被自我叙述污染」,恢复损失回答「遇到故障后保住了多少工作」。Long-horizon 系统的差异,往往正藏在后三项里。
这些过程指标还可以帮助解释跨基准差异。Terminal-Bench 的终态往往能由测试命令读取,Auditor 容易得到强证据;OSWorld 涉及桌面应用、登录态和视觉界面,同一个动作是否完成更难稳定观测。因而,同样的 MEA 结构在不同基准上的收益不能只归结为模型强弱,验证器覆盖率和环境可观测性也会改变上限。部署团队若发现 Auditor token 持续上涨,先看它是否在反复弥补弱观察,而非立刻缩短审计提示词。
进一步说,进度曲线也适合选择 checkpoint。系统不必每轮保存完整环境,可以在高权重条件刚通过、不可逆动作即将发生、或外部依赖完成切换时保存。这样既控制存储成本,也让恢复点靠近真正有价值的进展。固定每五轮保存一次虽然简单,却可能恰好跳过最需要保护的状态。
状态提交必须满足的约束. 1. 状态外置:task state 不在 Executor 上下文里「顺便维护」,而是 harness 层的显式记录。 2. 验证先于提交:只有经 Auditor 独立确认的事实才能进入持久 task state;LLM 自评不算数。 3. 跨轮记忆受控:下一轮决策读取结构化 task state 与 audit report;Executor 原始历史不能绕过审计门进入事实状态。 4. 子任务有界:每轮只执行一个明确定义的 subtask contract,避免「一个会话干到底」。 5. 后端可替换:AgentAdapter 保证换模型/换 harness 不改 MEA 语义。
与单循环 Harness 相比,MEA 的差别包括:
| 路线 | 核心手段 | 与 LongHorizon-Harness 的关系 |
|---|---|---|
| 上下文压缩(CompactionRL、Self-Compacting 等) | 在单会话内摘要/删历史 | 仍假设「一个 growing context」;LH-Harness 直接拆会话 |
| Reflexion / 反思循环 | 模型读自己的失败反思 | 反思仍可能自洽地错;LH-Harness 要求环境客观证据 |
| Verifier / RLVR | 训练期学验证 | LH-Harness 是推理期 harness,可与 verifier 训练互补 |
| Orchard / OpenForge | 训练期在真实 harness 里 rollout | 解决 train-deploy mismatch;LH-Harness 专注部署期状态管理 |
| Argus | 四角色 + verification-gated 状态进化 | 更重的 campaign 级 runtime;MEA 是 lighter 的三角色审计环 |
可复用的任务状态结构. 无论是否采用 LH-Harness 代码,以下抽象可直接迁移到任意 long-horizon agent 系统:
- Audited State Transition:每一轮推进 = 「规划 → 执行 → 审计 → 状态提交」,而非「执行 → 自我感觉完成」。
- Fresh Context Executor:执行层每轮 blank slate,规划层靠结构化 state 而非 raw chat log。
- Subtask Contract:子任务必须带 acceptance criteria,Auditor 可机械对照。
- Single Source of Cross-Round Memory:明确指定「什么可以跨轮」——通常是 verified facts,不是 model narrative。
- Role Budget Split:Manager 便宜、Auditor 中等、Executor 昂贵——架构上允许按角色分配模型档位。
CLI 入口:uv tool install lh-harness → lh-harness init → lh-harness run --task @task.md --dashboard。评测复现见 repo 内 eval/WeaveBench-harness/ 与 eval/OSWorldv2-harness/。