从0打造编码Agent 阅读 + 实验 ≈ 25 分钟 页内实验 ×1
A3 权限与审批:它要执行 rm -rf 怎么办? 第 4 课

让另一个模型来审批,审批者该有多大权限?

模型审批
auto 把「问人」换成「问模型」,可 Anthropic 自报它对真实越权动作仍有 17% 漏判。审批者如果和被审者共享上下文、手里还有写权限,被注入一次就全线失守。Codex 的 Guardian 给了一套可读的答案:独立会话、历史只当证据、只读权限、任何故障都不放行。
❓

本课一问:上一课的 auto 模式把「问人」换成了「问另一个模型」。这个审批者该看到什么、手里能有什么、出了故障默认怎样?

这一课先不碰:分类器怎么训练、提示词怎么写(各家不公开或不在 pin 里);规则与审批都放行之后的最后一道防线——操作系统沙箱(A4);多个 agent 之间的分工(A7)。

从已有出发

在上一课的组件里,我们真实运行中的 139 次工具调用切到 auto 模式后,读文件和工作区内的编辑都直接放行,只有跑测试的 37 次 bash 被送去分类器。修 test_parse_date 的每一次测试命令,放行与否就取决于另一个模型的一次判断。

从已有出发 · 累计数据流 点已学环节看它回答什么
每一轮循环都经过

审批者本身也是一个模型:它会读到主 agent 读过的内容,也会犯错。问题从「要不要问」变成了「问谁、让它看什么、给它什么权力」。

先自己设计:让主 agent 自己再审一遍

最省事的做法:审批就是再调一次同一个模型——同一段上下文、同一套工具,问它「这一步安全吗」。

  1. ① 朴素方案
  2. ② 它在哪失败
  3. ③ 改进方案
朴素方案审批者 = 主 agent 自己(同一上下文、同一套工具)
朴素设计会出什么问题
审批者读的是主 agent 的整段上下文主 agent 读过的网页、README、测试输出里如果藏着「忽略之前的规则」,审批者分不清它和用户指令
审批者手里有写文件、跑命令的工具被说服的审批者不必「批准」任何东西,它可以自己执行
审批调用出错、超时时没有约定实现者很容易写成「出错就放行」,故障变成绕过审批的路
审批者的判断本身即使是专门的分类器,真实越权动作上也有 17% 漏判

改进:Codex 的 Guardian,逐条看源码

Codex 把「用模型做审批人」实现在 core/src/guardian/(pin 8cabf5a),产品上叫 Auto-review(配置 approvals_reviewer = "auto_review",界面上叫 Approve for me)。它的定位一句话:「a reviewer swap, not a permission grant」——换的是谁来点头,不是能做什么 。

审批者的权限必须严格小于被审者
同一个风险,两种设计各会怎样

行号均在 openai/codex@8cabf5a 的只读副本上核对;Codex 为 Apache-2.0。产品名 Auto-review、「reviewer swap, not a permission grant」出自 learn.chatgpt.com 现行文档(2026-09-26)。

🎯

试三件事:① 点内框里「权限档锁成 read_only」和「审批策略锁成 never」,读 pin 源码原文:审批者能查证,不能写、不能提权;② 切到「朴素:主 agent 自己审」,对比两个框的颜色和能力;③ 依次点三个情景,尤其是「审批调用超时了」:Guardian 不执行,但会告诉主 agent「超时本身不证明动作不安全」。

把「什么时候才真正执行」写成一个条件,每一项都能在 pin 里找到:

Guardian 放行一个动作的条件(openai/codex@8cabf5a)
⇔ ∧ ∧
👆 公式里带下划线的每一项都可以点——点哪项,讲哪项。
被拒之后还有熔断:同一轮连续被拒 3 次,或最近 50 次审查里被拒 10 次,就中止这一轮(mod.rs:55-58),不让主 agent 换着写法反复试。

三家的模型审批并排看

Claude Code autoCodex Auto-review(Guardian)Hermes smart
谁来审一个分类器模型,不跟随你选的主模型一个独立的 Codex 审查会话一个辅助模型,一次调用最多回 16 个 token
审什么规则与只读 / 项目内编辑之外的一切本来要停下来问人的越界请求先被危险模式命中的 shell 命令
它看到什么每次检查发送一部分会话记录加待执行的动作压缩后的会话记录(作为不可信证据)加这次请求只有这条命令(去掉注释、包进定界符)和它被标记的原因
它能做什么只返回判决三个工具、只读权限、不能再申请审批只回 APPROVE / DENY / ESCALATE 一个词
出故障时服务端没给判决就拒绝执行不执行(fail closed)交给人(escalate)
被拒多了连续 3 次或累计 20 次:暂停 auto,改回问人连续 3 次或 50 次内 10 次:中止这一轮连续 3 次:返回给模型的提示升级为「停下来找用户」
出处官方文档 permission-modes(2026-09-26)pin guardian/;learn.chatgpt.com 文档pin tools/approval.py:3054-3144,config_defaults.py:2098-2114

三家的共同点比差异更重要:审批者拿到的权力都比被审者小(只返回判决、或只读),出故障时都不会默默放行(拒绝、不执行或交给人)。差别在于让它看多少:Hermes 只给一条命令,几乎无从注入,也几乎没有上下文可判断;Codex 给压缩历史但标成不可信;Claude Code 给一部分会话记录。

权限设计的演进:每一代都被上一代的某个真数字逼出来
  1. Pi 核心、bypassPermissions、CoreCoder --yes
    解决了零打断,模型想跑什么马上跑。
    卡在L1 的 6 条本意危险的构造命令(含 rm -rf /)会全部直接执行。
  2. lcc s01 / s03、CoreCoder bash 正则、Pi permission-gate
    解决了把已知危险的写法挡在执行之前,代码只有几行。
    卡在lcc s03 三道闸(pin 源码实跑):6 条危险命令里漏拦 4 条,5 条日常命令里误拦 2 条(cat sudoku_solver.py 因含子串 sudo 被拒)。
  3. 第一代 每次都问人
    CoreCoder 交互模式、Claude Code Manual、lcc s03 的第三道闸
    解决了判断交给人,规则写不全也不怕。
    卡在我们 26 次真实运行的 139 次工具调用,在 CoreCoder 交互模式下有 74 次要停下来问(53%);Anthropic 自报用户批准了约 93% 的弹窗——问多了,人就不看了。
  4. Claude Code(deny → ask → allow)、OpenCode(last-match)、Codex(最严格者胜)
    解决了把常见的放行和拒绝写成规则,只有规则没覆盖的才问人。
    卡在同一份规则换一种求值语义可能换一个答案:同一份 rules-standard.json 改用 first-match,真实运行 pd-firstmatch-s1 里模型的 python -m unittest -v test_dateparse.py 被规则 #8 拒掉。
  5. 第三代 分层放行 + 模型审批 你在这里
    Claude Code auto、Codex Auto-review(代码名 Guardian)、Hermes smart
    解决了只读直放、项目内编辑免审,其余交给另一个模型判断;弹窗接近清零。
    卡在Anthropic 自报:auto 分类器在真实越权动作上仍有 17% 漏判(n = 52),官方原话「does not guarantee safety」。
  6. 下一章 与 OS 沙箱分层
    Claude Code sandbox、Codex Seatbelt / bubblewrap
    解决了规则管「允许调用什么」,沙箱管「调用之后能碰到什么」。
    卡在L1 的 python3 -c "import shutil; shutil.rmtree(…)" 在四个黑名单里被 4 个全部放行;规则看不见脚本在运行时做什么 → A4。

数字口径:黑名单与「每次都问」由原实现在 pin 源码上实跑(a03-permission-fixtures.json,2026-09-26);真实运行 = 本课程项目 miniagent 用 Qwen/Qwen3-8B-MLX-4bit 本机录制;93% 与 17% 为 Anthropic 官方自报。

⚠

常见误解一:「有模型审批,就安全了。」

Claude Code 文档的原话是 auto 模式「does not guarantee safety」;官方自报它对真实越权动作漏判 17%。模型审批的价值是把弹窗从人身上拿走、同时保留一道判断,不是提供保证。保证要靠下一章的操作系统沙箱。

常见误解二:「审批者能力越强、工具越全,审得越准。」

方向反了。审批者的工具多一件,被注入之后能直接做的坏事就多一件。Codex 只给审批者三个工具,并锁成只读、不能再申请审批;Hermes 干脆不给工具。

证据三问

问本课的回答
① 它解决什么问题?把大部分审批从人身上拿走,同时保留一道独立判断
② 为什么审批者的权限要更小?审批者会读到不可信内容;它能做的事越少,被注入后的损失越小;故障默认不执行,才不会把故障变成绕路
③ 效果如何?只有 Anthropic 公开了误差:两段分类器误拦 0.4%、漏判 17%;Codex 与 Hermes 没有公开同类数字

一句话

📌

审批者必须比被审者权限更小,读到的历史只当证据,出任何故障都默认不执行。

🚦

先停在这里:记住三条约束——权限更小、历史只当证据、fail closed。
再深一层:在上面的边界图里把 Guardian 的九条能力逐条点开,每条都有 pin 源码原文;然后去实验课。

下一个缺口

规则和审批都放行了一个 python -c,谁拦?

python3 -c "import shutil; shutil.rmtree(…)" 在第 1 课的四个黑名单里全部放行;就算审批者看了,它看到的也只是一行命令文字,删除发生在 Python 进程里。规则和审批都管「允许调用什么」,管不了「调用之后能碰到什么」。下一章 A4 讲操作系统沙箱:不管命令怎么写,越界的系统调用都会被内核拒绝。

你可能会问