KiloClaw is amazing.
A practical field guide for routing KiloClaw/OpenClaw model calls through a ChatGPT Plus/Pro Codex OAuth session instead of a traditional OpenAI API key.
KiloClaw normally makes model calls through configured model providers. The regular openai provider expects an OpenAI API key and bills through the OpenAI API platform.
But OpenAI's Codex CLI can authenticate with a ChatGPT account using OAuth. OpenClaw also has an openai-codex provider that can use those OAuth credentials. If configured correctly, model calls can be routed through the Codex/ChatGPT subscription path instead of through OPENAI_API_KEY.
The key detail is the model prefix:
openai/gpt-5.5 -> regular OpenAI API provider; requires OPENAI_API_KEY
openai-codex/gpt-5.5 -> Codex provider; uses ChatGPT/Codex OAuth
That prefix is the entire trick.
This was tested inside a hosted KiloClaw instance running OpenClaw, with persistent state under /root.
The same approach should apply to other OpenClaw deployments if:
- the
openai-codexprovider is installed/enabled; - the OpenAI Codex CLI can be run on the host;
- OpenClaw stores provider auth profiles in the same OAuth profile format; and
- the selected model id uses the
openai-codex/prefix.
Kilo Chat / OpenClaw session
-> OpenClaw agent runner
-> model id: openai-codex/gpt-5.5
-> provider: openai-codex
-> OAuth profile from auth-profiles.json
-> OpenAI Codex backend using the ChatGPT account subscription
The model selector chooses the provider by parsing the model id at the first slash:
kilocode/anthropic/claude-opus-4.7 -> provider kilocode
openai/gpt-5.5 -> provider openai
openai-codex/gpt-5.5 -> provider openai-codex
If you accidentally use openai/gpt-5.5, OpenClaw will try to use the regular OpenAI API provider and may complain that OPENAI_API_KEY is missing. That does not mean the Codex OAuth profile is bad; it usually means the model prefix is wrong.
Install/run the OpenAI Codex CLI and authenticate with device auth:
npx @openai/codex login --device-authThe CLI prints:
- a URL, usually
https://auth.openai.com/codex/device; - a short device code; and
- a timeout window.
Open the URL on your laptop or phone, sign in with the ChatGPT account whose subscription you want to use, and enter the device code.
After successful login, the Codex CLI writes credentials to:
~/.codex/auth.json
The file has a shape like this:
{
"auth_mode": "chatgpt",
"OPENAI_API_KEY": null,
"tokens": {
"id_token": "...",
"access_token": "...",
"refresh_token": "...",
"account_id": "..."
},
"last_refresh": "..."
}Do not publish this file. It contains live credentials.
OpenClaw's provider auth profiles live in an auth-profiles.json file. In the KiloClaw instance tested here, the file was:
/root/.openclaw/agents/main/agent/auth-profiles.json
Other deployments may use a different agent profile path, but the structure is the important part.
The openai-codex OAuth profile should look like this:
{
"version": 1,
"profiles": {
"openai-codex:user@example.com": {
"type": "oauth",
"provider": "openai-codex",
"access": "<access_token>",
"refresh": "<refresh_token>",
"expires": 1779550231000,
"email": "user@example.com"
}
},
"order": {
"openai-codex": ["openai-codex:user@example.com"]
},
"lastGood": {
"openai-codex": "openai-codex:user@example.com"
}
}Here is a reusable injection script. Review it before running; it modifies your OpenClaw auth profile file.
#!/usr/bin/env python3
import base64
import json
from pathlib import Path
codex_auth_path = Path.home() / ".codex" / "auth.json"
openclaw_auth_path = Path("/root/.openclaw/agents/main/agent/auth-profiles.json")
codex = json.loads(codex_auth_path.read_text())
tokens = codex["tokens"]
def decode_jwt_payload(jwt: str) -> dict:
payload = jwt.split(".")[1]
payload += "=" * (-len(payload) % 4)
return json.loads(base64.urlsafe_b64decode(payload))
access_payload = decode_jwt_payload(tokens["access_token"])
id_payload = decode_jwt_payload(tokens["id_token"])
email = id_payload["email"]
expires_ms = access_payload["exp"] * 1000
profile_id = f"openai-codex:{email}"
if openclaw_auth_path.exists():
auth_profiles = json.loads(openclaw_auth_path.read_text())
else:
auth_profiles = {"version": 1, "profiles": {}, "order": {}, "lastGood": {}}
auth_profiles.setdefault("version", 1)
auth_profiles.setdefault("profiles", {})[profile_id] = {
"type": "oauth",
"provider": "openai-codex",
"access": tokens["access_token"],
"refresh": tokens["refresh_token"],
"expires": expires_ms,
"email": email,
}
auth_profiles.setdefault("order", {})["openai-codex"] = [profile_id]
auth_profiles.setdefault("lastGood", {})["openai-codex"] = profile_id
openclaw_auth_path.parent.mkdir(parents=True, exist_ok=True)
openclaw_auth_path.write_text(json.dumps(auth_profiles, indent=2) + "\n")
print(f"Wrote OpenClaw OAuth profile: {profile_id}")If your OpenClaw auth profile path differs, change openclaw_auth_path before running.
Set the default model using the Codex provider prefix:
openclaw models set openai-codex/gpt-5.5Do not use this if your goal is ChatGPT subscription routing:
openclaw models set openai/gpt-5.5That routes to the regular OpenAI API provider.
Depending on the OpenClaw version/provider build, available Codex-routed model ids may include names like:
gpt-5.5
gpt-5.5-pro
gpt-5.4
gpt-5.4-pro
gpt-5.4-mini
gpt-5.3-codex
gpt-5.3
Use the full model id with the provider prefix, for example:
openai-codex/gpt-5.5
Run:
openclaw models statusYou want to see something equivalent to:
Default: openai-codex/gpt-5.5
Providers with OAuth/tokens: openai-codex
OAuth profile: openai-codex:user@example.com ok
Inside a live KiloClaw/OpenClaw chat session, /status should show the model and auth source, e.g.:
Model: openai-codex/gpt-5.5
Auth : oauth (openai-codex:user@example.com)
If an existing chat session was created before you changed the default model, it may stay pinned to the old model. Start a fresh session or switch the current one explicitly:
/model openai-codex/gpt-5.5
This setup survives ordinary restarts if the relevant files live on persistent storage.
In the tested KiloClaw environment, the important files were:
/root/.openclaw/openclaw.json
/root/.openclaw/agents/main/agent/auth-profiles.json
/root/.codex/auth.json
The default model is stored in openclaw.json; the OAuth profile is stored in auth-profiles.json; and the Codex CLI credentials remain in ~/.codex/auth.json.
On KiloClaw, /root is backed by the instance's persistent volume, so ordinary OpenClaw restarts, machine restarts, and redeploys should preserve the setup.
Codex OAuth access tokens expire. The auth profile includes a refresh token, and OpenClaw should use it to refresh the access token automatically.
If refresh fails because OpenAI rotated or revoked the refresh token, repeat:
npx @openai/codex login --device-authThen rerun the injection script.
Most likely cause: the model is set to openai/... instead of openai-codex/....
Fix:
openclaw models set openai-codex/gpt-5.5Existing sessions can be pinned to their original model.
Fix:
/model openai-codex/gpt-5.5
Or start a new chat/session.
Some hosted dashboards treat the dashboard settings as source-of-truth for the primary model. If you change models there, it may overwrite your CLI-set default.
Fix: rerun:
openclaw models set openai-codex/gpt-5.5Then verify with:
openclaw models statusCheck all of the following:
- the model id starts with
openai-codex/; - the profile's
providerfield isopenai-codex; - the profile includes both
accessandrefreshfields; expiresis epoch milliseconds, not seconds; and- the OpenClaw process can read the auth profile file for the active agent.
- Do not publish
~/.codex/auth.json. - Do not publish
auth-profiles.jsonwith realaccessorrefreshtokens. - Treat Codex OAuth refresh tokens like passwords.
- If writing a public guide, replace real emails with
user@example.comand redact all tokens.
# Authenticate with the ChatGPT account
npx @openai/codex login --device-auth
# Copy ~/.codex/auth.json tokens into OpenClaw's openai-codex OAuth profile
python3 inject-codex-oauth-into-openclaw.py
# Select the Codex provider, not the regular OpenAI provider
openclaw models set openai-codex/gpt-5.5
# Verify
openclaw models statusIf you remember only one thing, remember this:
openai-codex/gpt-5.5 uses ChatGPT/Codex OAuth.
openai/gpt-5.5 uses the regular OpenAI API provider.