Connect Codex to DIAL
In this tutorial you point Codex, the command-line coding agent, at DIAL and watch a DIAL-hosted model reply. Codex speaks only the OpenAI Responses API, so how it reaches DIAL depends on your deployment: one that exposes the Responses API natively connects directly, while a Chat-Completions-only deployment needs a small translating proxy. Step 1 shows which case you are in. This tutorial is for developers who already have a DIAL host, a DIAL API key, and Codex installed.
Prerequisites
- A DIAL host and API key. See Before you begin.
- Codex installed.
- For the proxy path only: Docker and git.
What you'll build
A working connection from Codex to DIAL. By the end, codex exec sends a prompt and prints the model's reply, routed through your DIAL deployment with DIAL's roles, quotas, and cost tracking applied.
Step 1: Find out which path your deployment needs
Ask DIAL for the deployment's metadata and read the responses_api flag:
curl -s -H "Api-Key: <DIAL_API_KEY>" \
"https://<YOUR_DIAL_HOST>/openai/deployments/gpt-5.4-2026-03-05" \
| grep -o '"responses_api":[^,]*'
On Windows (PowerShell), call curl.exe — PowerShell's curl is an Invoke-WebRequest alias — and pipe to findstr:
curl.exe -s -H "Api-Key: <DIAL_API_KEY>" `
"https://<YOUR_DIAL_HOST>/openai/deployments/gpt-5.4-2026-03-05" | findstr responses_api
If curl is unavailable, Invoke-RestMethod reads the flag directly and prints True or False:
(Invoke-RestMethod -Headers @{ "Api-Key" = "<DIAL_API_KEY>" } `
"https://<YOUR_DIAL_HOST>/openai/deployments/gpt-5.4-2026-03-05").features.responses_api
Verify:
"responses_api":true— follow The direct path and ignore the proxy."responses_api":false— your deployment is chat-only; follow The proxy path.
The responses_api flag only means anything on DIAL v0.45+ (see Check your DIAL version); on older DIAL every deployment is chat-only, so take the proxy path. Even on v0.45+, many deployments are still chat-only, so check the flag rather than assume. You can also test it functionally: a POST to https://<YOUR_DIAL_HOST>/openai/v1/responses returns 200 on a Responses-capable deployment and 503 on a chat-only one.
The direct path
Follow this path when Step 1 reported responses_api: true.
Step 2: Tell Codex about DIAL
Open ~/.codex/config.toml (on Windows, %USERPROFILE%\.codex\config.toml; create it if it does not exist) and paste the following. The model_provider and model_providers keys only take effect in this user-level file.
model = "gpt-5.4-2026-03-05" # the DIAL deployment id; Codex sends it to DIAL as the model
model_provider = "dial"
disable_response_storage = true # DIAL doesn't store responses, so this must be on
[model_providers.dial]
name = "DIAL (direct)"
base_url = "https://<YOUR_DIAL_HOST>/openai/v1" # Codex appends /responses
wire_api = "responses" # the only valid value — Codex's old "chat" wire was removed
env_key = "DIAL_API_KEY"
env_http_headers = { "Api-Key" = "DIAL_API_KEY" } # DIAL authenticates on Api-Key
requires_openai_auth = false # don't enforce the sk- prefix check
query_params = { api-version = "2025-04-01-preview" } # Azure-backed deployments require this
Note
Put the
api-versioninquery_params, not inbase_url. Codex appends/responsestobase_url, so a query string there lands in the wrong place. Drop thequery_paramsline if your DIAL host does not require an Azure API version — see Azure-backed deployment settings.
Step 3: Set your API key
Bash or Zsh:
export DIAL_API_KEY="<DIAL_API_KEY>"
PowerShell:
$env:DIAL_API_KEY = "<DIAL_API_KEY>"
Step 4: Check the wiring
codex doctor
Verify:
Your config loads cleanly and a row appears for the dial provider — config.toml parse ok, auth ✓ with provider auth env var DIAL_API_KEY (present), and wire API responses. The model line names your deployment, for example gpt-5.4-2026-03-05 · dial.
Step 5: Run Codex
codex exec "Reply with exactly: PONG"
Verify:
You see PONG printed back, routed Codex → DIAL with no proxy in between. Run plain codex for the interactive session you will use day to day.
The direct path is complete. Skip to What you learned.
The proxy path
Follow this path when Step 1 reported responses_api: false. Put a small translating proxy between Codex and DIAL. The proxy (responses-proxy) converts Codex's Responses calls into the Chat Completions calls DIAL understands and forwards your Api-Key header to DIAL.
Step 2: Build and run the proxy
There is no published image, so build it from the repo — a one-time Rust build:
git clone https://github.com/chutesai/responses-proxy && cd responses-proxy
Warning
Do not use the project's
install_codex.shone-liner for DIAL. It installs chutes' own fork of Codex and points it at their hosted proxy (responses.chutes.ai, whose backend is chutes — not DIAL), and the config it writes omits bothdisable_response_storageand theApi-Keyheader DIAL needs. Build and run the proxy yourself, as below.
Point the proxy's BACKEND_URL at your DIAL chat deployment — the deployment id lives in the URL. If your DIAL's Chat Completions endpoint requires an Azure API version, append ?api-version=2025-04-01-preview to BACKEND_URL (see Azure-backed deployment settings). Start it either way:
# Option A — Docker Compose (the maintainers' path). --build compiles the image;
# naming the service skips the bundled Caddy/TLS sidecar you don't need locally.
BACKEND_URL="https://<YOUR_DIAL_HOST>/openai/deployments/gpt-5.4-2026-03-05/chat/completions" \
docker compose up --build openai-responses-proxy
# Option B — plain Docker (build once, then run).
docker build -t responses-proxy .
docker run -d --name responses-proxy -p 8282:8282 \
-e BACKEND_URL="https://<YOUR_DIAL_HOST>/openai/deployments/gpt-5.4-2026-03-05/chat/completions" \
responses-proxy
On Windows (PowerShell), the inline VAR=… command form and the \ line-continuation do not work. Set the variable with $env: first and use a backtick to continue lines:
$env:BACKEND_URL = "https://<YOUR_DIAL_HOST>/openai/deployments/gpt-5.4-2026-03-05/chat/completions"
docker compose up --build openai-responses-proxy # Option A
# or, after `docker build -t responses-proxy .` :
docker run -d --name responses-proxy -p 8282:8282 `
-e BACKEND_URL="$env:BACKEND_URL" responses-proxy # Option B
The proxy now listens on http://0.0.0.0:8282. Confirm it is up:
curl -s -o /dev/null -w "%{http_code}\n" http://0.0.0.0:8282/health
On Windows, use curl.exe, or Invoke-WebRequest if curl is unavailable:
curl.exe -s -o NUL -w "%{http_code}`n" http://0.0.0.0:8282/health
(Invoke-WebRequest -UseBasicParsing http://0.0.0.0:8282/health).StatusCode
Verify: you see 200.
Step 3: Tell Codex about the proxy
Open ~/.codex/config.toml (on Windows, %USERPROFILE%\.codex\config.toml; create it if it does not exist) and paste the following. The model_provider and model_providers keys only take effect in this user-level file.
model = "gpt-5.4" # the DIAL deployment id you set in BACKEND_URL above
model_provider = "dial"
disable_response_storage = true # DIAL doesn't store responses, so this must be on
[model_providers.dial]
name = "DIAL (via responses-proxy)"
base_url = "http://0.0.0.0:8282/v1" # the proxy; Codex appends /responses
wire_api = "responses" # the only valid value — Codex's old "chat" wire was removed
env_key = "DIAL_API_KEY"
env_http_headers = { "Api-Key" = "DIAL_API_KEY" } # forwarded through the proxy to DIAL
requires_openai_auth = false # don't enforce the sk- prefix check
Step 4: Set your API key
Bash or Zsh:
export DIAL_API_KEY="<DIAL_API_KEY>"
PowerShell:
$env:DIAL_API_KEY = "<DIAL_API_KEY>"
Step 5: Check the wiring
Before running a real prompt, ask Codex to inspect its own setup:
codex doctor
Verify:
Your config loads cleanly and a row appears for the dial provider — config.toml parse ok, auth ✓ with provider auth env var DIAL_API_KEY (present), and wire API responses. The model line names your deployment, for example gpt-5.4 · dial.
Step 6: Run Codex
codex exec "Reply with exactly: PONG"
Verify:
You see PONG printed back, routed Codex → proxy → DIAL. Run plain codex for the interactive session you will use day to day.
What you learned
- How to read a deployment's
responses_apiflag to choose the direct or proxy path. - How to register DIAL as a Codex
model_providerand authenticate with theApi-Keyheader. - Why
disable_response_storage = trueis required on both paths — DIAL does not store responses or supportprevious_response_id, so without it Codex breaks after the first turn.
Good to know
- Which path you need depends on the deployment. Re-run the Step 1 check for any new deployment — the flag can differ even between versions of the same model family.
- Codex sends the key as an
Authorization: Bearertoken; theenv_http_headersline is what makes it also send theApi-Keyheader that DIAL authenticates on. On the proxy path, the proxy forwards it. - On the proxy path, mind the proxy's own limits: only
functiontools are forwarded, file inputs must be inlined, and no session state is kept.
Next steps
- Connect Claude Code to DIAL — another command-line agent, with no proxy needed
- Agentic tools overview — shared prerequisites and the other tools
- Unified API reference — the API DIAL exposes