docs: explain Codex app approval precedence (#155089)

* docs: explain Codex app approval precedence

* docs: describe pending Codex approval fixes
This commit is contained in:
stevenlee-oai 2026-09-24 15:55:34 -07:00 • committed by GitHub
parent 58c4dfe03d
commit 1d1691663c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 184 additions and 21 deletions

View file

@ -10,6 +10,11 @@ sidebarTitle: "Approval and sandbox"
The approval and sandbox posture of a Codex turn, and where native execution runs. Part of the [Codex harness reference](/plugins/codex-harness-reference); [Where each section moved](/plugins/codex-harness-reference#where-each-section-moved) lists every section.
For native plugin/app tools, also follow the
[app approval decision order](/plugins/codex-native-plugins#approval-decision-order).
App admission, tool enablement, per-tool approval modes, and OpenClaw's
elicitation response are separate from the general presets below.
## Approval and sandbox modes
Local stdio app-server sessions default to YOLO mode:

View file

@ -32,6 +32,11 @@ Plugin, account, Computer Use, and MCP approval classification runs before
ordinary input handling. A denied policy or unmappable approval schema returns
an explicit decline and never becomes a general-purpose form.
For native app tools, see the
[approval decision order](/plugins/codex-native-plugins#approval-decision-order)
for OpenClaw defaults, native per-tool overrides, remembered approvals, and
how eligible hosted app tools reach consent while disabled tools remain blocked.
OpenClaw supports app-server MCP elicitation modes `form`, `openai/form`, and
`url`. Standard and extended forms can contain at most 12 fields. OpenClaw
normalizes field names to Gateway-safe question IDs, retains the original names

View file

@ -6,6 +6,7 @@ read_when:
- You are migrating source-installed openai-curated Codex plugins
- You are discovering or installing a Codex marketplace plugin
- You are troubleshooting codexPlugins, app inventory, destructive actions, or plugin app diagnostics
- You need the precedence of OpenClaw policy, native app defaults, and per-tool overrides
---
Native Codex plugin support lets a Codex-mode OpenClaw agent use Codex
@ -212,6 +213,15 @@ runtime, revoked app, narrower policy, or unavailable inventory stops before
app execution and reports how to restore access or reauthorize the automation.
Model fallbacks cannot move this authority to another runtime or account.
This path is stricter than an ordinary interactive turn. OpenClaw generates
per-tool `enabled` and `approval_mode` values from current tool metadata and
the captured authority. An explicit native `enabled: true` cannot override a
captured or current destructive/open-world restriction on a scheduled run.
Approval intersections keep `"prompt"` if either side requires it;
`"approve"` defers to the other side. Combining `"auto"` with `"writes"`
produces `"prompt"`, because their annotation-dependent rules are not totally
ordered.
Jobs created before app authority capture may keep their ordinary OpenClaw
tool cap and continue non-app work, but cannot recover Codex app access
automatically. Recreate or reauthorize only a job that needs app access, from a
@ -533,20 +543,140 @@ cleanup cannot be confirmed.
`destructive_enabled` on each app comes from the effective global or
per-plugin `allow_destructive_actions` policy; `true`, `"auto"`, and `"ask"`
all set `destructive_enabled: true`, and `false` sets it `false`. Codex still
enforces destructive tool metadata from its native app tool annotations.
evaluates native tool enablement and annotations in the order below.
`_default` is disabled with `open_world_enabled: false`; enabled plugin apps
get `open_world_enabled: true`. OpenClaw does not expose a separate
plugin-level open-world policy knob and does not maintain per-plugin
destructive tool-name deny lists.
Admitted apps retain their native Codex approval mode and reviewer, including
app defaults and saved link or tool overrides. With no native approval setting,
Codex uses its `auto` approval mode, and read-only tools usually run without a prompt.
Use `allow_destructive_actions: "auto"` to route native human approval requests
through OpenClaw; native `prompt` with the `auto_review` reviewer stays within
Codex's automatic review flow. These settings also apply when resuming a thread
or asking a `/btw` side question. Explicit OpenClaw `"ask"` policy overrides saved
native approvals as described below; `false` still disables destructive tools.
## Approval decision order
For an ordinary interactive Codex turn, follow these decisions in order:
1. **Admission:** OpenClaw selects the plugin/app identities allowed on this
thread. Unavailable inventory or unproven ownership does not grant access.
2. **Thread configuration:** OpenClaw overlays its app policy on the target
app-server's native configuration. Codex administrative requirements still
apply.
3. **Tool enablement:** Codex decides whether the particular tool is callable.
A disabled tool cannot be made callable by approving a prompt.
4. **Approval mode and reviewer:** Codex decides whether the call needs review
and whether to use its automatic reviewer or send a user approval request.
5. **OpenClaw response:** When a plugin approval request reaches OpenClaw, its
elicitation bridge applies the effective `allow_destructive_actions` value.
These are separate decisions. `enabled: true` does not mean automatic approval,
and `approval_mode: "approve"` does not enable a disabled tool. OpenClaw dynamic
tools, ordinary MCP forms, and native shell permissions have their own flows;
see [Native permissions and MCP elicitations](/plugins/codex-harness-runtime/permissions).
### Which configuration owns each setting
| Setting | Owner and purpose |
| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `plugins.entries.codex.config.codexPlugins` | OpenClaw's admission and plugin elicitation policy. |
| `codexPlugins.allow_destructive_actions` | Shared OpenClaw default for configured plugins and admitted account apps. |
| `codexPlugins.plugins.<key>.allow_destructive_actions` | Explicit override for that configured plugin. |
| Native `apps._default`, `apps.<appId>`, and `apps.<appId>.tools` | Codex app defaults and per-tool settings, after configuration layers and the OpenClaw thread patch are combined. |
| `plugins.entries.codex.config.appServer.approvalPolicy` and `approvalsReviewer` | General Codex approval posture and reviewer, distinct from app/tool policy. See [Approval and sandbox modes](/plugins/codex-harness-reference/approval-and-sandbox). |
OpenClaw resolves the destructive-action setting as:
```text
per-plugin value ?? codexPlugins shared value ?? true
```
Omitting a per-plugin value inherits the shared value. Explicit `false`,
`true`, `"auto"`, and `"ask"` all override it. In particular, a generated
per-plugin `"auto"` overrides a shared `false`; `"auto"` is a policy value,
not an instruction to inherit.
The shared default lives in the same OpenClaw configuration as the plugin
entries. It requires no separate host-wide configuration file. Native Codex
settings belong to the app-server that runs the tools: the default managed
local server uses an agent-scoped Codex home; a remote server uses its own
configuration. Starting Codex from OpenClaw or a deployment manager
does not remove this native configuration layer. OpenClaw's thread patches
do not rewrite saved native settings.
### Native tool enablement
After OpenClaw's admission patch, Codex evaluates an app tool in this order:
1. A disabled app blocks all its tools, including explicitly enabled tools.
Managed app disablement remains authoritative.
2. An explicit `apps.<appId>.tools.<tool>.enabled` wins for that tool.
3. Otherwise, an explicit `apps.<appId>.default_tools_enabled` wins.
4. Otherwise, Codex checks `destructive_enabled` and `open_world_enabled`
against the tool's annotations. Each category setting falls back from the
app to `apps._default`, then to `true`. Missing annotations are treated as
destructive/open-world for this eligibility check.
For tool configuration, an exact tool-name entry wins over a tool-title entry.
Codex selects the whole entry first; it does not fill missing fields from the
title entry. Omit `enabled` to inherit; TOML has no `null` value.
For example, on an admitted app with `destructive_enabled: false`, an omitted
tool `enabled` leaves destructive tools blocked. Explicit `enabled: true`
allows that particular tool through this native eligibility check, while
`enabled: false` blocks it even if the app allows destructive tools. The call
still has to pass approval and execution checks. This is an exception to an
app default, not a way to enable an unadmitted app or widen scheduled authority.
### Native approval mode
For an enabled tool, Codex selects the first applicable approval mode:
1. Managed per-tool approval requirement.
2. The selected native tool entry's `approval_mode`.
3. The selected connected account's
`apps.<appId>.links.<linkId>.default_tools_approval_mode`.
4. `apps.<appId>.default_tools_approval_mode`.
5. `apps._default.default_tools_approval_mode`.
6. `"auto"`.
The account link is the connected account used for this call, not the
OpenClaw conversation. The following modes decide whether review is needed;
they do not themselves promise an OpenClaw prompt:
| Native mode | Approval requirement |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"approve"` | No tool approval request. Other access and execution restrictions still apply. |
| `"prompt"` | Requires approval, including for read-only tools. |
| `"writes"` | Requires approval unless the tool explicitly declares itself read-only. |
| `"auto"` | Uses annotations: explicitly destructive tools require approval; otherwise explicitly read-only tools do not. Remaining tools require approval when destructive/open-world hints are true or missing. |
Reviewer selection is separate: the connected account's reviewer overrides
the app reviewer, then `apps._default.approvals_reviewer`, then the thread
reviewer. Codex only accepts a configured reviewer allowed by administrative
requirements; otherwise it uses the thread reviewer. A model-specific
requirement for automatic review takes precedence. Strict automatic review
can also require review when a tool's mode would otherwise skip it.
Unless OpenClaw policy is explicitly `"ask"`, admitted apps retain their
native approval mode and reviewer, including app defaults and saved account-link
or tool overrides. This also applies when resuming a thread or asking a `/btw`
side question. With no native approval setting, Codex falls back to `"auto"`.
Use OpenClaw `allow_destructive_actions: "auto"` to route native human approval
requests through OpenClaw consent. Native `"prompt"` with the `"auto_review"`
reviewer stays in Codex's automatic review flow. OpenClaw `true` preserves the
native mode too, but auto-accepts supported approval requests that reach the
bridge, as described below.
OpenClaw `"ask"` also overlays saved approval fields for current non-read-only
tool names/aliases and connected accounts, selecting native `"auto"` and a
human app/account reviewer. It preserves tool enablement. If tool summaries
are unavailable, it targets all saved tool approval entries. Thus `"ask"`
requires one-shot consent for the actions Codex sends for approval; it does
not mean native `"prompt"` for every read. Other apps retain their reviewer.
On ordinary native-plugin turns and `/btw` side questions with bound apps,
OpenClaw enables MCP elicitation delegation even when the general
`appServer.approvalPolicy` is `"never"`; this does not enable unrelated shell
approval categories. The app mode, reviewer, and bridge response still
determine the outcome. General approval policy is not a replacement for the
per-app/tool settings above.
## Destructive action policy
@ -556,25 +686,23 @@ plugins, while unsafe schemas and ambiguous ownership fail closed:
- Global `allow_destructive_actions` defaults to `true`.
- Per-plugin `allow_destructive_actions` overrides the global policy for
that plugin.
- `false`: OpenClaw excludes destructive hosted app tools before execution.
Native approval requests for permitted tools still go through OpenClaw consent,
including during a `/btw` side question. Plugin-provided MCP server approval
requests receive a deterministic decline.
- `false`: OpenClaw sets native `destructive_enabled: false`; tool eligibility
follows the native defaults and explicit exceptions described above. Approval
requests for eligible hosted app tools still go through OpenClaw consent,
including permitted reads and `/btw` side questions. The bridge does not
classify tools again or blanket-decline their requests. Plugin-provided MCP
server approval requests still receive a deterministic decline.
- `true`: OpenClaw auto-accepts only safe schemas it can map to an approval
response, such as a boolean approve field.
- `"auto"`: OpenClaw exposes destructive plugin actions to Codex, then
turns ownership-proven MCP approval elicitations into OpenClaw plugin
approvals before returning the Codex approval response.
- `"ask"`: OpenClaw uses the same Codex write/destructive gating as
`"auto"`, overrides saved per-tool and per-account approvals in the native
thread's configuration, and offers only one-shot approval or denial. Saved
native settings stay unchanged, and user-config reloads preserve the thread's
approval policy. These checks also run before reusing a thread or answering a
`"auto"`, applies the tool/account approval overlays described above, and
offers only one-shot approval or denial. Saved native settings stay unchanged,
and user-config reloads preserve the thread's approval policy. These checks
also run before reusing a thread or answering a
`/btw` side question. Changed override keys rebuild the thread with current policy.
For each admitted app using `"ask"`, OpenClaw selects Codex's human approvals
reviewer for that app so Codex sends its approval elicitations to
OpenClaw; other apps and non-app thread approvals keep their configured
reviewer and policy.
- Missing plugin identity, ambiguous ownership, a missing or mismatched
turn id, or an unsafe elicitation schema declines instead of prompting.
@ -587,6 +715,31 @@ configuration and prevent app admission; move those app settings to a supported
user or project configuration layer. Native administrative requirements remain
authoritative.
### Approval examples
Assume an admitted, authenticated app, no conflicting managed requirement,
and a human reviewer for calls that need approval. The read tools below declare
`readOnlyHint: true` and `destructiveHint: false`:
| Configuration | Observable result on an ordinary turn |
| --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| OpenClaw shared `false`, per-plugin `"auto"` | The plugin override wins. Destructive tools are eligible; approval elicitations that reach OpenClaw request consent. |
| OpenClaw `"auto"`, native app default `"prompt"`, no tool/link override, non-destructive read | Native `"prompt"` survives. The read requests consent; Allow once permits the call and Deny blocks it. |
| OpenClaw `"auto"`, native read-tool `approval_mode: "prompt"` | The per-tool mode survives. The read requests consent; Allow once permits the call and Deny blocks it. |
| OpenClaw `false`, native app default `"prompt"`, no tool/link override, non-destructive read | Native eligibility allows the read, and OpenClaw requests consent. Allow once permits the call and Deny blocks it. |
| OpenClaw `false`, destructive tool explicitly `enabled: true` and `approval_mode: "approve"` | The native tool exception bypasses the category default and requires no tool approval request. The bridge's decline path is not an execution-time category ceiling. |
| OpenClaw `"ask"`, saved non-read-only tool approval `"approve"` | The thread overlay replaces that saved approval with native `"auto"`; calls needing approval use one-shot consent. |
If the reviewer in the native `"prompt"` examples is `"auto_review"` instead
of `"user"`, Codex performs automatic review rather than displaying an
OpenClaw consent prompt. Neither reviewer choice enables a tool that failed
the eligibility check.
Remembered approval and explicit enablement are different settings. Codex's
persistent app-tool approval writes `approval_mode: "approve"`, not
`enabled: true`; Allow once does not persist either setting. Recheck both when
explaining why a tool ran or why no prompt appeared.
## Troubleshooting
| Code | Meaning | Fix |