AIClaw 的 Harness Runtime:让 Agent 只有拿到证据才能结束
先说几个核心判断:AIClaw 最近在 origin/master 上连续落了三组相关提交,核心都指向一个新执行层——Harness Runtime。这个设计的意图很明确:很多 Agent 系统会把“模型说自己做完了”当成完成信号,但真实执行里,工具证据、文件产物、计划终态、阻塞原因,往往都还没闭环。AIClaw 这次把“模型提议完成”和“执行层放行完成”明确拆开了。

2026-07-02feat: add harness execution protocol2026-07-06refactor(agent): integrate harness runtime verifier2026-07-09feat(agent): align harness execution runtime
先说问题
常见的 Agent 失败模式其实很像:模型先给出计划,调了几个工具,输出一段看起来很像总结的话,但实际没有足够证据,或者承诺的文件没交付,甚至只是在汇报“我接下来继续做”。如果运行时直接接受这类答复,执行记录表面上成功,实际却把未完成任务包装成了完成。
Harness Runtime 就是为解决这个问题而来。按 README 里的描述,它被设计成一个独立运行层:先根据任务构造 Contract,再记录 Evidence,在工具前后和最终答复前后做 Validate,必要时再用 Correct 机制要求模型纠偏。
核心设计:Contract -> Evidence -> Validate -> Correct
设计文档把整体模型抽象成四段:Contract -> Evidence -> Validate -> Correct。对应到代码里,大致是这样:
TaskContract:根据用户目标、Agent profile、工具数量、附件、Plan State 等信息,推导这次执行到底要求什么。EvidenceLedger:记录执行过程中真正发生了什么。Validator:在不同阶段判断当前状态能不能继续。CorrectionState:如果校验失败,生成结构化纠偏提示,让模型继续补齐。
这里最关键的一点是,AIClaw 不再只看最终输出文本,而是看“这条回答背后有没有足够执行证据”。
Contract 到底约束什么
pkg/harness/contract.go 里现在会推导多个关键约束:是否要求 Plan、是否要求 Tool Evidence、是否要求最终答复、是否要求文件产物、输出模式是 text、file、mixed 还是 json,以及最多允许几次纠偏。
拿一个“修改代码并生成文件”的任务来说,Contract 自然倾向于要求:需要 Plan、需要工具执行证据、需要产物校验,最终不能只给一句“我已经处理好了”。这让执行层有了明确的放行标准。
Evidence 记录的不只是工具成功
EvidenceLedger 现在采集的信息很完整,不只看“调用过哪个工具”。它会记录:实际执行过的业务工具、每个工具轮的 ToolEvent、文件产物与附件信息、当前 Plan 快照、校验事件与纠偏事件,还有阻塞证据——例如权限不足、认证失败、策略拦截、资源不存在、限流、超时。
这点很重要,因为很多真实失败并不是“工具报错”这么简单,而是不同类型的 blocker 需要不同的最终答复策略。比如:权限问题应该明确告诉用户缺什么权限;认证问题应该提示重新登录或补授权;资源不存在应该让用户确认名称或配置;可恢复的超时和限流,则可以先重试或解释外部服务状态。
四个校验关口
AIClaw 现在把校验拆成四个阶段:
| Stage | 作用 |
|---|---|
pre_tool | 工具调用前先检查策略是否允许 |
post_tool | 工具轮结束后检查当前证据是否足够 |
pre_final | 模型准备结束时检查最终答复是否真的可交付 |
pre_sa ve | 渲染完附件链接后,保存前再次确认交付内容没丢 |
这种拆分比“最后统一判断一次”更实用。因为不同问题出现的位置不同:有些是工具还没跑就该拦住;有些是工具跑了但失败类型需要进入证据系统;有些是最终答复看起来完整,其实只是进度汇报;有些是任务要求交文件,但回答里没有真正可引用的文件标识。Harness Runtime 正是在这些位置上逐层收口。
它怎么识别“假完成”
这次实现里特别实用的一点,是 pkg/harness/outcome.go 对最终结果做了更细的分类:success、blocked、partial、progress_only、unknown。这意味着 AIClaw 不会再把“非空文本”直接当成完成。
如果模型输出的是“我接下来继续生成”、“请稍等,我正在处理”或“下一步我会整理文件”,这类内容会更容易被视为 progress_only,在 pre_final 阶段被拦下来。反过来,如果工具失败是因为权限或认证问题,Harness 也能要求最终答复显式解释阻塞原因,而不是给出一段模糊总结。
纠偏不是无限重试
校验失败后,AIClaw 不会立刻结束,也不会无上限地让模型重试。internal/agent/harness_verifier.go 里把纠偏统一成了一个有预算的 nudge 机制。像 final gate 被拒绝、tool round 证据不足、模型输出被截断、流式中断或空输出后的恢复提示,这些情况都会消耗同一套纠偏预算。
如果还有剩余次数,就追加 correction prompt,让模型补证据、补结果、补阻塞说明。如果次数耗尽,系统就会明确失败收口,而不是把未完成结果包装成完成。
和 Runtime Plan State 的配合更完整了
这组改动不是孤立功能,它和 AIClaw 现有的 Runtime Plan State 是联动的。当 Contract 推导出这次任务需要 Plan,而当前会话又没有 active plan 时,Harness 可以直接 bootstrap 一个初始计划模板,大致包括:理解目标和依赖信息、执行必要工具并收集证据、校验证据和输出要求、汇总结果并交付最终答复。
这样做的好处是,Plan 仍然是运行时状态的一部分,不会退回到聊天正文里的 TODO 文本;而 verifier 又能确保 plan 到达终态后,最终答复才允许结束。
新增的 finish 工具也很关键
2026-07-09 的对齐工作里,还新增了一个内置 finish 工具。它的意义不是“让模型更容易结束”,而是让模型可以用结构化方式提交“这是最终答复”,然后再由 Harness 做一次 explicit final gate 校验。也就是说:模型可以声明“我准备结束了”,但真正决定能不能结束的,还是执行层。这个边界很清晰,也更方便在执行日志里排查问题。
对使用者有什么实际价值
这不是一个“让回答更像 AI”的功能,恰恰相反,它是在压缩 Agent 幻觉式完成的空间。对于真正做生产任务的系统,这类能力会直接影响可操作性:更少“看起来完成,实际没完成”的结果;更清晰的 blocker 说明;更稳定的附件与文件交付校验;出问题时,execution log 里能看到明确的 harness 校验/纠偏轨迹。
README 里现在把 AIClaw 定位成一个强调显式执行轨迹、可观察运行状态、少一点“隐形魔法”的自托管 Agent 平台。Harness Runtime 正是这个方向里非常核心的一步。
想继续看代码,可以从这些文件开始
docs/design/agent-harness-runtime.mdinternal/agent/harness.gointernal/agent/harness_verifier.gointernal/agent/finish_tool.gopkg/harness/contract.gopkg/harness/runtime.gopkg/harness/outcome.go
如果你也在做 Agent 执行层,这部分很值得细看。它讨论的不是“提示词怎么写更聪明”,而是“模型给出完成信号之后,系统凭什么相信它真的完成了”。