Repository navigation
Description
Summary
codex itself supports workspace-write sandboxing with network access enabled — sandbox_mode = "workspace-write" plus [sandbox_workspace_write] network_access = true. None of codex-acp's three agent modes exposes that combination, and no configuration path can reach it.
The result is that a host application driving codex-acp has only two usable options:
| mode | sandbox | network |
|---|---|---|
read-only |
readOnly |
✗ |
agent (default) |
workspaceWrite |
✗ |
agent-full-access |
dangerFullAccess, approval never |
✓ |
So enabling network for an agent means giving up the workspace boundary and approvals at the same time. There is no way to say "keep the workspace sandbox, allow network".
Why this matters
Our use case is an automated code-review agent. It runs in a checkout, and its job legitimately ends in network calls — git ls-remote / git fetch against the forge, then posting the review back. Under the default agent mode every one of those fails, and the run ends with nothing to do. The only mode that lets it work is agent-full-access, which also removes the workspace boundary and silences approvals — considerably more privilege than the task needs, for an agent whose whole design premise is that its worst case should be a wrong opinion.
Running the same prompt through the codex CLI directly works exactly as wanted:
codex exec --strict-config -s workspace-write -c sandbox_workspace_write.network_access=true "…"
→ sandbox: workspace-write [workdir, /tmp, $TMPDIR] (network access enabled)
→ git ls-remote … succeeded
--strict-config accepts the key, so it is a recognised setting — it just cannot be reached through ACP.
Cause
Two things combine.
1. The modes are hardcoded. AgentMode defines exactly three statics, and Agent — which is DEFAULT_AGENT_MODE — fixes networkAccess: false:
static Agent = new _AgentMode(
"agent", "Agent", "Read and edit files, and run commands.",
"on-request",
{ type: "workspaceWrite", writableRoots: [], networkAccess: false,
excludeTmpdirEnvVar: false, excludeSlashTmp: false },
"workspace-write"
);Nothing constructs an AgentMode anywhere else, and AgentMode.find() resolves only against those three — including for INITIAL_AGENT_MODE, where an unrecognised value falls back to agent silently.
2. Config cannot widen it, because the policy is re-asserted every turn. CODEX_CONFIG does reach the session — CodexAcpClient keeps it as this.config, createSessionConfig() merges it, and it is sent as the config field of thread/start. But sendPrompt then passes the mode's policy into every turn/start:
return await this.codexClient.runTurn({
threadId: request.sessionId,
input,
approvalPolicy: agentMode.approvalPolicy,
sandboxPolicy: addAdditionalDirectoriesToSandboxPolicy(agentMode.sandboxPolicy, additionalDirectories),
…
});There is no conditional, and addAdditionalDirectoriesToSandboxPolicy only appends writable roots — it never touches networkAccess. So a sandbox_workspace_write.network_access = true supplied via config.toml or CODEX_CONFIG is transmitted at thread start and then overwritten on the first prompt turn.
This is observable from the host side: a session run this way records
sandbox_policy = {"type":"workspace-write","network_access":false,…}
sandbox_mode = null
approval_policy = "on-request"
— an explicit turn-level policy object rather than a config-level mode string.
There is a subtlety worth flagging for anyone debugging this: runReview and runGoalSet do not send a sandboxPolicy, so the thread-level config still governs those. That makes it possible to see config-supplied network settings appear to work on one path while silently having no effect on ordinary prompts.
Versions
Observed on 1.1.14. Verified still present in 1.3.0 (latest at time of writing) — the Agent static still carries networkAccess: false, and sendPrompt still passes sandboxPolicy: addAdditionalDirectoriesToSandboxPolicy(agentMode.sandboxPolicy, …) into runTurn. So upgrading does not address it.
Relationship to #310
Same chokepoint, different missing capability. #310 asks for granular approval policy from config.toml, and a commenter there additionally wants sandbox-off-with-approvals-on. This request is the other axis — keep the workspace sandbox and the approval behaviour exactly as agent has them, and only allow network. Neither is a superset of the other, but a fix that decouples the policy dimensions from the three presets would resolve both.
Possible directions
Roughly in increasing order of scope, and entirely your call which fits the project:
- Let
CODEX_CONFIG/config.tomlwiden the selected mode rather than being overwritten — i.e. treat the mode as a default and the config as an override at turn construction. This is the smallest change and would close Sandbox and approval policies from config.toml are ignored #310 too. - Add a fourth mode, e.g.
agent-network:workspaceWrite+networkAccess: true, approval stillon-request. Cheap and explicit, but adds a preset rather than removing the coupling. - Make
networkAccessselectable independently of the sandbox type — a config knob or an ACP session option — which is the general form of the problem both this and Sandbox and approval policies from config.toml are ignored #310 describe.
Happy to test a patch against our setup if that would help; we drive codex-acp over ACP stdio from a host application and can report what a real run records.
Activity
cblage commentedon Aug 28, 2026
FWIW, I got mine to work with network access AND manual approvals with
auruhm commentedon Sep 29, 2026
Confirming this from a different client/setup, with a measurement that may help land one of the open fixes.
Environment: Zed (macOS, Apple Silicon) driving
codex-acp1.13.1 fromagent_servers, Codex CLI 0.157.1. The session runs in the default mode (agentviaDEFAULT_AGENT_MODE;INITIAL_AGENT_MODEis not set). This is a plain Agent prompt — no explicit mode change.Observed — a network command in the default
agentmode fails at DNS resolution, not at the forge:The same command through Codex's own sandbox, with the combination this request asks for, works:
So the only difference between "blind to the network" and "works" is exactly the
network_accessflag the per-turn policy discards — confirming both halves of the report on 1.13.1.I also traced the code path in 1.13.1:
AgentMode.Agent(theDEFAULT_AGENT_MODE) hardcodesnetworkAccess: false, andsendPromptpassessandboxPolicy: addAdditionalDirectoriesToSandboxPolicy(agentMode.sandboxPolicy, …)into everyturn/start;addAdditionalDirectoriesToSandboxPolicyonly appends writable roots and never touchesnetworkAccess. Asandbox_workspace_write.network_access = truesupplied viaCODEX_CONFIG/config.tomlreachesthread/startand is then overwritten on the first prompt turn — exactly as described.+1 for direction 1 (let
CODEX_CONFIG/config.tomlwiden the selected mode rather than being overwritten): it is the smallest change and would close #310 as well. Both #561 and #368 already implement the network half of it — would love to see one of them merged.Current workaround: selecting
agent-full-accessfor the session, which grants unrestricted filesystem access and turns approvals off — far more privilege than a task that only needsgit ls-remote/git fetch.ma-pony commentedon Oct 10, 2026
Reproduced this on upstream v2.2.2 and opened #608 with a configuration-based fix.
For workspace-write turns, it uses an explicit boolean from CODEX_CONFIG first, then Codex's effective config/read result for the working directory, then the existing mode default. This covers config.toml as well as the supplied session configuration, while leaving other sandbox types, writable roots and approvals unchanged.
The new policy tests reproduce the problem before the change and pass afterward. A native Codex config/read probe also confirmed that the file-backed flag reaches the outgoing workspace-write policy; it made no model requests. Full local tests pass except for three filesystem-watcher failures that also reproduce on the unmodified upstream SHA in this macOS environment. The PR remains Draft pending the release-matrix/CI checks.
Related to the existing approaches in #561 and #368; this proposal includes the effective file-configuration path rather than changing everyone's default mode.