news 2026/10/14 16:58:36

Bernstein的Janitor验证体系:为什么AI Agent的自我报告不能直接信任

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Bernstein的Janitor验证体系:为什么AI Agent的自我报告不能直接信任

【免费下载链接】bernstein

The open‑source AI Agents Governance & Orchestration framework: write the rules declaratively, Bernstein enforces them and produces the verifiable, replayable record. Free, Apache-2.0. https://bernstein.run

项目地址:https://gitcode.com/gh_mirrors/be/bernstein
点击查看免费下载

在 AI Agent 自动化开发流程中,最大的隐患之一不是"Agent 写不出代码",而是"Agent 声称做完了"。Bernstein是一个开源的 AI Agent 治理与编排框架(Governance & Orchestration Framework),它的核心组件Janitor(清道夫验证器)专门解决"自我报告不可信"问题:不采信 Agent 的口头汇报,而是用可执行的完成信号、工作归属归因和带签名的验证凭证,对每个任务做独立裁决。本文带你完整走一遍这套验证体系的设计思路。

为什么"我做完了"这句话不能直接采信

LLM 驱动的 Agent 有一个被反复观察到的特性:自报的置信度与实际正确性并不相关。Bernstein 的文档对此有明确的结论(docs/quality/empirical-confidence.md):模型自评的 confidence 无法作为决策依据,单次运行的结果也过于嘈杂。

所以 Bernstein 的原则很简单:Agent 只负责干活,"干没干完"由独立于 Agent 的验证层裁决。验证逻辑集中在 janitor.py,它是每个任务完成后的第一道关卡——官方架构文档将其称为质量管线的核心(docs/architecture/quality-pipeline.md)。

值得注意的是,Janitor 规则里记录的"历史教训"本身就来自真实事故,例如:

  • 误归属(Misattribution):一个没有改任何文件的"经理"任务,因为子任务的改动恰好满足了它的完成信号而"顺理成章"地通过了验证;
  • 橡皮图章孤兒(Rubber-stamped orphans):崩溃恢复产生的"自动完成"任务(0 提交、0 token、空 diff)被当作完成,因为"没有失败的信号"被误读成了"通过"。

这两类事故直接催生了下面这些防线。

第一道防线:完成信号(Completion Signals)

Bernstein 不信任自然语言汇报,而是要求每个任务在规划阶段就声明一组可执行的完成信号(completion signals),验证时对文件系统逐一检查:

信号类型含义验证方式
path_exists文件/目录已交付检查路径是否存在(精确匹配,临时 worktree 内的文件不算数)
test_passes测试通过实际运行命令,退出码必须为 0
file_contains文件包含指定内容内容匹配检查
absence_verified"确实没有"类声明必须对应到一次有完整覆盖记录的工具调用,缺失证据一律 fail-closed
llm_judge模糊任务的主观评判异步 LLM 裁判(见下文)
schema_valid/hash_stable等产物字节级校验只允许在"产物模式"下评估,文件系统路径直接 fail-closed

其中两个细节体现了"防作弊"思路:

  1. 路径不能指进临时工作区。Agent 在.sdd/worktrees/里写的文件不算交付——run 结束后 worktree 会被删除,Janitor 会把工作区内的路径翻译成仓库相对路径再对主检出做验证;
  2. fail-closed 设计。任何无法评估的信号(比如产物模式信号出现在文件系统路径上)不会被当作"通过",而是明确判负。"没被检查过的声明"永远不会读成"已验证"。

第二道防线:工作归属归因(Attribution)

信号全过还不够——Janitor 还要回答"这些改动确实是这个任务做的吗?"

janitor.py 中的归因逻辑按优先级解析:

  1. 查找 commit message 中引用了当前任务 id 的提交(最强证据);
  2. 回退到最近一次提交、且限定在任务声明的owned_files范围内(弱证据,会明确记录"attribution 较弱")。

判定结果分三档:

  • 空 diff + 非 no-op 任务 → 直接拒绝(REJECT),这就是"空 diff 守卫",专治橡皮图章式完成;
  • 空 diff 但有不平凡信号通过(如test_passes真实跑通)→ 接受但标记警告,提示人工复核;
  • 规划类任务的"产物"是任务图本身,只要分解出了子任务即可凭此通过,且会在日志中记录子任务列表——接受是"可审计的",而不是按任务类型一刀切豁免。

第三道防线:LLM Judge 也有"置信度门槛"

对难以用确定性信号描述的任务(如"代码质量是否达标"),Bernstein 引入了llm_judge信号:把任务描述、评估标准和 git diff 交给一个独立的裁判模型(模板见 templates/prompts/judge.md),要求返回结构化 JSON 判定。

但裁判本身也可能"说谎"或"失误",所以配套了多重保险:

  • 置信度阈值 0.7:低于阈值的 accept 判定会被标记"需人工复核",而不是直接采信;
  • 判定重试上限 2 次:judge 判retry时自动创建修复任务,超限即停,防止无限循环烧钱;
  • 降级 fail-closed:LLM 调用失败、返回空、JSON 解析失败等一切降级场景,都会被编码为"零置信度 + 标记复核"的 retry,绝不静默变成通过;
  • 成本封顶:diff 截断在 10,000 字符、响应限 1024 token,单次判定成本约几分钱。

Verifier Ladder:验证过程本身也可以被验证

"验证者可信吗?"这个问题 Bernstein 用 **Verifier Ladder(验证阶梯)**回答(docs/sdd/verifier-ladder.md,实现见 verifier_ladder.py):

把"是否可合并"的单个布尔值拆成三层有序凭证:

  1. deterministic 层:完成信号 + 归因 + guardrails 等确定性检查;
  2. judge 层:LLM 裁判的裁决;
  3. human 层:人工共识/评审。

每一层只要运行过,就封一条冻结的TierRecord(配置哈希、输入哈希、证据哈希、裁决)进 lineage 签名链;复合LadderReceipt再把这些层绑定成一个merge_eligible声明。关键设计是**"验证即重算"**:bernstein verify ladder <receipt-hash>会重新哈希、重新推导裁决,并逐条核对每层的 spine 锚点——哪怕 receipt 内部哈希自洽,只要存储的merge_eligible不被层裁决所蕴含,也会被拒绝。连"裁判被咨询但从未实际裁决"这种情况都会诚实地记为skip,而不是悄悄消失。

未验证完成的"仪表盘告警":Verification Nudge

就算有 Janitor,仍可能出现"任务完成了但没有任何验证痕迹"(没跑测试、没过质量门、没查完成信号)的情况。Bernstein 用 verification_nudge.py 对此建账:

  • 每次完成写一条 append-only 记录到.sdd/metrics/verification_nudges.jsonl;
  • 当窗口内未验证完成占比 > 30%(默认阈值)且完成数 ≥ 3时,在bernstein status、TUI 和/status/API 中触发告警;
  • 配套运维手册给出了标准处置流程:先抽查一个被标记任务,区分"Agent 真的跳过了验证"还是"日志摘要解析漏了证据"(docs/operations/verification-tracking.md)。

这套机制和 Janitor 的关系是互补的:Nudge 是面向操作员的粗粒度健康信号,Janitor 是面向任务的细粒度合并门禁。

失败之后:不阻塞,而是回流

验证失败时,Bernstein 不只是"挡住"。失败结果会反馈给 cascade-router(docs/architecture/quality-pipeline.md):先在同一模型链上换更强模型重试(sonnet → opus),同时记录成本与原因到.sdd/metrics/cascade_chains.jsonl。可选的跨模型验证器(cross_model_verifier.py)还会让另一个厂商的模型来审查 diff——"写代码的 != 审代码的"。

总结:信任是怎么被"设计"出来的

回头看,Bernstein 的 Janitor 体系给出的答案并不复杂,但足够完整:

  • 📌不信声明:完成信号在规划期声明,验证期对文件系统执行;
  • 📌不信巧合:空 diff 守卫 + 任务归因,堵死"蹭别人的功劳";
  • 📌不信裁判:置信度阈值 + 重试上限 + 降级 fail-closed;
  • 📌不信记录:Verifier Ladder 让验证过程本身可离线重算、可签名校验。

对普通用户的启示是:当你让 AI Agent 自动改代码时,把"验收标准"从提示词搬进可执行的检查里,比任何"请仔细完成"的叮嘱都有效。

延伸阅读

  • 质量管线全景:docs/architecture/quality-pipeline.md
  • Verifier Ladder 设计文档:docs/sdd/verifier-ladder.md
  • 未验证完成告警运维指南:docs/operations/verification-tracking.md
  • Spec-as-test 循环:docs/concepts/spec-as-test.md
  • Janitor 核心实现:src/bernstein/core/quality/janitor.py

【免费下载链接】bernstein

The open‑source AI Agents Governance & Orchestration framework: write the rules declaratively, Bernstein enforces them and produces the verifiable, replayable record. Free, Apache-2.0. https://bernstein.run

项目地址:https://gitcode.com/gh_mirrors/be/bernstein
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 16:58:17

ESP32舵机控制全攻略:从PWM原理到平滑运动与机械臂实践

舵机大概是单片机入门里第一个能让你直接看到"动起来"的元件。拧一下摇杆&#xff0c;云台上的摄像头就跟着转&#xff1b;写一段扫臂程序&#xff0c;机械手就从左划到右。不过我自己第一次把三个舵机直接插在 ESP32 开发板的 5V 引脚上时&#xff0c;串口先是乱码&…

作者头像 李华
网站建设 2026/10/14 16:57:34

ponytail插件是什么?轻量级即插即用工具的核心机制与使用指南

1. 从“ponytail”这个热词说起&#xff1a;它到底指什么第一次看到“ponytail”被当成一个技术热词来搜&#xff0c;我其实愣了一下。这个词本意是“马尾辫”&#xff0c;一个再日常不过的发型词&#xff0c;怎么就跟“skill”“插件”“如何使用”这些词绑在一起了&#xff1…

作者头像 李华
网站建设 2026/10/14 16:57:24

逆傅里叶变换 MATLAB 实战:从频谱到波形的完整落地与避坑指南

简介&#xff1a;这份资源围绕逆傅里叶变换&#xff08;IFFT&#xff09;在MATLAB中的实现展开&#xff0c;面向正在学习数字信号处理、通信工程或图像频域分析的学生与工程师&#xff0c;帮助理解如何将频域信息还原为时域信号。压缩包内仅含1个m文件&#xff0c;体积约244B&a…

作者头像 李华
网站建设 2026/10/14 16:56:27

STM32 USART串口配置详解:从寄存器到中断的嵌入式实践

1. 为什么第四章先讲串口&#xff0c;而不是直接上定时器1.1 串口在嵌入式开发里的角色翻过前三章的朋友应该都有体会&#xff0c;从点亮一颗LED到摆弄外部中断&#xff0c;STM32的学习曲线其实并不陡&#xff0c;真正让人开始觉得"有点东西"的&#xff0c;往往是第四…

作者头像 李华