Codex Harness Plugin Configuration Reference

Complete reference for configuring the Codex harness plugin, covering discovery, app-server, auth, and approval options. Essential for developers integrating Codex.

Read this when

  • You need every Codex harness config field
  • You are changing app-server transport, auth, discovery, or timeout behavior
  • You are debugging Codex harness startup, model discovery, or environment isolation

This reference details the full configuration options for the official codex plugin. For guidance on setup and routing choices, consult the Codex harness first.

Plugin config surface

Every Codex harness option is configured beneath plugins.entries.codex.config.

{
  plugins: {
    entries: {
      codex: {
        enabled: true,
        config: {
          discovery: {
            enabled: true,
            timeoutMs: 2500,
          },
          appServer: {
            mode: "guardian",
          },
        },
      },
    },
  },
}

Fields at the top level:

FieldDefaultMeaning
discoveryenabledControls how models are discovered for the Codex app-server model/list.
appServermanaged stdio app-serverTransport, command, auth, approval, sandbox, and timeout configuration. The standard harness defaults to agent-scoped state.
codexDynamicToolsLoading"searchable"Use "direct" to inject OpenClaw dynamic tools directly into the initial Codex tool context.
codexDynamicToolsExclude[]Extra OpenClaw dynamic tool names to exclude from Codex app-server turns.
codexPluginsdisabledNative Codex plugin and app support, including opt-in access to connected account apps. See Native Codex plugins.
computerUsedisabledCodex Computer Use configuration. See Codex Computer Use.
sessionCatalogenabledNative Codex session discovery for the sidebar. Set enabled: false to turn it off, or set homes to add further local Codex stores.
supervisiondisabledAgent-facing policy for native-session transcripts and write controls. See Codex supervision.

Supervision

By default, native session discovery lists non-archived Codex sessions from the Gateway machine and any paired nodes that opted in. To disable only that catalog, use:

{
  plugins: {
    entries: {
      codex: {
        enabled: true,
        config: {
          sessionCatalog: {
            enabled: false,
          },
        },
      },
    },
  },
}

Discovery automatically covers the Gateway process Codex home (CODEX_HOME or ~/.codex) plus the Codex home of every configured OpenClaw agent. Register additional local Codex stores only when sessions reside in a home OpenClaw does not already recognize, for instance a store created with a custom CODEX_HOME outside OpenClaw:

{
  plugins: {
    entries: {
      codex: {
        enabled: true,
        config: {
          sessionCatalog: {
            homes: [
              "/path/to/additional-codex-home",
              { path: "/path/to/review-codex-home", label: "Review sessions" },
            ],
          },
        },
      },
    },
  },
}

Configured stores appear in the sidebar next to automatically discovered ones, labeled Local Codex · <label> and grouped by each session's working directory. String entries and objects lacking label take the basename of the canonicalized home directory; an explicit label overrides that default. Sessions in these stores support the same view, continue, and archive actions, and the selected OpenClaw agent still owns the resulting connection; homes only adds catalog sources.

Only existing directories are included. Equivalent paths are canonicalized and deduplicated against the automatic homes, and automatic homes keep priority under the 100-source catalog cap. Changes require a Gateway restart. sessionCatalog.homes needs the default managed stdio app-server transport; Unix and WebSocket transports reject it with a visible error because they cannot start a source-bound app-server for each home.

supervision separately controls agent-facing tools:

FieldDefaultMeaning
enabledfalseEnable agent-facing Codex supervision tools. This does not control the authenticated operator session catalog.
endpointsbuilt-in local endpointCompatibility and advanced endpoint targets for the retained Codex supervision agent and standalone MCP tools. The human catalog and branch flow ignore these targets and use the supervision App Server resolved from appServer.
allowRawTranscriptsfalseWith supervision enabled, allow autonomous agent or standalone MCP transcript reads and transcript-derived list fields. codex_threads metadata-only reads remain available. Does not control authenticated Control UI continuation.
allowWriteControlsfalseWith supervision enabled, allow autonomous codex_threads fork, rename, archive, and unarchive mutations plus standalone MCP send, steer, and interrupt operations. Does not bypass other binding, host, status, or confirmation checks.

Endpoint entries accept these fields:

FieldApplies toMeaning
idallStable endpoint id.
labelallOptional display label.
transportall"stdio-proxy" or "websocket".
commandstdio-proxyOptional App Server command.
argsstdio-proxyOptional command arguments.
cwdstdio-proxyOptional child-process working directory.
urlwebsocketRequired WebSocket or supported local socket URL.
authTokenEnvwebsocketOptional environment variable whose value authenticates the endpoint.

The Codex Sessions page relies on the plugin's supervision App Server and displays only sessions that are not archived. When no explicit appServer connection settings are provided, that connection operates as managed user-home stdio. Local rows that are stored or idle can produce a model-locked Chat with limited user and assistant history, extending through the last terminal persisted source turn. Its private binding preserves the snapshot fork, canonical appServer-source branch, history injection, and subsequent turns on that connection. The initial canonical start uses the pair returned by the fork. Later resumes skip OpenClaw model and provider overrides, allowing Codex to restore the persisted pair from the canonical thread; a separate native change can update that pair, but the outer model and fallback chain never override it. Stored and idle rows can be archived after confirming no other runner exists, unless another active OpenClaw binding owns the exact target or one of its non-archived spawned descendants. OpenClaw follows Codex's descendant pagination and fails closed on enumeration errors, cycles, or safety-limit exhaustion. Confirmation still covers unknown native clients and the status-to-archive race. A supervised model-locked Chat cannot be deleted while it protects the native binding. Active sources cannot create a branch or be archived, but an existing supervised Chat can still be opened. Every paired-node row remains read-only; the node transport does not yet offer the streaming lifecycle the harness requires.

appServer.homeScope: "user" alone determines which Codex home a managed harness process uses; it does not publish the fleet catalog. Enabling supervision does not alter the harness default. Instead, the separate supervision connection defaults to managed user-home stdio when no explicit appServer connection settings exist. Explicit settings are honored for that connection. Pending and committed supervised bindings retain that connection for every turn; disabled supervision or connection/lifecycle drift fails closed rather than falling back to the agent-home harness. The default connection shares stored sessions with native Codex clients, not their process-local activity state.

Legacy plugins.entries.codex-supervisor settings are retired. Run openclaw doctor --fix to migrate the old entry, endpoint definitions, policy flags, and plugin allow/deny references into this block. Explicit canonical codex.config.supervision values win conflicts.

App-server transport

For ordinary harness turns, OpenClaw starts the managed Codex binary shipped with the official plugin (currently @openai/codex 0.148.0):

codex app-server --listen stdio://

This ties the app-server version to the official codex plugin rather than whatever separate Codex CLI happens to be installed locally. Set appServer.command only when you intentionally want a different executable. Ordinary managed turns with the default isolated agent home prefer this pinned package even when a macOS desktop bundle is installed. When Computer Use is enabled, or when homeScope is "user" and can load native Computer Use state, managed startup instead prefers the desktop app binary that owns the required macOS permissions. The same desktop-first rule applies when an isolated agent home's effective Codex config enables native Computer Use. If no desktop app bundle is installed, OpenClaw falls back to the pinned package binary.

Before cutting over a staged OpenClaw package, run the opt-in managed-binary check against the candidate installation:

openclaw doctor --lint --only codex/managed-app-server --json

The check is read-only. For every configured Codex agent it applies the same final command selection as a live harness turn, then verifies that a selected package-owned native binary exists and reports the plugin's exact pinned version. A selected Codex Desktop binary, an explicit custom command, and a remote app-server are outside this package check. The command exits nonzero on an error-level finding, so a deployer can reject the candidate before cutover without changing Codex state or app-server settings.

Executable handoff and native-config fencing coordinate clients inside one running Gateway process. Restart the Gateway after another process changes the native Codex plugin config.

Supervision resolves a separate connection. With no explicit appServer connection settings, it uses managed stdio with homeScope: "user"; the ordinary harness remains managed stdio with homeScope: "agent". Explicit connection settings are honored by both paths. Set homeScope: "user" explicitly when the ordinary harness should share $CODEX_HOME (or ~/.codex) with native clients. A private supervised binding uses the supervision connection regardless of the ordinary harness default. Independent App Server processes retain separate live status and approval state.

For non-production testing against an already-running app-server, WebSocket transport is available:

{
  plugins: {
    entries: {
      codex: {
        enabled: true,
        config: {
          appServer: {
            transport: "websocket",
            url: "ws://gateway-host:39175",
            authToken: "${CODEX_APP_SERVER_TOKEN}",
            requestTimeoutMs: 60000,
          },
        },
      },
    },
  },
}

Codex classifies WebSocket transport as experimental and unsupported. Prefer managed stdio or the local Unix control socket for production workloads.

appServer fields:

FieldDefaultMeaning
transport"stdio"Codex is launched by "stdio"; an explicit "unix" attaches to the local control socket; "websocket" links up with url.
homeScope"agent"Per OpenClaw agent, ordinary harness state is kept apart by "agent". Sharing the native $CODEX_HOME or ~/.codex requires the explicit opt-in "user", which also applies native auth and restricts thread management to the owner. Local stdio or Unix transport is what user scope supports. For the distinct supervision connection, leaving the value unset makes it resolve to "user" for stdio or Unix and "agent" for WebSocket.
commandmanaged Codex binaryThe executable used for stdio transport. When left unset, the managed binary is what gets used.
args["app-server", "--listen", "stdio://"]Arguments passed for stdio transport.
urlunsetA WebSocket App Server URL or a unix:// URL. An explicit Unix path that is empty selects the canonical user-home control socket.
authTokenunsetThe bearer token for WebSocket transport. It accepts either a literal string or a SecretInput like ${CODEX_APP_SERVER_TOKEN}.
headers{}Additional WebSocket headers. Literal strings or SecretInput values are accepted for header values, for instance x-codex-client-session-token: "${CODEX_CLIENT_SESSION_TOKEN}".
clearEnv[]Environment variable names that get stripped from the spawned stdio app-server process once OpenClaw assembles its inherited environment.
remoteWorkspaceRootunsetRoot workspace for a remote Codex app-server. OpenClaw maps the local cwd into that root and moves authoritative remote attachments through an output-capped, no-shell command/exec reader. Paths that leave either workspace, symbolic links, files over the size limit, and attachment batches without bounds all fail closed; uploads keep the configured channel identity and the app-server request timeout.
loopDetectionPreToolUseRelaytrueTurns on the Codex PreToolUse relay for loop detection when OpenClaw loop detection is active. No PreToolUse relay gets installed by OpenClaw when there is no local work for a before-tool plugin hook, trusted-tool policy, or enabled loop detector. To switch off the loop-detection relay even with detection enabled, set false; the fail-closed relay required by before-tool plugin hooks and trusted-tool policy is still installed.
requestTimeoutMs60000How long app-server control-plane calls may take before timing out.
turnCompletionIdleTimeoutMs60000Quiet period after Codex accepts a turn or after a turn-scoped app-server request, during which OpenClaw waits for turn/completed.
turnAssistantCompletionIdleTimeoutMs10000Quiet period after a final/non-commentary assistant item or a pre-tool raw assistant completion arms the assistant-output release while OpenClaw continues waiting for turn/completed. Increasing it grants Codex additional time to produce turn/completed before OpenClaw steps in and frees the session lane.
postToolRawAssistantCompletionIdleTimeoutMs300000Completion-idle and progress guard that applies after a tool handoff, native tool completion, post-tool raw assistant progress, raw reasoning completion, or reasoning progress while OpenClaw waits for turn/completed. Use it for trusted or heavy workloads where post-tool synthesis can legitimately stay quiet longer than the final assistant release budget allows.
mode"yolo" unless local Codex requirements disallow YOLOPreset governing YOLO or guardian-reviewed execution.
approvalPolicy"never" or an allowed guardian approval policyNative Codex approval policy delivered to thread start, resume, and turn.
sandbox"danger-full-access" or an allowed guardian sandboxNative Codex sandbox mode delivered to thread start and resume. Active OpenClaw sandboxes narrow danger-full-access turns to Codex workspace-write; the turn network flag follows OpenClaw sandbox egress.
approvalsReviewer"user" or an allowed guardian reviewerTo have Codex review native approval prompts when permitted, apply "auto_review".
defaultWorkspaceDircurrent process directoryWorkspace that /codex bind relies on when --cwd is not supplied.
serviceTierunsetExclusive to the native Codex app-server preference. Any non-empty string is passed through for forward compatibility; the documented options are "priority" and "flex". null removes the override, and the older "fast" is normalized to "priority". This is neither the shared Fast-mode setting nor a direct embedded OpenAI setting. A shared Fast run control takes precedence over it with priority or null, or makes the decision per model call in auto mode.
networkProxydisabledEnables the Codex permissions-profile networking option for app-server commands. OpenClaw defines the chosen permissions.<profile>.network config and picks it with default_permissions rather than transmitting sandbox.
experimental.sandboxExecServerfalseA preview opt-in that registers an OpenClaw sandbox-backed Codex environment with the supported Codex app-server, allowing native Codex execution to run inside the active OpenClaw sandbox.

appServer.serviceTier applies only when no shared Fast-mode run control is provided. On Codex harness turns, shared Fast on transmits priority, Fast off sends null to clear the OpenClaw-owned tier, and auto decides per model call. /codex fast off stands apart: it stores flex in the bound native conversation preference for later conversation-bound turns and leaves the shared OpenClaw session policy untouched. These values describe native configuration and preference state, not observed provider routing.

appServer.networkProxy is explicit because it alters the Codex sandbox contract. When turned on, OpenClaw also sets features.network_proxy.enabled and default_permissions in the Codex thread config so the generated permission profile can initiate Codex-managed networking. OpenClaw generates a collision-resistant openclaw-network-<fingerprint> profile name from the profile body by default; use profileName only when a stable local name is needed.

export default {
  plugins: {
    entries: {
      codex: {
        config: {
          appServer: {
            sandbox: "workspace-write",
            networkProxy: {
              enabled: true,
              domains: {
                "api.openai.com": "allow",
                "blocked.example.com": "deny",
              },
              allowUpstreamProxy: true,
              proxyUrl: "http://127.0.0.1:3128",
            },
          },
        },
      },
    },
  },
};

If the normal app-server runtime would be danger-full-access, enabling networkProxy uses workspace-style filesystem access for the generated permission profile instead. Codex-managed network enforcement is sandboxed networking, so a full-access profile would not guard outbound traffic.

The plugin ships Codex app-server 0.148.0 and accepts external versions at or above 0.147.0. Older, malformed, and unversioned handshakes are rejected. Build metadata does not affect SemVer precedence. The same minimum applies to explicit custom executables, remote app-servers, and macOS desktop binaries; admission is not readiness proof.

OpenClaw treats non-loopback WebSocket app-server URLs as remote and requires identity-bearing WebSocket auth through appServer.authToken or an Authorization header. appServer.authToken and each appServer.headers.* value can be a SecretInput; the secrets runtime resolves SecretRefs and env shorthand before OpenClaw builds app-server start options, and unresolved structured SecretRefs fail before any token or header is sent.

When native Codex plugins are configured, OpenClaw caches one runtime-and-workspace-scoped plugin/installed snapshot. This snapshot covers installed plugins from Codex-discovered marketplaces, including disabled ownership; plugin/read resolves only exact configured plugin identities. Failed or incomplete installed snapshots are never cached. /codex plugins available queries plugin/list for the current conversation workspace, while /codex plugins install <plugin>@<marketplace> installs only after an owner or operator.admin explicitly authorizes that plugin. Existing explicitly configured curated plugins retain their automatic recovery path. The model's plugin-discovery tool cannot install, enable, or authenticate a plugin.

app/installed reports installed app runtime state, and app/read returns authenticated metadata for at most 100 requested app IDs per call. OpenClaw force-refreshes the first cold installed snapshot and consolidates successful curated installations into one app-inventory refresh. Later cached reads do not force repeated connector refreshes.

Deny-by-default Codex app policy is evaluated per thread, so an explicitly allowed app can be installed and authenticated before it becomes callable. OpenClaw provisionally admits only ownership-proven, policy-approved apps, creates the thread with _default.enabled = false and explicit app overrides, then calls app/installed once with that thread's ID and forceRefresh: false. It exposes an app only when Codex confirms the app is enabled and callable for the actual thread. Managed restrictions, workspace policy, missing metadata, revoked auth, and unavailable tools still fail closed.

Attestation completes before OpenClaw injects history, starts a turn, or persists the native thread binding. On failure, OpenClaw deletes a persistent provisional thread with thread/delete or unsubscribes an ephemeral thread with thread/unsubscribe. If safe cleanup cannot be confirmed, it retires the owning app-server connection. Supervised branches also clean up their temporary probe and retain recovery state when cleanup fails.

With allow_all_plugins, an explicitly disabled configured workspace plugin still denies its owned apps. When app/read does not expose that ownership, OpenClaw uses its plugin/installed snapshot and reads only the exact configured plugin's details to reserve the denied app IDs. It does not scan unrelated marketplaces or install, enable, or authenticate the disabled plugin; missing ownership fails closed.

Only connect OpenClaw to a remote app-server in the supported range trusted to accept configured marketplace plugin installs and inventory refreshes. Missing modern inventory methods and server, authentication, or transport failures fail closed.

Approval and sandbox modes

Local stdio app-server sessions default to YOLO mode: approvalPolicy: "never", approvalsReviewer: "user", and sandbox: "danger-full-access". This trusted local operator posture lets unattended OpenClaw turns and heartbeats make progress without native approval prompts that nobody is around to answer.

If Codex's local system requirements file disallows implicit YOLO approval, reviewer, or sandbox values, OpenClaw treats the implicit default as guardian instead and selects allowed guardian permissions. tools.exec.mode: "auto" also forces guardian-reviewed Codex approvals and does not preserve unsafe legacy approvalPolicy: "never" or sandbox: "danger-full-access" overrides; set tools.exec.mode: "full" for an intentional no-approval posture. Hostname-matching [[remote_sandbox_config]] entries in the same requirements file are honored for the sandbox default decision.

Set appServer.mode: "guardian" for Codex guardian-reviewed approvals:

{
  plugins: {
    entries: {
      codex: {
        enabled: true,
        config: {
          appServer: {
            mode: "guardian",
            serviceTier: "priority",
          },
        },
      },
    },
  },
}

The guardian preset, when those values are permitted, expands to include approvalPolicy: "on-request", approvalsReviewer: "auto_review", and sandbox: "workspace-write". Individual policy fields take precedence over mode. While the older guardian_subagent reviewer value remains accepted for compatibility purposes, new configurations should adopt auto_review.

With an OpenClaw sandbox in effect, the local Codex app-server process continues running on the Gateway host. Rather than treating Codex host-side sandboxing as equivalent to the OpenClaw sandbox backend, OpenClaw instead disables Codex native Code Mode, user MCP servers, and app-backed plugin execution for that turn. Shell access is provided through OpenClaw sandbox-backed dynamic tools like sandbox_exec and sandbox_process, assuming the standard exec/process tools are present.

Note

On OpenClaw sandbox hosts backed by Docker (where agents.defaults.sandbox.mode points to a Docker backend), openclaw doctor checks whether the host permits the unprivileged user to use the namespaces that nested Codex bwrap requires for workspace-write shell execution inside the sandbox container. This check also covers network namespaces when Docker sandbox network egress is disabled. A failed probe typically appears as bwrap: setting up uid map: Permission denied or bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted on Ubuntu/AppArmor systems. Correct the host namespace policy for the OpenClaw service user and restart the gateway; prefer a scoped AppArmor profile for the service process rather than the host-wide kernel.apparmor_restrict_unprivileged_userns=0 fallback, and avoid granting extra Docker container privileges solely to accommodate nested bwrap.

Sandboxed native execution

The stable default is fail-closed: with active OpenClaw sandboxing, native Codex execution surfaces that would normally run from the Codex app-server host are turned off. Use appServer.experimental.sandboxExecServer: true only when you want to experiment with Codex's remote environment support alongside OpenClaw's sandbox backend. This preview path relies on the pinned Codex 0.148.0 app-server.

{
  plugins: {
    entries: {
      codex: {
        enabled: true,
        config: {
          appServer: {
            experimental: {
              sandboxExecServer: true,
            },
          },
        },
      },
    },
  },
}

When the flag is enabled and the current OpenClaw session is sandboxed, OpenClaw launches a local loopback exec-server backed by the active sandbox, registers it with the Codex app-server, and begins the Codex thread and turn using that OpenClaw-owned environment. If the app-server cannot register the environment, the run fails closed rather than quietly reverting to host execution.

Sandboxed process output streams as ordered stdout, stderr, or PTY notifications. OpenClaw keeps only a bounded recent-output buffer for polling and replay, so long-running processes cannot expand the app-server bridge indefinitely. Process exit and cleanup stay tied to the sandbox-owned process.

This preview path works only locally. A remote WebSocket app-server cannot access the loopback exec-server unless it runs on the same host, so OpenClaw rejects that combination.

Paired-device remote-exec placement follows a separate, placement-owned execution path and does not depend on appServer.experimental.sandboxExecServer. The Gateway keeps Codex app-server and provider auth local, while the authorized paired device runs the managed Codex exec-server over its existing duplex node connection. This requires explicit gateway.nodes.commands.allow authorization for codex.exec-server.stdio.v1, the approved pairing surface, plus normal node invocation approval. The node gets a fresh private home and sanitized environments, never Gateway provider, cloud, or GitHub credentials. A lost node connection terminates the attempt and process instead of resuming it. Each paired-device attempt uses its own Gateway app-server client, since Codex can register a remote environment but cannot remove one from a running app-server. The device exec-server does not occupy an OpenClaw worker slot. HTTP requests carrying authentication, cookies, API keys, or other credential-bearing headers are rejected before reaching the device; use a Gateway-owned authenticated request or a credential-free endpoint instead. Standard Codex turns are supported, but /btw side questions are unavailable until they can be bound to the active placement. The managed placement workspace is not an OS sandbox: approved processes and files have the node account's full access. Use a separate least-privilege node account when isolation is required. See Run Codex on a paired device.

Auth and environment isolation

In the default per-agent home, managed stdio launches use Codex's ephemeral credential store. OpenClaw supplies auth in this order:

  1. An explicit or ordered OpenClaw auth profile for the agent.
  2. For an API-key route only, a prepared key or local stdio fallback from CODEX_API_KEY, then OPENAI_API_KEY.

The managed app-server does not read an existing codex-home/auth.json in this mode. Import that file explicitly as described below. Set appServer.homeScope: "user" only when the app-server should instead own and use the operator's native Codex account.

No credential file is written in this mode, in either home. A subscription profile is handed over as an account/login/start request of type chatgptAuthTokens, which Codex installs as in-memory external auth rather than persisting; the ephemeral credential store covers the API-key login, which would otherwise write CODEX_HOME/auth.json.

Token refresh is inverted so the long-lived secret never leaves OpenClaw. Codex holds only a short-lived access token, and on an unauthorized response it sends an account/chatgptAuthTokens/refresh request back to OpenClaw over the same connection. OpenClaw refreshes against its own auth profile store and returns a fresh access token, so the refresh token stays in SQLite. A refresh that does not answer within the app-server's timeout fails that turn rather than falling back to another credential.

When OpenClaw sees a ChatGPT subscription-style Codex auth profile (OAuth or token credential type), it removes CODEX_API_KEY and OPENAI_API_KEY from the spawned Codex child process. That keeps Gateway-level API keys available for embeddings or direct OpenAI models without making native Codex app-server turns bill through the API by accident.

Explicit Codex API-key profiles and local stdio env-key fallback use app-server login instead of inherited child-process env. WebSocket app-server connections do not receive Gateway env API-key fallback; use an explicit auth profile or the remote app-server's own account.

Stdio app-server launches inherit OpenClaw's process environment by default. OpenClaw owns the Codex app-server account bridge and sets CODEX_HOME to a per-agent directory under that agent's OpenClaw state. That keeps Codex config, accounts, plugin cache/data, and thread state scoped to the OpenClaw agent instead of leaking in from the operator's personal ~/.codex home.

Set appServer.homeScope: "user" to share native Codex state with Codex Desktop and the CLI. This local user-home mode supports managed stdio and explicit Unix transport. It uses $CODEX_HOME when set and ~/.codex otherwise, including native auth, config, plugins, and threads. OpenClaw skips its auth-profile bridge for the app-server. Verified owner turns can use codex_threads to list (with an optional search filter), read, fork, rename, archive, and unarchive those threads. Fork a thread before continuing it in OpenClaw; independent Codex processes do not coordinate concurrent writers for the same thread.

That homeScope opt-in applies to ordinary harness sessions. A Chat created through Codex Sessions uses its private supervision connection instead, which preserves the native connection's auth and provider configuration for the canonical branch and future resumes.

In a model-locked supervised Chat, codex_threads cannot attach a different fork or archive the Chat's bound native thread. List and metadata-only read remain available. Raw transcript reads require allowRawTranscripts; when it is disabled, list search is also rejected because native search can match transcript previews. Rename, unarchive, detached fork, and archive of an unrelated thread not owned by another OpenClaw Chat require allowWriteControls. Neither option bypasses a locked binding.

OpenClaw does not rewrite HOME for normal local app-server launches. Codex-run subprocesses such as openclaw, gh, git, cloud CLIs, and shell commands see the normal process home and can find user-home config and tokens. Codex may also discover $HOME/.agents/skills and $HOME/.agents/plugins/marketplace.json; that .agents discovery is intentionally shared with the operator home and is separate from isolated ~/.codex state.

In the default agent scope, OpenClaw plugins and OpenClaw skill snapshots still flow through OpenClaw's own plugin registry and skill loader; personal Codex ~/.codex assets do not. If you have useful Codex CLI skills or plugins from a Codex home that should become part of an isolated OpenClaw agent, inventory them explicitly:

openclaw migrate codex --dry-run
openclaw migrate apply codex --yes

Because the default agent scope will not read a copied or mounted codex-home/auth.json directly, credentials must take the sensitive migration path. Point <agent-id> at the configured agent that owns this Codex home:

openclaw migrate plan codex --from <codex-home> --agent <agent-id> --include-secrets --item auth:openai
openclaw migrate apply codex --from <codex-home> --agent <agent-id> --include-secrets --item auth:openai --yes

When a deployment calls for extra environment isolation, append those variables to appServer.clearEnv:

{
  plugins: {
    entries: {
      codex: {
        enabled: true,
        config: {
          appServer: {
            clearEnv: ["CODEX_API_KEY", "OPENAI_API_KEY"],
          },
        },
      },
    },
  },
}

Only the spawned Codex app-server child process is affected by appServer.clearEnv. During local launch normalization, OpenClaw drops CODEX_HOME and HOME from that list: CODEX_HOME remains fixed to the selected agent or user scope, while HOME stays inherited so subprocesses can rely on ordinary user-home state.

Dynamic tools

Codex dynamic tools load by default via searchable, exposed under the openclaw namespace with deferLoading: true. Dynamic tools that overlap with Codex-native workspace operations or Codex's own tool-search surface are generally not exposed by OpenClaw:

  • read
  • write
  • edit
  • apply_patch
  • exec
  • process
  • tool_call
  • tool_describe
  • tool_search
  • tool_search_code

progress_card is excluded from that native workspace tool filtering. It stays reachable through the OpenClaw dynamic-tool bridge as the durable session status surface.

When a finite runtime allowlist turns off native Code Mode, OpenClaw sends an empty execution-environment selection. In that direct, unsandboxed scenario, OpenClaw keeps its policy-filtered exec and process tools as the shell fallback. Runtime allowlists and codexDynamicToolsExclude still apply.

Most of the remaining OpenClaw integration tools, including messaging, media, cron, browser, nodes, gateway, heartbeat_respond, and web_search, are reachable through Codex tool search under that namespace. That approach keeps the initial model context smaller. A few tools remain directly callable regardless of codexDynamicToolsLoading, since Codex tool search may be unavailable or may resolve to a connector-only universe: agents_list, sessions_spawn, and sessions_yield. Developer instructions still guide normal Codex subagents toward native spawn_agent for Codex-native subagent work, while sessions_spawn stays available for explicit OpenClaw or ACP delegation. Message-tool-only source replies also remain direct, because that is a turn-control contract.

Codex Code Mode renders generic OpenClaw dynamic-tool results as text. Read a JSON result before accessing its fields. The Codex runtime serializes nested dynamic calls, so Promise.all will not submit them concurrently; start collector children with a bounded sequential launch loop.

Tools tagged catalogMode: "direct-only", including the OpenClaw computer tool, are collected under openclaw_direct. OpenClaw appends that namespace to Codex's code_mode.direct_only_tool_namespaces list without overwriting operator-supplied entries. As a result, Codex surfaces those tools as DirectModelOnly in normal and code-mode-only threads instead of sending them through nested Code Mode tools.* calls. This boundary is necessary for image-bearing results: nested Code Mode serialization collapses image output to text, which would lose the screenshot required for the next computer action.

Set codexDynamicToolsLoading: "direct" only when connecting to a custom Codex app-server that cannot search deferred dynamic tools, or when debugging the full tool payload.

Timeouts

OpenClaw-owned dynamic tool calls are bounded separately from appServer.requestTimeoutMs. Each Codex item/tool/call request picks the first available timeout in this order:

  • A positive per-call timeoutMs argument.
  • For image_generate, agents.defaults.mediaModels.image.timeoutMs.
  • For image_generate without a configured timeout, the 120 second image-generation default.
  • For the media-understanding view_image tool, the selected image-capable tools.media.models[] entry's timeoutSeconds converted to milliseconds, or the 60 second media default. For image understanding, this applies to the request itself and is not reduced by earlier preparation work.
  • For the message tool, a fixed 600 second outer budget that covers Gateway delivery and bounded same-key reconciliation.
  • The 90 second dynamic-tool default.

That watchdog serves as the outer dynamic item/tool/call budget. Provider-specific request timeouts run inside that call and keep their own timeout semantics. Dynamic tool budgets are capped at 600000 ms. agents_wait adds 30000 ms of outer completion grace, and the app-server client allows 660000 ms so that structured wait result can reach Codex. On timeout, OpenClaw aborts the tool signal where supported and returns a failed dynamic-tool response to Codex so the turn can continue instead of leaving the session in processing.

Once Codex has accepted a turn and OpenClaw has answered a turn-scoped app-server request, the harness expects Codex to advance the current turn and eventually wrap up the native turn with turn/completed. If the app-server stays silent for appServer.turnCompletionIdleTimeoutMs, OpenClaw makes a best-effort attempt to interrupt the Codex turn, logs a diagnostic timeout, and frees the OpenClaw session lane so that subsequent chat messages do not get stuck behind an outdated native turn.

Most non-terminal notifications within the same turn reset that short watchdog, since Codex has demonstrated the turn is still active. Tool handoffs rely on a longer post-tool idle budget: it applies after OpenClaw delivers an item/tool/call response, after native tool items such as commandExecution finish, after raw custom_tool_call_output completions, and after post-tool raw assistant progress, raw reasoning completions, or reasoning progress. The guard uses appServer.postToolRawAssistantCompletionIdleTimeoutMs when set and falls back to five minutes otherwise. That same post-tool budget also stretches the progress watchdog across the quiet synthesis window before Codex emits its next current-turn event. Reasoning completions, commentary agentMessage completions, and pre-tool raw reasoning or assistant progress can be followed by an automatic final reply, so they employ the post-progress reply guard rather than immediately releasing the session lane. Only final/non-commentary completed agentMessage items and pre-tool raw assistant completions trigger the assistant-output release: if Codex then goes silent without turn/completed, OpenClaw best-effort interrupts the native turn and releases the session lane. Replay-safe stdio app-server failures, which include turn-completion idle timeouts lacking assistant, tool, active-item, or side-effect evidence, are retried once on a fresh app-server attempt. Unsafe timeouts still retire the stuck app-server client and release the OpenClaw session lane. They also clear the stale native thread binding instead of being replayed automatically. Completion-watch timeouts surface Codex-specific timeout text: replay-safe cases indicate the response may be incomplete, while unsafe cases instruct the user to check current state before retrying. Public timeout diagnostics include structural fields such as the last app-server notification method, raw assistant response item id/type/role, active request/item counts, and armed watch state. When the last notification is a raw assistant response item, they also include a bounded assistant text preview. They do not include raw prompt or tool content.

Model discovery

By default, the Codex plugin requests available models from the app-server. Model availability is controlled by the Codex app-server, so the list can shift when OpenClaw upgrades the bundled @openai/codex version or when a deployment points appServer.command at a different Codex binary. Availability can also be account-scoped. Use /codex models on a running gateway to see the live catalog for that harness and account.

If discovery is temporarily unavailable or times out, the subscription route uses offline hints derived from the bundled OpenAI model manifest:

Model idDisplay nameReasoning efforts
gpt-5.6-solGPT-5.6 Sollow, medium, high, xhigh, max, ultra
gpt-5.5GPT-5.5low, medium, high, xhigh
gpt-5.5-progpt-5.5-promedium, high, xhigh

Offline hints never prove account entitlement. An authenticated discovery response remains authoritative even if it contains no visible models; HTTP 401 and 403 return an empty catalog rather than exposing fallback models.

Note

The current bundled harness is @openai/codex 0.148.0. A live model/list probe against the official 0.148.0 app-server returned these public picker rows:

Model idInput modalitiesReasoning efforts
gpt-5.6-soltext, imagelow, medium, high, xhigh, max, ultra
gpt-5.6-terratext, imagelow, medium, high, xhigh, max, ultra
gpt-5.6-lunatext, imagelow, medium, high, xhigh, max
gpt-5.5text, imagelow, medium, high, xhigh
gpt-5.2text, imagelow, medium, high, xhigh

Available model IDs, input modalities, and reasoning efforts remain account-scoped. Run /codex models after starting or upgrading the gateway to inspect the actual public picker for your account.

The app-server catalog can report ultra; OpenClaw reasoning controls currently expose levels through max. Hidden models can also appear in the app-server catalog for internal or specialized flows without being normal model-picker choices.

Tune discovery under plugins.entries.codex.config.discovery:

{
  plugins: {
    entries: {
      codex: {
        enabled: true,
        config: {
          discovery: {
            enabled: true,
            timeoutMs: 2500,
          },
        },
      },
    },
  },
}

Disable discovery when you want startup to avoid probing Codex and use only the fallback catalog:

{
  plugins: {
    entries: {
      codex: {
        enabled: true,
        config: {
          discovery: {
            enabled: false,
          },
        },
      },
    },
  },
}

Restricted turns

The Codex harness evaluates the effective tool policy for every turn. It marks the turn policy-restricted when any explicit policy would otherwise leave a Codex-native capability outside the OpenClaw policy boundary.

Restriction sources include global, provider, agent, group, sender, sandbox, subagent, inherited, scheduled/runtime, and per-run tool policies. A finite allowlist always restricts the native surface. A deny list restricts it when an expanded entry is unknown or absent from the audited safe-deny set; this includes wildcards and tool groups containing any unsafe entry. disableTools becomes an empty per-run allowlist and therefore also restricts the native surface. Default tool-profile narrowing is not an explicit restriction and does not activate this mode.

The current audited safe-deny names are:

automations, canvas, dashboard, gateway, heartbeat_respond, image_generate,
memory_get, memory_search, message, music_generate, show_widget, skill_workshop,
tts, video_generate, web_fetch, x_search

A policy containing only those denies stays on the normal Codex native surface; the harness applies the named OpenClaw denial directly. Any other deny fails closed into the restricted surface. For example, tools.deny: ["nodes"] restricts the native surface because nodes is not in the audited set.

Policy-restricted turns have no Codex environment selection or native Code Mode. OpenClaw disables inherited and configured MCP servers, attests that they remain disabled, disables native hook relays, and applies the effective policy to its dynamic tools. A temporary restriction on an existing session uses a transient Codex thread and preserves the unrestricted binding for later resume.

Ring zero is not a configurable policy profile. It is the host-scoped system agent path used by OpenClaw setup and repair flows. The host must activate the system-agent authority and provide the exact single-tool allowlist ["openclaw"]. Ring zero applies the restricted tool surface plus host-authored base instructions and zero project-document budget. It also suppresses OpenClaw's AGENTS.md developer-instruction carrier, so ambient workspace instructions cannot enter the setup/repair turn.

Message-only source replies also use the restricted tool surface. Lightweight bootstrap turns and tool-disabled internal turns additionally set the project- document budget to zero. These modes are separate inputs even when their final thread configuration overlaps.

Workspace bootstrap files

Codex normally handles AGENTS.md itself through native project-doc discovery. OpenClaw does not write synthetic Codex project-doc files or depend on Codex fallback filenames for persona files, because Codex fallbacks only apply when AGENTS.md is missing. Ordinary policy-restricted turns have no native filesystem environment, so OpenClaw instead sends the bounded workspace AGENTS.md snapshot as thread-level developer instructions. Ring-zero, lightweight, message-only, and tool-disabled internal turns suppress that carrier.

For OpenClaw workspace parity, local tool notes live in the ## Tools section of AGENTS.md and normally ride Codex's native project-doc discovery. The Codex harness forwards the other bootstrap files as developer instructions:

  • SOUL.md, IDENTITY.md, and USER.md are forwarded as turn-scoped collaboration instructions. Native Codex subagents do not inherit them, which keeps subagent turns from picking up the parent agent's persona and user profile.
  • The compact loaded OpenClaw skills list is also forwarded as turn-scoped collaboration developer instructions, so native Codex subagents do not inherit it either.
  • Heartbeat turns receive generic initiative guidance through collaboration mode. Monitor cron scratch is appended to the heartbeat prompt instead of injected as workspace context.
  • MEMORY.md content from the configured agent workspace is not pasted into native Codex turn input when memory tools are available for that workspace; when it exists, the harness adds a small workspace-memory pointer to turn-scoped collaboration developer instructions and Codex should use memory_search or memory_get when durable memory is relevant. If tools are disabled, memory search is unavailable, or the active workspace differs from the agent memory workspace, MEMORY.md uses the normal bounded turn-context path instead.
  • BOOTSTRAP.md, when present, is forwarded as OpenClaw turn input reference context.

Environment overrides

For local testing, environment overrides are still available:

  • OPENCLAW_CODEX_APP_SERVER_BIN
  • OPENCLAW_CODEX_APP_SERVER_ARGS
  • OPENCLAW_CODEX_APP_SERVER_MODE=yolo|guardian
  • OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY
  • OPENCLAW_CODEX_APP_SERVER_SANDBOX

When appServer.command is not set, OPENCLAW_CODEX_APP_SERVER_BIN takes over and skips the managed binary.

OPENCLAW_CODEX_APP_SERVER_GUARDIAN=1 is no longer supported. Switch to plugins.entries.codex.config.appServer.mode: "guardian" as the replacement, or use OPENCLAW_CODEX_APP_SERVER_MODE=guardian when you only need a quick local run. For deployments that need to be repeated, configuration is the better choice, since it places the plugin's behavior in the same reviewed file as the rest of the Codex harness setup.

6,614 words · updated Aug 25, 2026