Skip to main content
Version: 1.9.0

Govern Codex CLI with DVARA

Codex CLI sends its model calls straight to OpenAI. Your security team sees none of them. From 1.9.0 DVARA serves what Codex sends on the OpenAI Responses API, POST /v1/responses, with Codex's default settings. Point Codex at the DVARA AI governance platform and every model call it makes is governed and billed to one DVARA workspace.

Tested with Codex CLI 0.155.1.

What DVARA governs​

Each model call Codex makes runs the same controls as /v1/chat/completions: policy, PII rules, guardrails, budgets, rate limits, cost records and the audit chain. That includes the tool calls the model asks for and the tool output Codex sends back, so a guardrail or PII rule sees the files and command output that reach the model.

Point Codex CLI at DVARA​

You need:

  • A running DVARA 1.9.0 Gateway that Codex can reach.
  • A provider for the models Codex asks for. For OpenAI models, set OPENAI_API_KEY on the Gateway.
  • A DVARA workspace API key. If the key has scopes, it needs completions:write.

Add a provider for DVARA to ~/.codex/config.toml:

model_provider = "dvara"
model = "<model-id>" # a model your Gateway routes
web_search = "disabled" # required: see below

[model_providers.dvara]
name = "DVARA"
base_url = "https://gateway.acme.example.com/v1"
env_key = "DVARA_API_KEY"
wire_api = "responses"

Then set the key where Codex runs, and start Codex as usual:

export DVARA_API_KEY=<dvara-workspace-key>
codex
  • base_url ends in /v1. Codex adds /responses itself.
  • env_key names the variable that holds the key. Codex sends it as Authorization: Bearer. Use a DVARA key, not an OpenAI key.
  • wire_api = "responses" makes Codex use the Responses API.

Codex asks OpenAI to search the web for it by default. That search runs at OpenAI, outside DVARA, so DVARA cannot check what it fetches. DVARA refuses a request that asks for it, and Codex shows:

the tool type web_search is not supported on /v1/responses: it runs at the
provider, outside the gateway's checks. In Codex CLI, set web_search = "disabled"
in config.toml.

Set web_search = "disabled" as in the example above.

What happens on each route​

On a route to OpenAI or Azure OpenAI, DVARA sends Codex's request to the provider's own Responses API as Codex sent it. It changes only what governance changes, such as redacted text or the routed model. Codex's encrypted reasoning goes back and forth between turns unchanged, so a long session keeps its reasoning. The answer comes back as the provider sent it. Usage and cost come from the provider's own figures, including cached and reasoning tokens.

On a route to another provider, such as Anthropic or Gemini, DVARA translates the request to that provider's chat API:

  • Codex's own tools, including its patch tool and tool search, become tools the provider understands. Their calls come back in the shape Codex expects.
  • Images in a tool's output reach the model.
  • The answer carries no reasoning. Earlier reasoning from Codex is left out.
  • Settings only OpenAI understands, such as reasoning effort, are left out.

What DVARA refuses​

DVARA refuses with 400 unsupported_capability anything that would run or be stored outside the Gateway, and says what to change:

RefusedWhyWhat to do
Built-in tools: web search, file search, code interpreter, computer use, image generation, remote MCPThey run at the provider, outside DVARA's checksSet web_search = "disabled" in Codex
store: true, previous_response_idThey keep the conversation at the providerCodex's defaults do not send them
A file part in a tool's outputMost providers cannot take one there—

A refusal before the stream starts comes back as a normal HTTP error with a JSON body, so Codex shows the reason.

Known limits​

  • Codex's local actions are not governed. File edits and shell commands run on the developer's machine and never reach DVARA. DVARA sees what Codex sends to the model, including the output of those commands.
  • A cached answer has no reasoning items. If you turn on DVARA's response cache, an answer served from it is built by DVARA.
  • No reasoning on a translated route. Use an OpenAI or Azure OpenAI route if your sessions depend on reasoning.

Where to go next​