自主闭环 Agent Loop 中验证检查的三种集成方案(设置成本与人工介入权衡)

要把 Agent Loop 推向真正的 unattended run,关键不是让它跑得更久,而是把验证检查变成”不通过就不能停”的硬关卡。三类方案在工程上各有侧重:shell 测试闸、判官式复审、目标驱动循环。它们在设置成本、人工介入频率与适用规模上形成清晰梯度,按团队规模与任务可验证性选取即可。

一、为什么验证必须内置进循环

放任 Agent Loop 自由停下的最大风险是”模型自报完成”。模型对自己产出的信心与实际正确率没有强相关,特别是在测试稀疏、需求模糊的代码区。即便加了步数上限,没有外部验证的循环也只是”撞墙即停”,不是”达标才停”。

把验证放进循环等于把”停下”这件事外包给一个独立于生成器的判断者。即便生成器乐观,验证仍按客观命令(例如 pytest、go test、curl 业务接口)执行,失败就把堆栈与失败用例作为反馈塞回下一轮。停下来的条件第一次变成可观测的客观信号,而不是生成器的主观陈述。

二、方案一:Shell 命令闸(verify-loop.sh)

起步阶段的方案是给循环配一个”闸门脚本”,每次生成器完成后跑一次。脚本的退出码就是通过与否,循环据此决定继续或停止。设置要点:

  1. 选定真正能反映任务完成的命令(测试套件、构建、smoke run);
  2. 把命令包装成 verify.sh,写成可被任意子代理或主代理复用的标准入口;
  3. 给循环加最大步数与可选的成本上限(verify-loop.sh –max-cost USD);
  4. 默认先跑一次”红起步”校验,确认闸门在未改代码上确实失败。
#!/usr/bin/env bash
set -euo pipefail
pytest -q --maxfail=1 || exit 1
go vet ./... || exit 1
curl -fsS http://localhost:8080/healthz >/dev/null || exit 1
echo "GATE PASS"

优势是设置成本极低,几乎任何 CI 都能用。劣势是只验证脚本里写明的内容,未写明的一律不管。在多角度需求或主观产物上容易”绿灯但其实是错的”。

三、方案二:判官式复审(scripts/judge-check.sh)

对正确性、安全性或主观产物,仅靠 shell 闸不够,需要一个独立审稿环节。判官式复审的做法是再起一个只读权限的子代理,让它把生成器产出的 diff 逐行读一遍,按 rubric.md 打分,失败时给出具体意见反馈给主循环。

  1. 编写 rubric.md,把”必须满足的检查点”逐条列成可枚举的项;
  2. 把 judge-check.sh 与 verify.sh 串接,让判官只在 shell 闸通过后再跑(一次成功一审);
  3. 判官必须运行在独立的上下文窗口,不能复用生成器的会话;
  4. 主观产物可让判官读取渲染后的图片,对照 rubric 给出意见。
#!/usr/bin/env bash
set -euo pipefail
# 仅在 shell 闸通过后才调用
claude --print --model claude-opus-4-5 \
  --system-prompt "你是独立判官,按 rubric.md 逐条核对下方 diff" \
  <(git --no-pager diff HEAD) || exit 1

这一方案设置成本比 shell 闸高一档:需要写 rubric、调试判官提示词、设计失败反馈的格式。回报是抓到了 shell 闸完全看不见的”测试通过了但漏了某条业务需求”。

四、方案三:目标驱动循环(goal-based loop)

对自主跑要求高的场景,把”何时停”这件事整体交给一个评估器。Agent Loop 在每轮结束后,把当前产出传给评估器;评估器根据目标陈述(例如”所有 API 鉴权检查在路由层都生效”)返回结构化结论,包含通过/失败、证据、下一轮应改的方向。

  1. 把目标陈述写成可被独立验证的形式,避免”把代码改好”这种含糊措辞;
  2. 写一个 evaluator 函数:输入是工作目录状态,输出是结构化 JSON;
  3. 循环的停止条件改成”evaluator.pass == true”或”达到步数/成本上限”;
  4. 把 evaluator 的调用结果落盘,便于事后审计与改进循环本身。
def evaluate_auth(state):
    routes = list_routes(state)
    missing = [r for r in routes if not has_auth_check(r)]
    return {
        "pass": len(missing) == 0,
        "missing": missing,
        "evidence": [r.path for r in missing],
    }

这种方案在设置成本上明显更高:评估器本身需要写代码或配置逻辑、需要测试其正确性。优势是给”自主跑”提供了最严密的护栏,适合无人值守过夜运行。步数上限与成本上限仍然是必须的硬护栏,缺一不可。

五、三种方案的横向比较

维度 Shell 闸 判官复审 目标驱动循环
设置成本 低(一段 shell) 中(rubric + 判官提示) 高(evaluator + 单元测试)
抓错范围 写明的命令 主观/语义/需求覆盖 任意可观测目标
人工介入 闸门失灵时介入 rubric 改动时介入 评估器改写时介入
适用任务 测试覆盖完善的代码改动 涉及业务语义、UI、安全 无人值守、大规模并行
风险 绿灯即放过 判官与生成器同模型时可靠性下降 evaluator 自身缺陷导致误判

六、混合配置与升级路径

实际工程里三类很少单独使用,更多是”先闸再判”或”先评再判”的组合。最稳的升级路径是:先用 Shell 闸让循环能跑起来,观察哪些任务”绿灯了但不该绿”,针对这些任务加判官;等判官稳定的覆盖面够广,再把停止条件整体迁到目标驱动循环。

  1. 起步阶段只配 Shell 闸,验证循环框架本身跑得通;
  2. 跑出 10–20 个任务后统计误判,把反复误判的场景拆出判官;
  3. 等判官覆盖 80% 以上场景,把停止条件改为”evaluator.pass == true”;
  4. 长期运行时把步数/成本上限、暂停恢复、trace 日志一起加上。

升级的判断标准不是”用了哪个最复杂的方案”,而是”误判率是否低于团队可接受阈值”。每升一档都要重新跑回归任务集,避免评估器自身的变化引入新偏差。

七、避免”自欺式绿灯”

自主循环最隐蔽的失败是验证自身出问题。常见三类:

  1. 测试本身写错:测试在错误条件下也通过,需要在加循环之前先红起步一次;
  2. 判官与生成器同模型:模型对自己的产出有偏好,判官应该用独立会话甚至独立模型;
  3. 评估器目标过宽:写”代码质量好”等于没写,要写”所有路由都覆盖了鉴权检查”。

把这三类写进循环的事前 checklist,能把”看起来通过实则无效”的事故压在最低水平。

常见问题(FAQ)

Q1:Shell 闸够用吗?

对测试覆盖完善的代码改动够用;对业务语义、UI 效果或安全要求,必须叠加判官或目标驱动。

Q2:判官用与生成器不同的模型有必要吗?

有必要。判官独立上下文是底线,独立模型能进一步削弱”自我偏好”,提升判官的稳定性。

Q3:目标驱动循环的 evaluator 怎么写测试?

准备一组已知结果的回归集,跑 evaluator 比对结论与已知结果,覆盖率与单元测试同等重要。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
其AI的头像其AI普通用户

相关推荐

返回顶部