Skip to main content
The Codex plugin evaluates every tool call in a Codex session and writes a hash-linked decision chain you can verify afterwards. It runs the same runtime as the Claude Code plugin, so the rules, configuration and chain format are identical. Everything runs on your machine; sessions stream to a console only when you set AGENTEGRITY_TOKEN and AGENTEGRITY_EXPORTER_URL.

What it does

The plugin registers python3 -m agentegrity hook --host codex on eight Codex hook events: PreToolUse, PostToolUse, UserPromptSubmit, Stop, SubagentStart, SubagentStop, PreCompact and SessionEnd. The first hook of a session starts a daemon that holds the session’s state, so the layers see the whole conversation in order. Two things differ from Claude Code:
  • Verdicts. Codex parses an ask decision but only enforces deny, so the runtime maps both block and escalate to deny, with the reason shown. Anything that would ask for approval on Claude Code is denied on Codex. That includes GOV-002: a command that gives an interpreter a program inline (python -c, node -e, a heredoc into python) is denied, while bash -lc '…' is judged by the command inside it. AGENTEGRITY_SANDBOXED=1 turns this off.
  • Failures. Codex has no separate failure event. A PostToolUse whose tool_response.exit_code is a non-zero integer is recorded as post_tool_use_failure, with the exit code and the last 500 characters of the command’s output as the error.
What the runtime checks:
  • Argument classification. A downloaded or decoded payload piped into an interpreter, or deleting logs and shell history, is denied. Commands computed at runtime ($IFS splicing, computed executables) are denied as well, since they escalate. apply_patch is read as a file edit, never as shell: its paths come from the *** Update File:, *** Add File: and *** Delete File: headers.
  • Sensitive-data egress (GOV-005). An external send after a secret was read in the session, or in the same command, is denied. Reading a secret alone is allowed and recorded.
  • Output scanning. Injection found in tool output lowers the score until the context is compacted.
  • Written content. Lines added to files by apply_patch are scanned for instructions, and a strong finding is denied.
  • Behavioral drift. Each session that ends without a block or escalate teaches a per-agent baseline in <hook dir>/codex/baselines/. Later sessions whose tool mix departs from it lower the score and alert. Drift never blocks here.
  • Token usage. Read from the rollout’s token_usage_record lines (one per response), with the model from turn_context or the hook’s model field, totalled per model and sent on stop events and in the session summary. Older Codex builds without those lines fall back to token_count events, and the usage is marked incomplete. Only usage counts and model names are kept from the rollout.
  • Decision chain. Every evaluation and a hook_verdict decision for every non-allow verdict are appended to <hook dir>/codex/<session>.chain.json, written atomically with mode 0600 and resumed if the daemon restarts.
Verify a chain with:
The hook runtime signs every record with an Ed25519 key it creates on first use at <hook dir>/keys/hook.key (mode 0600), and writes the public key beside it as hook.pub, which is what --trusted-key takes. Set AGENTEGRITY_SIGNING_KEY_FILE to use your own key. Signing needs the [crypto] extra; without it, or with a key file others can read, chains stay unsigned and the hook keeps working. The key sits on the same machine and under the same user as the agent, so a signature shows the chain was not changed afterward by someone without the key; it does not stop a process running as you from signing a forged one. See Attestation.

Install

Install agentegrity from the marketplace, then run /hooks once to review and trust the plugin’s hooks. Codex does not run hooks that are not managed until you trust them. Organizations can ship them as managed hooks through requirements.toml instead. The plugin version (0.13.0) matches the library release it needs. If the hook command fails because the library is missing or older than 0.11.0, the plugin prints a system message saying the action was not checked, and the action goes through. The plugin is a root plugin.json and hooks/hooks.json. Every command has a 20 second timeout except SessionEnd (5 seconds), and PreToolUse and PostToolUse use "matcher": "*". If your Python launcher is python rather than python3, change the command in hooks/hooks.json.

Configuration

Codex reads the same environment variables as Claude Code. AGENTEGRITY_AGENT_ID and AGENTEGRITY_AGENT_NAME default to codex, and chains, usage state and baselines live under <hook dir>/codex/.

Stream sessions to a console

Set the token and URL in the environment Codex starts from; the session daemon inherits it and attaches the built-in HTTPExporter:
Or let agentegrity pro check the token against the console and run Codex with both variables set:
Events carry full content, including prompts and tool arguments. Only the daemon streams; on Windows, where there is no daemon, nothing is sent. See Agentegrity Pro and Data flows.

Failure semantics

The hook never breaks a session. When it cannot reach a verdict it prints nothing, and Codex proceeds as it would without the plugin.

Limits

These come from Codex’s hook coverage and cannot be closed from a hook:
  • write_stdin has no PreToolUse, so input typed into a shell that is already running is not checked.
  • A command still running when its call returns gets no PostToolUse, so its output is never scanned.
  • Hosted tools such as web search do not go through hooks.
The plugin has not yet been exercised against a live Codex binary; the runtime is tested in-process and as separate processes for both hosts, and is marked experimental in STATUS.md. The hook evaluates tool calls, not the model’s reasoning, and static command analysis flags runtime-computed commands as obfuscated rather than resolving them.