Skip to main content

OpenAI Codex + AxonFlow Integration

AxonFlow adds governance to OpenAI Codex through a hybrid model: enforcement on Bash tool calls via PreToolUse hooks, and advisory governance for other tools via skills that instruct the agent to check policies before acting.

Prerequisites: OpenAI Codex CLI plus an AxonFlow agent gateway. Self-host via Docker Compose (Getting Started) for any real workload — see Privacy notice below for why.

Plugin repo: getaxonflow/axonflow-codex-plugin

Governance coverage
  • Interception point: Codex hooks — PreToolUse / PostToolUse with the matcher Bash | exec_command | shell (per the plugin's hooks.json), backed by advisory skills for other tools.
  • Governs (enforced): terminal/shell command execution — blocked before it runs when policy denies — plus an audit record.
  • Does not enforce: file edits, MCP tools, or prompt content. Non-shell tools are covered only advisorily, through skills that instruct the agent to check policy before acting — that is guidance, not a hard pre-execution gate.

See Governance Architecture and Coverage for how this adapter fits the complete runtime path model.

Privacy notice​

Read before installing. AxonFlow Community SaaS at try.getaxonflow.com is the zero-config endpoint the plugin uses if neither AXONFLOW_ENDPOINT nor AXONFLOW_AUTH is configured. In that mode, governed tool inputs (tool name + arguments) and outbound message bodies are checked by AxonFlow's policy enforcement endpoint and recorded for audit. Community SaaS is offered in two tiers — Free (3-day audit retention, 200 events/day) and Plugin Pro ($9.99 / 90 days, 30-day retention, 2,000 events/day). Both tiers are suitable for individual use within their documented limits. Neither tier is designed for regulated industries, real user data of third parties, or workloads requiring contractual SLOs — see the Privacy Policy for the full scope of what we commit to and what we don't.

For any serious use, choose one of the following instead:

  1. Self-host AxonFlow Community Edition — runs entirely on your infrastructure and keeps data within your boundary. Recommended for any real workload.
  2. Community Edition with an Evaluation License — for production use with real users or clients on the open core; adds production-fit limits and license-gated features. Free 90-day evaluation license.
  3. AxonFlow Enterprise — production-grade governance, regulatory-grade controls, SLOs, and contractual commitments suitable for regulated industries. Contact [email protected].

Setting AXONFLOW_ENDPOINT to a self-hosted AxonFlow URL flips the plugin into self-hosted mode. For a Community Edition self-hosted agent that is enough — no credential is required. For an Enterprise / in-VPC agent you must also authenticate (see Self-hosted / Enterprise authentication), or the agent rejects every call. For air-gapped operation, set AXONFLOW_COMMUNITY_SAAS=0 to suppress the bootstrap attempt and AXONFLOW_TELEMETRY=off to disable the anonymous 7-day heartbeat.


Plugin Pro — paid upgrade for individual developers​

$9.99 USD for 90 days. One-time payment, no auto-renewal.

If you're using this plugin against try.getaxonflow.com and outgrowing the Free tier's caps — daily quota, burst limit, audit retention, the HITL-approval limit, or the lack of LLM cost pre-flight — Plugin Pro raises them:

  • 30-day audit retention (10× Free)
  • 2,000 governed events per day (10× Free)
  • 200 governed write events per minute (Free: 25/min)
  • 20 HITL approvals per rolling 7 days (Free: 2 per rolling 7d)
  • LLM cost pre-flight — see what a multi-step plan costs before it runs (Pro only)
  • Email support, 2 business-day response
  • 14-day refund window — no questions asked

Buy at getaxonflow.com/pricing → paste your cs_<uuid> tenant ID at Stripe Checkout → receive your AXON-… token by email → install with export AXONFLOW_LICENSE_TOKEN='AXON-...' in your shell profile, or write the token to ~/.config/axonflow/license-token (mode 0600). The next tool-using prompt through codex picks up the token and surfaces Pro tier. Full guide: Plugin Pro install.

Pro is for individual-developer use only. For team/production workloads, self-host Community Edition or contact us about Enterprise.


What This Integration Enables In The Hybrid Governance Model​

Codex still uses a hybrid model, but the governed workflow around it is much more usable now. That distinction matters because Codex does not enforce every tool the same way. Terminal execution is hook-enforced, while other actions rely on skills and MCP guidance. Without a common explainability and override model, the user experience after a block can feel fragmented across those two governance paths.

  • blocked exec_command calls can carry decision_id, risk_level, and override hints, so shell enforcement failures have enough context to investigate
  • Codex can use explain_decision, create_override, delete_override, and list_overrides through the agent MCP server when a task needs explanation or a short-lived exception
  • that means the enforced path for terminal work and the advisory path for skills now converge on the same explainability and override model instead of diverging after a deny

The core split is unchanged: Bash and terminal-style tools are still enforced through hooks, while other tools remain advisory through skills. What improves is the unblock experience after a block, especially for teams that want a documented route through Decision Explainability and Session Overrides.

For a senior engineer assessing Codex for governed software delivery, this matters because the same reasoning and exception workflow now spans both sides of the hybrid model. A blocked terminal action can be explained and, if permitted, temporarily unblocked with a visible audit trail. Advisory skills can also steer non-terminal actions through the same explanation and override tools, even though those paths are not enforced the same way. That distinction is important: Codex is strict on the hook side and guidance-driven on the skill side. Making that explicit is what turns the plugin into something a platform team can reason about instead of a fuzzy "guardrails" story.


What Codex Does Well​

OpenAI Codex is a cloud-based agentic coding platform with strong execution capabilities:

  • Cloud-hosted agentic coding with sandboxed execution
  • MCP server support for external data and tool access
  • Skill system for composable, reusable agent instructions
  • Git-integrated development workflows
  • Task-based asynchronous execution

What Codex Doesn't Provide​

Production RequirementCodex's Position
Policy enforcement before Bash executionPreToolUse hooks available — governance logic not provided
Policy checks for non-Bash toolsSkills can advise — cannot enforce
PII detection in tool outputsNot addressed
Audit trails for complianceExecution logs exist — not compliance-formatted
SQL injection prevention for MCP queriesNot provided
Approval gates for sensitive operationsNot provided

Governance Model​

AxonFlow uses a hybrid approach on Codex:

Governance TypeToolMechanismEnforcement
EnforcementBash/exec_commandPreToolUse hook (exit code 2 = block)Yes — dangerous commands blocked before execution
AdvisoryWrite, Edit, MCP toolsSkills instruct agent to call check_policyAgent decides — skills guide but cannot force
AuditAll governed toolsPostToolUse hook (Bash) + skills (others)Automatic for Bash, skill-guided for others

Enforcement (Bash/exec_command): The PreToolUse hook fires on every terminal command (Codex reports these as exec_command), evaluates the command against AxonFlow policies, and blocks it (exit code 2) if it violates policy. This is automatic and cannot be bypassed.

Advisory (other tools): For Write, Edit, and MCP tool calls, governance skills instruct the Codex agent to call check_policy before proceeding. Skills support implicit activation — Codex invokes them automatically when the task matches the skill description. However, the agent ultimately decides whether to follow the skill's guidance.


How AxonFlow Plugs In​

Terminal commands (enforced):

Codex selects exec_command tool
│
▼
PreToolUse hook fires automatically
│ → check_policy("codex.exec_command", "curl 169.254.169.254")
│
├─ BLOCKED (exit 2) → command never runs
└─ ALLOWED (exit 0) → command executes → PostToolUse audits + PII scans

Other tools (advisory):

Codex selects Write/Edit/MCP tool
│
▼
Governance skill activates (implicit or explicit)
│ → agent calls check_policy("codex.Write", file content)
│
├─ Policy says blocked → agent should not proceed (advisory)
└─ Policy says allowed → agent proceeds → audit skill records action

Quick Start: Plugin Installation​

# 1. Start AxonFlow (if not already running)
git clone https://github.com/getaxonflow/axonflow.git
cd axonflow && docker compose up -d

# 2. Clone the plugin
git clone https://github.com/getaxonflow/axonflow-codex-plugin.git

# 2a. Optional: increase hook HTTP timeout for remote deployments
export AXONFLOW_TIMEOUT_SECONDS=12

# 3. Configure MCP server in Codex (TOML format in ~/.codex/config.toml)
cat >> ~/.codex/config.toml << 'EOF'

[mcp_servers.axonflow]
url = "http://localhost:8080/api/v1/mcp-server"
EOF

# 4. Enable hooks and place hooks.json
cat >> ~/.codex/config.toml << 'EOF'

[features]
codex_hooks = true
EOF
cp axonflow-codex-plugin/hooks/hooks.json ~/.codex/hooks.json

# 5. Create local marketplace entry (from the directory where you'll run codex)
mkdir -p .agents/plugins
cat > .agents/plugins/marketplace.json << 'EOF'
{
"name": "axonflow-local",
"plugins": [{
"name": "axonflow",
"source": { "source": "local", "path": "./axonflow-codex-plugin" },
"policy": { "installation": "INSTALLED_BY_DEFAULT" },
"category": "Security"
}]
}
EOF

# 6. Launch Codex and install the plugin via /plugins
codex

In community mode, no auth is needed. The MCP server config must be in ~/.codex/config.toml (TOML format) — Codex does not read .mcp.json from the plugin directory for MCP server connections.

Self-hosted / Enterprise authentication​

  • Community Edition self-hosted — the agent accepts unauthenticated calls; leave AXONFLOW_AUTH unset.
  • Enterprise / in-VPC agents — the agent requires HTTP Basic auth on every call, including the MCP server connection. Add an env_http_headers block to your [mcp_servers.axonflow] entry so Codex attaches the credential, and point the url at your agent:
[mcp_servers.axonflow]
url = "https://your-agent.internal:8080/api/v1/mcp-server"

[mcp_servers.axonflow.env_http_headers]
"Authorization" = "AXONFLOW_AUTH"
"X-License-Token" = "AXONFLOW_LICENSE_TOKEN"

Codex's env_http_headers maps a header name to the name of an environment variable whose value it sends verbatim. Because Codex does not add the Basic prefix for you, AXONFLOW_AUTH must include it for Codex (unlike the Claude Code and Cursor plugins, where it is the bare base64):

# NOTE the leading "Basic " — required for Codex's verbatim env_http_headers.
export AXONFLOW_AUTH="Basic $(printf '%s:%s' "<org_id>" "<license_key>" | base64 | tr -d '\n')"

Without this, codex mcp get axonflow will connect but every tool call returns an authentication error and governed tools are blocked.

Per-user authorization token — AXONFLOW_USER_TOKEN​

Requires plugin 1.6.0+ and platform v9.10.0+ (Enterprise).

The shared AXONFLOW_AUTH credential authenticates the tenant; the per-user token identifies and authorizes the developer behind the session. Your AxonFlow admin mints a token per developer (or your IdP issues one via OIDC), and the plugin sends it as the X-User-Token header on every governed request — both hooks and the MCP session. The platform validates it and resolves a {identity, role} that scopes governance reads: a developer-role token reads its own audit/decision/override rows, an admin-role token reads the whole tenant, and — a behavior change on platform v9.10.0 — a caller with no per-user identity reads zero rows from the read tools (search_audit_events, list_overrides, …) instead of the whole tenant trail (an asserted email behind the platform's identity trust gate is capped at its own rows). Enforcement (allow/deny/redact) is unaffected. See the two identity layers.

The hooks resolve the token from AXONFLOW_USER_TOKEN (wins outright) or the 0600 provisioning file ~/.config/axonflow/user-token.json ({"token": "<minted token>"} — the plugin refuses a file with looser permissions):

export AXONFLOW_USER_TOKEN=<token minted by your AxonFlow admin>

For the MCP session, Codex attaches headers from config.toml, so the env_http_headers block gains a third entry (env-var-only on this plane — the file fallback covers the hooks):

[mcp_servers.axonflow.env_http_headers]
"Authorization" = "AXONFLOW_AUTH"
"X-License-Token" = "AXONFLOW_LICENSE_TOKEN"
"X-User-Token" = "AXONFLOW_USER_TOKEN"

After upgrading the plugin, re-run bash scripts/install-mcp-with-headers.sh to regenerate this block.

Unset — no X-User-Token header is sent (never an empty header); requests are exactly what a pre-1.6 plugin sends, so rollout can be incremental. A malformed value is dropped locally by the hooks rather than sent; a present-but-invalid token (expired, revoked, tampered) is rejected by the platform fail-closed — with a token configured, the hooks treat an authentication rejection as a block, not a fall-open. Token minting, rotation, and the IdP/OIDC path are covered in Per-Developer Identity → Provisioning.

Timeout Tuning​

Use AXONFLOW_TIMEOUT_SECONDS when Codex needs to reach AxonFlow over a slower network path, VPN, or remote deployment.

  • PreToolUse defaults to 8 seconds when unset
  • PostToolUse defaults to 5 seconds when unset
  • setting AXONFLOW_TIMEOUT_SECONDS applies the same timeout to all hook HTTP calls

MCP Tools​

10 MCP tools are served by the agent's MCP server at /api/v1/mcp-server. The plugin's .mcp.json points Codex at the agent endpoint; the plugin itself doesn't define the tools. Platform-side tool additions are immediately available to Codex.

Governance (6):

ToolPurpose
check_policyEvaluate specific inputs against policies
check_outputScan specific content for PII/secrets
audit_tool_callRecord additional audit entries
list_policiesList active governance policies
get_policy_statsGet governance activity summary
search_audit_eventsSearch individual audit records

Session overrides and explainability (4):

ToolPurpose
explain_decisionReturn the full DecisionExplanation for a decision ID
create_overrideCreate a time-bounded, audit-logged session override (mandatory justification)
delete_overrideRevoke an active session override
list_overridesList active overrides scoped to the caller's tenant

When Codex stderr prints a governance block on an exec_command call, the decision ID is included. The agent can call explain_decision with that ID and, if the decision is overridable, create_override to unblock. For non-exec_command tools, the hybrid governance model still applies — the advisory skills will guide Codex to consult these same MCP tools.


Skills​

SkillWhen UsedActivation
pre-execute-checkBefore non-Bash tool calls that modify stateImplicit (task matches) or explicit (@axonflow)
post-execute-auditAfter non-Bash tool calls completeImplicit or explicit
pii-scanAfter tool calls that return dataImplicit or explicit
governance-statusWhen checking governance postureExplicit
audit-searchWhen searching compliance evidenceExplicit
policy-listWhen listing active policiesExplicit

Skills support implicit activation: Codex invokes them automatically when the current task matches the skill description. For example, if a user asks "write this data to a file", the pre-execute-check skill may activate automatically because the task involves state modification.


Integration-Specific Policies​

Set AXONFLOW_INTEGRATIONS=codex or let auto-detection handle it:

  • .codex-plugin/*.json and .mcp.json write protection (block)

Latency Considerations​

OperationTypical Latency
Policy pre-check (hook)2-5ms
PII detection1-3ms
Audit write (async)0ms (non-blocking)
Total overhead3-10ms

Troubleshooting​

MCP Server Connection Failed​

Codex reads MCP config from ~/.codex/config.toml (TOML format), not from .mcp.json in the plugin directory. Add [mcp_servers.axonflow] with url = "http://localhost:8080/api/v1/mcp-server" to your config.toml.

Hooks Not Firing on Bash​

Hooks must be at ~/.codex/hooks.json (not inside the plugin directory). Enable hooks with [features] codex_hooks = true in ~/.codex/config.toml. The hook matcher should include exec_command — Codex uses this tool name for terminal commands, not Bash.

Skills Not Activating​

Skills activate implicitly when the task matches the description. For explicit invocation, use @axonflow. Ensure the plugin is installed via /plugins in Codex and the MCP server is reachable.

Plugin Not Visible in /plugins​

The marketplace.json must be at $CWD/.agents/plugins/marketplace.json relative to where you launch codex. The source.path must be relative (start with ./) and point to a directory inside the same root.

PII in File Writes Not Detected​

Codex hooks currently only support Bash (exec_command). Write and Edit operations cannot be hooked. PII detection for file writes depends on advisory skills — the pre-execute-check and pii-scan skills instruct the agent to call check_output before writing, but this is not enforced.


Telemetry​

This plugin sends an anonymous heartbeat at most once every 7 days during activity. Under the v1 telemetry schema, the ping carries telemetry_type=plugin, sdk=codex-plugin, and stream=heartbeat. The payload also includes plugin version, OS, architecture, bash version, and AxonFlow platform version. No PII, no tool arguments, no policy data.

The cadence is gated by a stamp file at $HOME/.cache/axonflow/codex-plugin-telemetry-sent; delete it to force one fresh ping on the next hook invocation.

Opt out with AXONFLOW_TELEMETRY=off. DO_NOT_TRACK is not honored — the Codex CLI injects DO_NOT_TRACK=1 into every hook subprocess regardless of user intent, so it cannot represent a real opt-out signal in this context. See Telemetry for the full wire-level field reference and the scope of AXONFLOW_TELEMETRY=off on Community SaaS vs self-hosted.

Plugin: v1.9.0 | Platform: v11.1.0 | SDKs: Python v9.4.0, TypeScript v9.4.0, Go v9.4.0, Java v9.4.0, Rust v0.11.0 (preview)

Implementation Checklist​

Before you put this integration in front of real users, connect it back to the core runtime docs: