专题篇章 · 拆开 OpenAI Codex

审批策略:同一条命令,问不问看哪两颗旋钮

默认问不问跟沙箱种类绑在一起。问过一次之后,记住的是完整命令,还是一段前缀。

本页解决的问题

先给结论

「审批策略:同一条命令,问不问看哪两颗旋钮」要解决的关键问题是什么?

默认问不问跟沙箱种类绑在一起。问过一次之后,记住的是完整命令,还是一段前缀。

判断标准

跟着交接处走,不要只看 Demo。 系统是否可靠,往往取决于模型、工具、状态、权限和人的交接处。把每次交接都当成可以观察、测试和恢复的地方。

下一步

为一个自动化步骤写清输入、负责人、审批和恢复动作。

常见误区

一次运行成功了,却说不清发生了什么,也无法安全重放。

课程目标读完能说清两件事。同一条命令为什么会从直接放行变成必须有人点头。以及你点过一次 Yes 之后,下次还问不问,系统到底记住了什么。
先玩一遍 · 同一条命令,换策略看结局
四种策略,三种沙箱,看哪一格盖放行、问人、拒绝
命令
前三条走 Allow。第四条命中 execpolicy 的 Prompt。
策略
沙箱
旋钮
点格子也能跳到那一格。两套记住互斥。
十二格沙盘 · 只读和工作区常常盖同一张章Restricted 两行会撞车
CodexOnRequest · workspace-write
等待点播放,看同一条命令换策略之后盖哪张章。
给模型的说明书策略还没选定。
DSHask · workspace-write
等待两颗旋钮独立。全盘可写仍可继续提问。
记住什么只有 allowed-once。问过一次,下一次还问。
逻辑轨迹 · 动画每一步对应源码里的哪一段
  1. 读当前 turn 的 AskForApprovalprotocol.rs L924
  2. 看 FileSystemSandboxKind 是不是 Restrictedpermissions.rs L227
  3. Never 给 Skip,UnlessTrusted 给 NeedsApprovalsandboxing.rs L198
  4. OnRequest 或 Granular 只在 Restricted 时要问sandboxing.rs L200
  5. Granular 要问且关掉沙箱审批则 Forbiddensandboxing.rs L209
  6. execpolicy 的 Prompt 再过第二道闸exec_policy.rs L214
  7. 会话缓存只收 ApprovedForSession,认精确 keysandboxing.rs L108
  8. 策略改了,给模型的说明书一起改permissions_instructions.rs L271
点播放,看同一条命令从直接放行一路变到必须有人点头。
十二格里有几格一样read-only 和 workspace-write 都是 Restricted。OnRequest 在这两行盖同一张问人章。danger-full-access 把 kind 拧成 Unrestricted,默认函数不再问。
Never 也会拒绝策略要求提问时,Never 把提问升级成拒绝。关掉 sandbox_approval,只挡住本来要弹的窗。文件系统已经 Unrestricted,Forbidden 分支进不去。
两套记住按会话记住 npm run test,再跑 npm run lint,key 对不上还要问。按前缀记住才会把范围扩出去。常规弹窗默认露出的,是前缀那一条。
教学示意:舞台只演示判定函数和两套缓存的结构差异,不执行真实命令。逻辑轨迹右侧行号对应 openai/codex 仓库 commit 4f39251a01。
思路一 · 默认问不问,跟沙箱种类绑在一起
它解决什么问题

你把审批留在 on-request,沙箱从 workspace-write 拧到 danger-full-access。十分钟前那条出沙箱命令还会弹窗。现在不弹了。你没改审批旋钮。

审批策略 AskForApproval 是当前 turn 用哪套问人规则,类型里有四个变体。文件系统沙箱种类是三个,默认 Restricted,意思是只读或只能写工作区。这两颗旋钮在同一个判定函数里。改其中一颗,另一颗的行为会跟着走。出处:codex-rs/protocol/src/protocol.rs 第 924 至 947 行,以及 codex-rs/protocol/src/permissions.rs 第 227 至 232 行

思路是什么

一条命令先读审批策略,再看文件系统是不是 Restricted,再让 execpolicy 把 Allow、Prompt、Forbidden 叠上去。execpolicy 是按命令文本给出三态的规则文件。

默认问不问写在 default_exec_approval_requirement。Never 这一层给 Skip。UnlessTrusted 这一层给 NeedsApproval。OnRequest 和 Granular 只在 Restricted 时要问。read-onlyworkspace-write 都是 Restricted,所以这两格的默认结局一样。danger-full-access 把 kind 变成 Unrestricted,默认函数走 Skip。出处:codex-rs/core/src/tools/sandboxing.rs 第 198 至 230 行

Granular 还多一个闸。需要审批、且 sandbox_approval 关掉时,直接 Forbidden。文件系统如果已经是 Unrestricted,needs_approval 先变成假,Forbidden 分支进不去。关掉沙箱审批,只挡住本来就要弹的窗。

Never 遇到 execpolicy 的 Prompt,提问会升级成拒绝。它并不表示什么都准跑。出处:codex-rs/core/src/exec_policy.rs 第 214 至 236 行

命令到达 AskForApproval 文件系统 kind 是不是 Restricted 默认要求 Skip / 问人 / 拒绝 Allow 则开跑 Prompt 再过一闸 OnRequest 加 Unrestricted,默认 Skip。Never 加 Prompt,提问升级成拒绝。
教学化结构图:先出默认要求,再让 execpolicy 叠一层。

untrusted 写不进配置。类型还在,公开字符串已经退休。用户显式写出,整次加载失败。没写才看项目信任:已信任走 OnRequest,明确未信任走 UnlessTrusted。出处:codex-rs/core/src/config/mod.rs 第 3607 至 3625 行

还有一个加载期硬拒绝。requirements 不允许 danger-full-access,配置却写了 approval_policy = "never",加载器会先把权限档案回落到只读。只读加上从不提问,等于模型在窄沙箱里还没人可问。这种组合直接判非法。出处:codex-rs/core/src/config/mod.rs 第 3969 至 3979 行

为什么长期成立

全盘可写时,再问一次出沙箱没有意义。两颗旋钮绑在一起,少弹窗。代价是改沙箱会静默带走审批行为。换个语言重写,仍要先回答:全权模式还要不要问人。

策略枚举靠穷尽分支表达规则。新加一个变体,编译器会逼所有判定函数表态。这是类型在替运行时守门。

思路二 · 问过之后,记住什么
它解决什么问题

弹窗上两条记住长得很像。一条是本会话记住这条命令。一条是把前缀写进 execpolicy,跨会话生效。点错了,后面的边界题就会答反。

常规 exec 弹窗默认菜单里,甚至没有 ApprovedForSession。有网络上下文时才带上它。普通命令给一次批准,有前缀修正提案时再加按前缀记住,最后是取消。用户最常碰到的记住,是前缀那一条。出处:codex-rs/protocol/src/approvals.rs 第 314 至 347 行

思路是什么

会话缓存活在 ApprovalStore 里,跟会话同寿命。key 是规范化后的完整命令,外加 cwd、环境和 execpolicy 指纹。所有 key 都已经是 ApprovedForSession 才命中。Approved 一次放行不会进 map。出处:codex-rs/core/src/tools/sandboxing.rs 第 64 至 116 行

npm run test 批准进会话,npm run lint 是另一把 key。/bin/bash -lcbash -lc 在能拆出单一明文命令时,缓存成同一组 token。会话缓存认完整命令,不认 npm *。前缀扩张只走 execpolicy。

改审批策略不会清空这座 map。key 里没有 AskForApproval。中途从 OnRequest 改成 UnlessTrusted,已经缓存的批准仍算数。改 execpolicy 会改指纹,缓存才会失效。

用户点决定 ReviewDecision ApprovedForSession 精确 key 入会话抽屉 ApprovedExecpolicyAmendment 前缀写入规则文件 下次完整命令相同 才跳过弹窗 前缀匹配就放行 跨会话,范围更大 Approved 只放行这一次,不进 map。npm run test 和 npm run lint 是两把 key。 常规 exec 默认菜单常常只露出前缀这一条。
教学化对照:一层认完整命令,一层认前缀并落盘。
为什么长期成立

两套记住对应两种威胁。精确 key 挡不住换参数。前缀挡得住换参数,也容易把包装命令的范围扩太大。两层分开,才能各自配禁建议名单。一天弹窗不多的时候,先只做一次放行也成立。

思路三 · 策略改了,说明书一起改
它解决什么问题

策略改了,只改运行时分支不够。模型看到的说明必须同步改,否则它会按旧规则去要 require_escalated。Never 下面如果说明书还在教它提权,运行时会把提问升级成拒绝,模型只会反复撞墙。

思路是什么

权限说明是一段 developer 消息。先选沙箱模板,再选审批模板。Never、UnlessTrusted、OnRequest 各有现成 markdown。Never 那份只有一句:不要再给 sandbox_permissions,命令会被拒。Granular 没有第五份文件,按五个开关现场拼允许列表和拒绝列表。两套说明拼在同一段里,模型一次看到当前组合。出处:codex-rs/prompts/src/permissions_instructions.rs 第 271 至 291 行

钩子在人前面。钩子给出 Allow 或 Deny,弹窗就不会出现。钩子的 Allow 是一次 Approved,不写会话缓存。

策略改了,说明书必须一起改。
为什么长期成立

运行时和模型说明书是同一份合同的两面。判定函数改了,字典那一行必须一起改。把这两份放在同一个模块,用同一组测试喂两边,换语言也用得上。

横向对比 · 旋钮独立还是绑在一起

DSH:两颗旋钮,一次授权不扩大

DSH 的审批策略只有 asknevernever 在分派给回答者之前就返回 rejected,后挂的监听器改不了这个承诺。授权结果只有 allowed-once。没有本会话缓存,没有前缀修正。问过一次,下一次还问。出处:packages/interaction/user-approval/src/index.ts 第 84 至 94 行,以及第 304 至 312 行

沙箱和审批是两颗独立旋钮。用户看见的下拉框是预设表:workspace-writeaskdanger-full-accessnever。点下一档时分别调用两颗 setter。对不上表就显示 custom。所以 DSH 可以单独把审批留在 ask、把沙箱拧到全盘可写。Codex 的 OnRequest 在 Unrestricted 上默认 Skip,这个组合在默认函数里不可独立存在。出处:packages/interaction/permission-presets/src/index.ts 第 167 至 176 行

两侧均已核对源码 · 2026-08-22 · DSH · 审批与权限

Claude Code:记住写进规则表

Claude Code 对外的权限模式是五档,外加内部的 autobubble。规则来源包括 userSettingsprojectSettingssessioncliArg。判定先查整工具级 deny,再往下走。出处:restored-src/src/types/permissions.ts 第 16 至 29 行,以及 restored-src/src/utils/permissions/permissions.ts 第 1169 至 1181 行

alwaysAllowRules 可以按来源记下允许项,session 是其中一档。下次按规则匹配,不必完整 argv 相等。代价是匹配函数必须自己防包装。Codex 把扩大范围交给 execpolicy 前缀和禁建议名单。dontAsk 接近 Never。Codex 没有公开的全放行审批策略,Never 仍会被 execpolicy 拦住。出处:restored-src/src/types/permissions.ts 第 54 至 62 行,以及第 433 行

两侧均已核对源码 · 2026-08-22
课堂练习
01

拧沙箱,弹窗还在吗

审批留在 on-request,沙箱从 workspace-write 拧到 danger-full-access。再跑一条会写工作区外路径的命令。弹窗还在不在?为什么?

接着把同一条 npm run test 按会话批准,再提交 npm run lint。缓存该不该命中?如果点的是按前缀记住,答案会不会变?

Takeaway:同一条命令问不问,看审批策略和文件系统是不是 Restricted。Never 遇到必须提问的规则,提问会升级成拒绝。问过之后的记忆分两层:会话层认精确 key,持久层才允许前缀。策略改了,给模型的那句话必须一起改。

「先玩一遍 · 同一条命令,换策略看结局」的能力藏在每次交接里

「你把审批留在 on-request ,沙箱从 workspace-write 拧到 danger-full-access 。十分钟前那条出沙箱命令还会弹窗。现在不弹了。你没改审批旋钮」说明,Agent 的表现不只由模型决定。模型、上下文、工具、状态、权限和人之间的每次交接,都会改变任务能否继续以及出了问题能否恢复。

先写清状态,再增加能力

从「审批策略 AskForApproval 是当前 turn 用哪套问人规则,类型里有四个变体。文件系统沙箱种类是三个,默认 Restricted ,意思是只读或只能写工作区。这两颗旋钮在同一个判定函数里。改其中一颗,另一颗的行为会跟着走。」出发,可以把流程拆成起始状态、下一步动作、工具返回、状态更新和停止条件。这样调试时找的是第一处丢失信息或权限的位置,而不是笼统地说“模型变笨了”。

  • 读当前 turn 的 AskForApproval protocol.rs L924
  • 看 FileSystemSandboxKind 是不是 Restricted permissions.rs L227
  • Never 给 Skip,UnlessTrusted 给 NeedsApproval sandboxing.rs L198

成功路径不能代表系统可靠

用「接着把同一条 npm run test 按会话批准,再提交 npm run lint 。缓存该不该命中?如果点的是按前缀记住,答案会不会变」重放一次成功和一次失败,记录每一轮真正传入的上下文、工具结果和负责人;只要第二个人能复述这条链,系统才有可维护性。

从「先玩一遍 · 同一条命令,换策略看结局」走到「思路一 · 默认问不问,跟沙箱种类绑在一起」

「先玩一遍 · 同一条命令,换策略看结局」先把问题落在「四种策略,三种沙箱,看哪一格盖放行、问人、拒绝 播放 单步 重置 命令 git status npm run test npm run lint prompt 规则 前三条走 Allow。第四条命中 execpolicy 的 Prompt。 策略 OnRequest UnlessTrusted Granular Never 沙箱 read-only workspace-write danger-full-access…」上;到了「思路一 · 默认问不问,跟沙箱种类绑在一起」,讨论继续推进到「你把审批留在 on-request ,沙箱从 workspace-write 拧到 danger-full-access 。十分钟前那条出沙箱命令还会弹窗。现在不弹了。你没改审批旋钮」。两段连起来,重点就不只是记住一个结论,而是看清它成立所依赖的条件。

把这条判断带到下一个场景

分析 Agent 时,沿着状态、动作、工具结果和下一步的顺序走一遍;每次交接都要能说明信息从哪里来、由谁确认、失败时停在哪里。

  • 「先玩一遍 · 同一条命令,换策略看结局」:四种策略,三种沙箱,看哪一格盖放行、问人、拒绝 播放 单步 重置 命令 git status npm run test npm run lint prompt 规则 前三条走 Allow。第四条命中 execpolicy 的 Prompt。 策略 OnRequest UnlessTrusted Granular Never 沙箱 read-only workspace-write danger-full-access…
  • 「思路一 · 默认问不问,跟沙箱种类绑在一起」:你把审批留在 on-request ,沙箱从 workspace-write 拧到 danger-full-access 。十分钟前那条出沙箱命令还会弹窗。现在不弹了。你没改审批旋钮
  • 「最后的要点」:Granular 要问且关掉沙箱审批则 Forbidden sandboxing.rs L209

最后的「最后的要点」把讨论落到「Granular 要问且关掉沙箱审批则 Forbidden sandboxing.rs L209」。回看这条线索时,最值得保留的是:当输入、规模或风险改变,哪些判断需要重新做一遍。

标记为已学完 阅读进度会自动记录
← 上一篇下一篇 →

继续阅读

同一条线上的下一篇。

文章讨论

读到这里,留下一个判断。

把刚想明白的地方、还没想通的问题,留给下一位一起学习的人。

正在讨论 审批策略:同一条命令,问不问看哪两颗旋钮 拆开 OpenAI Codex
3条讨论文章讨论 · 与共学社区同步
在共学社区查看
AM
Asha Morgan内容编辑
观点实践记录

我把这篇文章里的一个判断改写成了今天可以验证的小实验。比记住结论更有用的是,知道下一步要观察什么。

文章讨论7 有帮助
LH
Lin Harper独立开发者
观点观点

读完以后我先回头找它成立的条件,而不是直接把方法搬进项目。这个顺序让后面的取舍清楚很多。

文章讨论5 有帮助
KM
Kiki Moore产品运营
问题问题

如果把这个判断放到真实工作里,最先需要补的约束是什么?我想知道从阅读到第一次实践之间,哪一步最值得先做。

文章讨论4 有帮助