Codex Harness Integration#
Codex is integrated as a first-class harness in Agenta, on architectural parity with Claude and Pi. It runs inside the SandboxAgentBackend and is delivered via the Agent Client Protocol (ACP) over local, Daytona, and E2B sandboxes. The full integration landed in PR #5509 and shipped in v0.108.0 . Sandbox support tracking is in issue #5502 .
Key Entry Points#
| Layer | Path |
|---|---|
| SDK DTOs / template | sdks/python/agenta/sdk/agents/dtos.py |
| Config renderer | sdks/python/agenta/sdk/agents/adapters/codex_settings.py |
| Harness adapter | sdks/python/agenta/sdk/agents/adapters/harnesses.py |
| Backend registration | sdks/python/agenta/sdk/agents/adapters/sandbox_agent.py |
| Model catalog data | sdks/python/agenta/sdk/agents/data/codex_models.curated.json |
| Runner session mode | services/runner/src/engines/sandbox_agent/codex-mode.ts |
| Runner asset provisioning | services/runner/src/engines/sandbox_agent/codex-assets.ts |
| ACP approval patch | services/runner/src/engines/sandbox_agent/codex-acp-patch.ts |
| Executable tool gate | services/runner/src/engines/sandbox_agent/executable-tools.ts |
| Design decisions | docs/design/codex-harness/decisions.md |
SDK Layer (Python)#
CodexAgentTemplate (in dtos.py) defines Codex's configuration model. It exposes tool_specs, harness_permissions, and three wiring methods :
wire_harness_mode()β returns an optional ACP session mode override (agent,read-only, oragent-full-access)wire_harness_files()β delegates tocodex_settings.pyto renderconfig.tomlwire_tools()β declares an empty built-in list; all tools arrive via MCP
codex_settings.py renders configuration in two layers :
- Layer 1 β passes the author's
approval_policyandsandbox_modethrough verbatim - Layer 2 β derives
sandbox_mode = "read-only"from a read-only filesystem boundary for reinforcement
capabilities.py advertises the curated Codex model list: gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.2 β all under the OpenAI provider only, with user HTTP MCP servers supported but no built-in MCP servers .
sandbox_agent.py adds Codex to its supported_harnesses frozenset .
Runner Layer (TypeScript)#
Four new TypeScript modules in services/runner/src/engines/sandbox_agent/ handle Codex-specific execution :
codex-mode.tsβ session mode resolution and applicationcodex-assets.tsβ credential provisioning and SQLite home redirectioncodex-acp-patch.tsβ build-time approval preset patchingexecutable-tools.tsβ two-layer tool gating
run-turn.ts (modified) wires the buildExecutableToolGate for Codex, handles Codex's dot-notation MCP tool names (e.g., mcp.agenta-tools.discover_tools), and records gate decisions as "codex-acp-permission" for warm approval parking .
Design Decisions#
1. File-Free Managed Authentication (D-002)#
Instead of writing auth.json to disk (which creates security and cleanup risks on durable Daytona object storage), the SDK renders a model_providers block in config.toml pointing to env_key = "OPENAI_API_KEY". Codex reads the key from the daemon's process environment at request time . For subscription mode, only auth.json is symlinked into the runner-owned home to prevent operator config leakage .
2. Approval Preset Patching (D-008 Amendment)#
The codex-acp bridge hardcodes approvalPolicy: "never" in its agent-full-access preset, silently disabling all permission gates. codex-acp-patch.ts patches this to "on-request" at build time β applied to both the runner image and the Daytona snapshot β enabling warm approval parking (the turn stays alive and resumes when the user approves), matching Claude's behavior. The patch is idempotent and fails the image build loudly if its anchor drifts .
3. Durable Home + In-VM SQLite#
CODEX_HOME = <cwd>/.codex stays on the durable mount so native sessions and resume survive sandbox replacement. CODEX_SQLITE_HOME is redirected to an ephemeral in-VM directory because geesefs cannot support SQLite's write-ahead logging .
4. Two-Layer Tool Gating#
Tool execution is enforced at both the harness's native ACP gate (now enabled via the approval patch) and the runner's loopback MCP seam gate. Execution grants prevent double-prompting: one approval satisfies both layers. Gate verdicts are allow, deny, or pendingApproval (which parks the turn) .
Test Coverage#
Tests are stratified across unit, integration, and live QA:
SDK unit tests :
test_codex_settings_layers.pyβ Layer 1/2 config rendering, managed vs. subscription auth, TOML formattingtest_capabilities_codex.pyβ capability declarationstest_wire_contract.pyβ wire contract validation including Codex fixtures
Runner unit tests :
executable-tools.test.tsβ tool gate decision matrix (allow/deny/ask), MCP envelope unwrapping, cold replaysandbox-agent-codex-assets.test.tsβ credential provisioning, SQLite redirection, symlink idempotencycodex-acp-patch.test.tsβ patch idempotence and anchor validationcodex-mode.test.tsβ mode resolution and error handlingsession-keepalive-approval.test.tsβ warm approval parking across turns
Integration test :
test_codex_tool_replay.pyβ replays a realgpt-5.6-lunaMCP tool invocation against the recordedcodex-agenta-tools-call.jsonfixture
The post-rebase suite passes 731 SDK agent unit tests and 1477 runner tests (96 files) . Live QA covered the full approval matrix: {local, daytona} Γ {allow, deny, ask-warm, ask-cold}, achieving 20/20 on local and green across all Daytona cells .