Codex CLI
Codex speaks only the OpenAI Responses API, which the gateway serves for the `openai` provider. `install codex` adds a model provider to `~/.codex/config.toml`.
Codex sends POST /v1/responses. Of the built-in providers only openai serves the responses surface, so Codex is always wired to https://guardrails.vulnetix.com/openai/<uuid>/v1. Pointing it at groq, openrouter or another chat-only provider returns 404 unsupported_api.
With the CLI
vulnetix ai-firewall key set openai --from-env OPENAI_KEY # once per organisation
vulnetix ai-firewall install codex --model gpt-4o-mini
install codex always writes ~/.codex/config.toml (user scope). It edits the file as text, keeps your comments and table order, and refuses to write a file that does not parse as TOML. It adds two root keys and one fenced table:
model = "gpt-4o-mini"
model_provider = "vulnetix-openai"
# Vulnetix AI Firewall
[model_providers.vulnetix-openai]
name = "Vulnetix AI Firewall (openai)"
base_url = "https://guardrails.vulnetix.com/openai/<uuid>/v1"
env_key = "VULNETIX_API_KEY"
wire_api = "responses"
# End Vulnetix AI Firewall
model is only written with --model, and the model is checked against your policy first. If the gateway does not advertise responses for openai, the CLI skips Codex with wire_unsupported rather than writing a config that would fail.
env_key names a variable: Codex reads the key from the environment, so export it where Codex runs.
export VULNETIX_API_KEY="<your Vulnetix API key>"
uninstall codex removes the table, and removes model_provider and model only while model_provider still names vulnetix-openai.
By hand
Write the block above into ~/.codex/config.toml yourself. The four values that matter:
wire_api = "responses". Codex accepts no other value.base_urlends in/v1.- The slug in
base_urlisopenai. env_keyis the name of the variable holding your Vulnetix key, not the key.
Verify
vulnetix ai-firewall status
codex should be wired, with the gateway URL as its base URL. points elsewhere means config.toml names another base_url and raises bypasses_firewall.
What Codex declares
| In the request | What it is |
|---|---|
tools[] with "type": "function" |
Codex’s own tools, such as apply_patch |
tools[] with "type": "local_shell", "web_search" |
Provider built-ins. The type is the name a rule matches. |
tools[] with "type": "mcp", server_label, server_url |
A remote MCP server, named and with its URL |
function_call, mcp_call items in input[] |
Tools called on earlier turns |
originator, User-Agent |
codex_cli_rs and codex_cli_rs/<version>; the gateway names the client codex-cli |
A local MCP server from config.toml arrives flattened into tools[] as <server>__<tool>, so it needs a tool rule. A remote one can be matched by an MCP rule.
Errors
| Status | code |
Cause |
|---|---|---|
401 |
invalid_api_key |
VULNETIX_API_KEY is unset, empty, or holds an OpenAI key |
403 |
provider_key_missing |
No OpenAI key in the vault |
403 |
model_not_allowed, model_denied |
The model is refused by policy |
404 |
unsupported_api |
The slug is not openai, or wire_api is not responses |
Limits
- Codex has no second credential or background model, so every request uses the provider you selected.
model_provideris one line in a file the developer owns.statusfinds a machine where it was changed back.- Tool-call arguments (shell commands, patches) are not scanned. Tool results are.