The three approval policies — untrusted, on-request, never
You’ve got the wall set to workspace-write for the money refactor. Now the other dial: the approval policy, the -a axis, which decides which of the actions the sandbox permits still stop to ask you first. Remember the framing from two lessons back — the sandbox is the wall, approval is the checkpoint inside it. Same three-step shape as the sandbox, tightest to loosest.
untrusted — pause for anything not known-safe
Section titled “untrusted — pause for anything not known-safe”codex -a untrustedThe agent runs the moves it’s confident are safe — reads, and a small set of obviously-harmless commands — without bothering you, and stops to ask for everything else. Any file edit, any command that isn’t on the known-safe list, any state change: y/n.
This is the checkpoint for code you don’t trust yet, or work where a wrong move is expensive. It’s deliberately close to babysitting — and that’s the point. On the first day with budgetcli, before you’d read much of it, untrusted was the right call: see every edit before it lands, approve each command consciously. The friction is the feature when you don’t yet know what the agent is about to do to unfamiliar code holding real data.
on-request — let the agent ask only when it matters
Section titled “on-request — let the agent ask only when it matters”codex -a on-requestHere the agent uses its own judgment about when to interrupt you. Routine, in-sandbox work — editing project files, running your tests — flows without prompts; the riskier moves stop and ask. You’re trusting it to recognise which actions deserve a checkpoint, rather than checkpointing everything (untrusted) or nothing (never).
This is the daily driver, and it’s the right answer for the money refactor. Paired with workspace-write, you get exactly the session you wanted at the start of the chapter: the agent rewrites floats to cents across the files and runs the suite uninterrupted, but if it reaches for something genuinely consequential it pauses for your sign-off — and the sandbox guarantees that even the moves it doesn’t stop for can’t escape the project or touch the network. Most of your week on budgetcli lives in this cell.
never — run end to end, no interruptions
Section titled “never — run end to end, no interruptions”codex -a neverThe agent never pauses for approval. It runs the whole task start to finish, and you review the result afterward rather than the steps along the way.
This sounds reckless, and on a one-dial tool it would be — but here’s where the orthogonality earns its keep. never only removes the checkpoint. It does nothing to the wall. So -a never -s read-only is a completely safe combination: the agent runs autonomously and never bothers you, yet cannot change a single thing, because the sandbox won’t let it. That pairing is perfect for “go audit the whole repo for float-money bugs and write me a report” — full autonomy, zero risk, because the reach is nil.
Where never does get dangerous is when you pair it with a loose sandbox. -a never -s danger-full-access is the genuinely hazardous corner of the grid — no checkpoint and no wall — and it has its own dedicated flag that we’ll meet, and warn you off, in the last lesson. The lesson to carry forward: never is only as risky as the sandbox you pair it with. Choose them together.
Set it persistently, not just per launch
Section titled “Set it persistently, not just per launch”Typing -a every invocation gets old. The persistent equivalent is approval_policy in config.toml, which takes the same three values (plus a granular form for finer control — see the config reference):
# ~/.codex/config.toml or .codex/config.tomlapproval_policy = "on-request"sandbox_mode = "workspace-write"That config.toml pairing is the same two dials, written down once instead of typed every time. You’ll see in the last lesson how to give a named pairing — a profile you can summon with one flag.
But before profiles, there’s a wall the agent is about to hit that has nothing to do with approvals and everything to do with the sandbox. The refactor’s fine — but the next ticket needs a live exchange rate, and the agent is about to discover it can’t get one. Network is off by default, and that’s the teachable moment.