凌晨一点半,你把一个批量任务丢给 Codex:给 80 个测试文件补用例,顺便把 lint 修干净。

早上七点回来,终端停在第 3 个审批提示上。光标在 [y/N] 后面闪了一夜,后面的活一行没动。

这是现在 agentic coding 最容易被忽略的一种失败。不是模型不会写,是它每往外走一步都要你点头,而你不可能 24 小时坐在屏幕前点头。

审批提示为什么成了瓶颈#

Codex 的两层控制里,沙箱和审批分工不同。沙箱定死了能碰什么,审批决定这次要不要问你。默认组合是 workspace-write 加 on-request:写项目内的文件不用问,越出这个范围才问。

问题出在越界操作的密度上。一个 80 个文件的批量任务,中间会夹着装包、curl 拉 schema、写 /tmp 临时文件、跑 git 子命令,几十次审批请求。人在的时候还能按,人不在就全停。

另一个极端是把 approval_policy 直接设成 never。审批消失了,护栏也一起消失了,这等于拿安全换通宵。

Guardian 子代理就是填在这个缝里的东西。

Guardian 是什么#

它是一个内置的审稿人,独立于主代理之外跑一次模型调用。链路是这样:

主代理想执行工具调用
    ↓ 触发 approval_policy
Guardian 评估这个动作
    ↓
放行 / 拒绝 / 升级给人

它 2026 年 4 月随 Smart Approvals 路由一起进来(v0.119),v0.160.0 才补上真正让它好用的部分:跨会话和跨代理的上下文。

有个细节值得单独拎出来:Guardian 自己锁在只读沙箱里,approval_policy 固定为 never,也不继承你的 exec-policy 规则。审稿人不能改稿,也不能给自己开权限。这条设计比它判得准不准更重要。

它到底看什么#

公开资料里,Guardian 评的东西有四类:

操作类型。cat 一个仓库根目录的文本文件,风险接近零;curl 一个外部主机,或者在仓库外面 rm,直接往上抬。

路径范围。写在 writable_roots 里、读在 readable_roots 里,算低风险。越界,或者碰到凭据、shell 配置、系统目录这类路径,升级处理。

网络目的地。把出站主机名对一遍已声明的 MCP 来源和已知安全模式,陌生域名算高风险。

MCP 服务器来源。从市场装的、外部托管的服务器,比你自己在 config.toml 里写死的那几个审得更保守。

要点在于它不是查表。同一条 npm test,昨天放行,今天可能被拦,取决于这个 session 声明了什么范围、主代理正在干什么、跟你早先说过的话是否一致。听起来灵活,代价是同样的事在不同 session 里结果不一样,你没法靠"我以前这么干过"来预判。

源码里的真实数字#

PR #13692(2026 年 3 月)把 MVP 合进去的时候,几个常数定下来了,比任何宣传文案都实在:

参数值含义
risk_score0 到 100 的整数风险刻度
放行阈值< 8080 分及以上直接拒绝
审查超时90 秒超时按 100 分处理
失败策略fail closed子代理起不来、输出不是合法 JSON,一律按拒绝
对话预算10000 token人写的消息总预算
工具预算10000 token工具调用与结果的总预算
单条上限2000 / 1000 token消息 / 工具结果各自截断
近期条目40 条保留最近多少条非用户上下文
审查模型优先 gpt-5.4没有则退回父 turn 的模型

90 秒超时这一条把设计取向暴露得很清楚:宁可卡住人,也不放过去。fail closed 在安全工程里是正确做法,但它跟"我要让它半夜自己干活"的诉求是反着的。Guardian 半夜超时一次,你的任务就停在那儿,等你早上回来处理。

顺带说一个容易踩的坑:有的文章贴的审计日志里 risk_score 是 0.12 这种小数,源码里是 0 到 100 的整数。看日志之前先确认你手上是哪个刻度,不然 0.12 和 12 会被当成两件事。

v0.160.0 补的是上下文#

v0.160.0(2026 年 10 月 1 日)加了两个可选的上下文来源,都默认关着。

会话指令上下文。你在 session 开头说过"只写 src/,别碰 migration 文件",几个小时后主代理早就把这句话挤出上下文窗口了,Guardian 还能捞回来,用它判断眼前这个动作算不算违背指令。

[guardian]
use_session_instruction_context = true

交接上下文。多代理场景里,worker 触发审批时,Guardian 以前只看得到 worker 眼前那一小片。打开 guardian_root_handoff_context 之后,它能读到 orchestrator 当初交给 worker 的原始任务,知道这个动作在整个任务里的位置。

[guardian]
guardian_root_handoff_context = true   # 默认关闭

为什么默认关,理由很直白:多读上下文就多花 token、多等延迟。还有一层不太明显的风险,这两项把"你早先说过的话"提升成了策略来源,一旦那句话本身有歧义,这份歧义会被固化进后面几小时的每一个决定里。

软门和硬墙别搞混#

这是我认为最需要说清楚的一点。sandboxPolicy 是硬边界,OS 层面挡住,Guardian 判什么都越不过去。Guardian 是软判断,它只能决定这次要不要问你,挡不住沙箱外面的事。

两个一起用才有意义:

# ~/.codex/config.toml

[approval]
approvals_reviewer = "guardian_subagent"
approval_policy = "auto-edit"

[sandbox]
enabled = true
writable_roots = ["./src", "./tests"]
network_mode = "restricted"

这样配下去,文件编辑直接过,shell 命令走 Guardian,写入范围由沙箱兜底。最坏情况变成"Guardian 放行了一条 src/ 里的坏命令",而不是"Guardian 放行了一次越界写入"。前者的爆炸半径可控,后者不可控。

什么时候别开#

外部副作用难以回滚的操作。付款、发邮件、打生产环境的 webhook,误判一次就是真金白银。这类用 [tools.X] 单独覆盖回人工,别让风险分替你决定。

CI 和无头环境。没有会话指令上下文,风险模型的可信度下降。CI 里直接 full-auto 加严格沙箱,比指望 Guardian 稳。

writable_roots 里躺着凭据。路径风险启发式在这种目录上不可靠,沙箱硬拦比模型判断靠谱得多。

日志比阈值更值得看#

Guardian 每个决定都会往 session 里发一条 warning,格式是 Guardian approved/denied approval request (分数/100, 等级): 理由。

麻烦的是"放行"那条不会打断你,跟着别的输出一起滚过去就没了。默认状态下,你实际感觉到的是"任务顺利跑完了",而不是"有个模型替你点了 40 次头,其中 3 次它自己也不太确定"。

所以启用之后第一件事应该是把 guardian_decision 记录捞出来,重点看两种:分数偏高但被放行的,和被拒绝但你事后觉得该放行的。前者是模型和你判断分歧的边界地带,后者说明你的沙箱范围或者指令写得有问题。跑一周,这个名单比调阈值有用得多。

我的看法#

这个功能的本质是把信任分层:硬边界交给操作系统,重复性的判断交给一个便宜的模型,不可逆的事留给人。方向我认同,因为人类审批的瓶颈从来不在判断质量,在出勤率。

但有两点得说清楚。

一是 80 分这个门槛是写死在源码里的全局常数,目前没看到按仓库调整的入口。等于你在别人的风险函数上做自己的决策。对多数业务够用,对金融、医疗这类行业,20 分的缓冲不够看。

二是收益和代价不对称。它替你省下的是按 40 次确认的时间,赔进去的是判断质量的方差变大。这个交换划不划算,取决于你能不能看见它的判断过程。看不见,就别开。

一个务实的启用顺序:

  • 第一周用 auto-edit 加 Guardian,writable_roots 收窄到 src 和 tests,只看日志不改别的
  • 每天扫一遍高分放行的记录,确认没有你接受不了的类型
  • 稳定之后打开 use_session_instruction_context
  • 上多代理任务再打开 guardian_root_handoff_context
  • 付款、发消息、打生产接口这类权限,永远不要交出去

Guardian 不会让 Codex 变成可以彻底撒手的工具。它只是把"你在不在场"从硬约束降级成了软约束,剩下的判断责任还在你这边,只是从按键盘转移到了读日志。


参考来源

  • Daniel Vaughan, The Guardian Subagent: How Codex v0.160.0’s Risk-Based Approval Framework Works, 2026-10-17:https://codex.danielvaughan.com/2026/10/17/guardian-subagent-v0160-risk-based-approval-framework-codex-cli/
  • openai/codex PR #13692, Add guardian approval MVP:https://github.com/openai/codex/pull/13692
  • Codex CLI v0.160.0 release notes(2026-10-01):https://github.com/openai/codex/releases/tag/v0.160.0