#OpenClaw 2026.5.12: Codex app-server fails OpenAI OAuth refresh after fresh openai-codex login
1 messages · Page 1 of 1 (latest)
Observed behavior:
-
Run:
openclaw models auth --agent ember login --provider openai-codex -
OAuth completes successfully:
Auth profile: openai-codex:<email> (openai-codex/oauth) -
Verify:
openclaw models auth --agent ember list
openclaw models status --agent ember --json --checkOpenClaw reports the profile as valid. In our case it expires 2026-05-
-
Send a message routed to Ember.
-
The turn fails with:
OAuth token refresh failed for openai-codex:
OpenAI Codex token refresh failed (401):
{
"error": {
"message": "Could not validate your token. Please try signing in
again.",
"type": "invalid_request_error",
"code": "token_expired"
}
}
Route/log context:
- Failing session key: agent:ember:direct:shravan
- Harness selected:
provider=openai
modelId=gpt-5.5
selectedHarnessId=codex
runtime=codex - Discord/TUI surfaces:
"Model login expired on the gateway for openai-codex. Re-auth with
openclaw models auth login --provider openai-codex, then try again."
Disk/auth shape:
-
Fresh 2026.5.12 Ember login writes an oauthRef-style profile:
hasAccess=false
hasRefresh=false
hasOauthRef=true
expires=2026-05-26T15:09:22.318Z -
The token material appears to live in:
$OPENCLAW_HOME/.openclaw/state/credentials/auth-profiles/<id>.json
What we have not proven yet:
- We have not proven that pi-ai receives refresh_token=undefined.
- We have not proven whether the app-server refresh path receives:
- an unhydrated oauthRef-only credential,
- a hydrated but rejected refresh token,
- the wrong/stale auth profile from session binding.
Question:
Could maintainers confirm the intended 2026.5.12 Codex app-server refresh
path for oauthRef-backed openai-codex profiles?
The key thing we need to know is whether refreshCodexAppServerAuthTokens
should log or guarantee the following before calling pi-ai/openai-codex
refresh:
- profileId
- agentDir / ownerAgentDir
- credential source
- hasAccess
- hasRefresh
- hasOauthRef
- oauthRef.id
- expires
No token values needed, only booleans/metadata.
Expected behavior:
After fresh openclaw models auth --agent ember login --provider openai- codex, the next Codex app-server turn should use the valid oauthRef-
backed profile and not fail with token_expired.
Current workaround under consideration:
Rollback the gateway image to the last known-good OpenClaw 2026.5.7 stack
for uptime, while keeping this as a 2026.5.12 investigation.
I checked current docs/source for this. Since you’re already on 2026.5.12, the important clue is that this release explicitly includes Codex app-server OAuth fixes around oauthRef profiles and refresh invalidation. So I’d split this into “is the profile valid in the same VM/agent scope?” vs “app-server is still using stale/bad state.”
On the agent-vm gateway VM, as the same OS user that runs the gateway, can you run:
openclaw models status --probe --probe-provider openai-codex --agent main
openclaw plugins list | rg "codex|app-server|openai"
openclaw logs --since 30m | rg "OAuth token refresh failed|Token refresh failed|openai-codex|codex app-server|invalid_grant|refresh_token_reused|entitlement|usage"
Don’t paste tokens, but the exact redacted failure line matters.
What I’d try immediately:
openclaw models auth login --provider openai-codex --set-default
openclaw gateway restart
Then start a fresh session/thread before testing again. If the probe is OK but app-server turns still fail, that points away from “bad OAuth login” and toward Codex app-server state/routing. In that case, please file a GitHub issue with openclaw status --all plus those redacted log lines: https://github.com/openclaw/openclaw/issues
Relevant docs:
https://docs.openclaw.ai/help/faq
https://docs.openclaw.ai/help/faq-models
https://docs.openclaw.ai/cli/models
That error is more specific: --check is only checking stored profile health/expiry metadata. It does not prove the live Codex refresh exchange will succeed. The live check is:
openclaw models status --agent ember --probe --probe-provider openai-codex --probe-profile "openai-codex:<email>" --json
Two things I’d verify next:
-
In the Ember thread/session, send
/model status. It should show the agent, the exactauth-profiles.jsonpath, and the auth profile being tried. This catches “valid profile exists, but the routed session is using another agent/store/profile.” -
Be careful with this command shape:
openclaw models auth --agent ember login --provider openai-codex
In current source/docs, models auth --agent is only documented/used for auth order get|set|clear, while auth login resolves the configured default agent’s auth store. So it may not be logging into Ember’s auth store even though the flag is accepted at the parent command. That’s a CLI UX footgun.
For a clean test, after re-auth:
openclaw gateway restart
then use a fresh Ember session/thread. Existing Codex app-server threads can hold stale auth/runtime state.
If /model status proves Ember is using ~/.openclaw/agents/ember/agent/auth-profiles.json, and the live --probe still returns the same token_expired 401 immediately after login, that’s issue-worthy. Include the redacted --probe output and the OAuth token refresh failed... log line here: https://github.com/openclaw/openclaw/issues
Docs I’m grounding this on:
https://docs.openclaw.ai/cli/models
https://docs.openclaw.ai/concepts/model-failover
https://docs.openclaw.ai/help/faq
I can’t speak for maintainers, but from the installed 2026.5.12 code path, the intended behavior appears to be:
account/chatgptAuthTokens/refresh → refreshCodexAppServerAuthTokens(... forceOAuthRefresh=true) → resolve selected openai-codex profile → resolvePersistedAuthProfileOwnerAgentDir({ agentDir, profileId }) → load the persisted owner store → for persisted OAuth creds, temporarily write expires: 0 → resolveApiKeyForProfile(... ownerAgentDir ...).
That last step should be the point where an oauthRef-only profile gets hydrated from the secret material under credentials/auth-profiles/<id>.json. So yes: an oauthRef-backed profile with hasAccess=false and hasRefresh=false in auth-profiles.json is expected and should still be usable if the ref payload is valid and the app-server refresh path is resolving the right owner agent dir/profile.
Your proposed metadata is exactly the right diagnostic surface, with one addition: log whether resolveApiKeyForProfile returned an access token after oauthRef hydration, as a boolean only. I’d want:
profileId
agentDir
ownerAgentDir
credential source: persisted | overlaid | passed
hasAccess
hasRefresh
hasOauthRef
oauthRef.id
expires
resolvedAccessAfterHydration: boolean
Given your session key is agent:ember:direct:shravan and harness routing is openai/gpt-5.5 -> codex, this is now issue-grade. I’d file it with exactly this data plus the redacted 401. The key question for maintainers is: “Can the app-server refresh callback prove it is hydrating the Ember oauthRef secret before pi-ai/openai-codex refresh?”
Rollback to 2026.5.7 for uptime sounds reasonable while keeping 2026.5.12 as the repro branch. For the issue: https://github.com/openclaw/openclaw/issues
We can verify this concretely with three checks inside the gateway VM:
-
Confirm managed Codex binary exists:
find /pnpm/global/5/.pnpm -path '*/node_modules/@openai/codex/
package.json' -print
node /pnpm/global/5/.pnpm/@openai+codex@0.130.0/node_modules/@openai/
codex/bin/codex.js --version -
Confirm OpenClaw-managed CODEX_HOME behavior:
openclaw agents list
find /home/openclaw/.openclaw/state/agents -maxdepth 3 -type d -name
codex-home -print -
Confirm actual runtime failure:
rg 'codex app-server startup timed out|OAuth token refresh failed|
bubblewrap|agent harness selected'
~/.agent-vm/runtime/zones/sunfam/logs/openclaw-2026-05-16.log
What I expect:
codexmay be absent from shell PATH; that alone is not a bug./home/openclaw/.codexmay be absent; that alone is not a bug.- The managed
@openai/codexbinary should exist under pnpm global. - OpenClaw should create/use per-agent
<agentDir>/codex-home. - If app-server still times out and OAuth refresh still returns 401, then
the issue is not just missing binary setup.
Yep, that verification plan is sound.
Two small tweaks I’d make so it survives layout/version drift:
find /pnpm/global/5/.pnpm -path '*/node_modules/@openai/codex/package.json' -print
find /pnpm/global/5/.pnpm -path '*/node_modules/@openai/codex/bin/codex.js' -print -exec node {} --version \;
or, if openclaw itself can resolve packages in that image:
node -e 'const r=require("module").createRequire(process.cwd()+"/x.js"); console.log(r.resolve("@openai/codex/package.json"))'
Your expectations match the 2026.5.12 code/changelog:
- shell
codexmissing fromPATHis not enough to explain this
/home/openclaw/.codexmissing is not enough to explain this- app-server stdio should use per-agent
<agentDir>/codex-home - OpenClaw resolves the managed
@openai/codexpackage bin directly; it does not require a globalcodexshim
I’d also add one route check:
openclaw models status --agent ember --probe --probe-provider openai-codex --json
openclaw models auth order get --agent ember --provider openai-codex
If the managed binary exists, codex-home exists/gets created, and the logs still show both app-server timeout and OAuth token refresh failed ... token_expired, then I agree this is not “missing Codex binary setup.” It’s either startup + auth callback interaction, wrong owner/profile resolution, or oauthRef hydration/refresh behavior.
In openclaw 2026.5.12 a fresh openclaw models auth login --provider openai-codex writes the OAuth profile in the new SecretRef format
(auth-profiles.json has oauthRef only, no inline access or
refresh). On the codex app-server refresh path, the credential
appears to be handed to pi-ai's openai-codex provider without first
being hydrated through resolvePersistedOAuthSecrets. pi-ai's
refreshToken reads credentials.refresh directly, so for SecretRef-
only profiles it sends refresh_token=undefined to auth.openai.com
and gets 401 token_expired.
Source pointers:
extensions/codex/src/app-server/auth-bridge.ts L452-L494
resolveOAuthCredentialForCodexAppServer takes the `forceRefresh
&& !persistedOAuthCredential && overlaidOAuthCredential` branch
and passes the un-hydrated credential to
refreshOAuthCredentialForRuntime.
src/agents/auth-profiles/oauth.ts L140
refreshOAuthCredential does not call resolvePersistedOAuthSecrets
before delegating to @earendil-works/pi-ai getOAuthApiKey.
@earendil-works/pi-ai@0.74.0 dist/utils/oauth/openai-codex.js L378
refreshToken reads credentials.refresh directly.
Questions:
1. Is this a known regression? If yes, what's the target fix
release?
2. Is there a config flag to keep new logins writing inline
access/refresh instead of oauthRef?
3. Is the right workaround to pnpm-patch openclaw to hydrate the
credential in refreshOAuthCredential, or is there a supported
entry point we should use that already does the hydration?
4. Does agentRuntime.id: "pi" on the openai provider bypass the
codex auth-bridge entirely and would that be the recommended
short-term workaround instead of rolling back to 2026.5.7?
Also reporting separately: in the same auth-bridge code path,
`forceOAuthRefresh: true` is set unconditionally on every codex
app-server `account/login/start` call, which means even a freshly-
issued token gets refreshed before first use. Intentional?
I checked the installed 2026.5.12 artifact, and this lines up with what I’m seeing.
The suspicious branch is real:
shared-client-3aMgN5po.js
292 if (forceRefresh && !persistedOAuthCredential && overlaidOAuthCredential)
293 refreshOAuthCredentialForRuntime({ credential: overlaidOAuthCredential })
And refreshOAuthCredential does pass the credential object through to provider refresh without doing SecretRef hydration first:
oauth.ts
153 getOAuthApiKey(oauthProvider, { [credential.provider]: credential })
So if overlaidOAuthCredential is oauthRef-only, then yes, the provider-side refresh path can plausibly see no inline refresh. That explains the fresh-login token_expired symptom much better than missing Codex binary/PATH.
One nuance: if persistedOAuthCredential is found in the owner store, the code takes the later resolveApiKeyForProfile(... ownerAgentDir ...) path, which should hydrate oauthRef. So the most useful maintainer repro is to show that app-server refresh is landing in the !persistedOAuthCredential && overlaidOAuthCredential branch for agent:ember:direct:shravan.
I’d file this as a bug with the branch analysis and redacted 401. Suggested title:
2026.5.12 Codex app-server refresh passes oauthRef-only openai-codex credential to provider without SecretRef hydration
Suggested expected fix direction: hydrate/resolve oauthRef material before refreshOAuthCredentialForRuntime, or avoid that early branch and route forced refresh through the owner-store resolveApiKeyForProfile path consistently.
Short answers, with caveats:
-
There is now a matching GitHub issue: https://github.com/openclaw/openclaw/issues/81941. I don’t see a maintainer-confirmed target release yet, so I wouldn’t promise one.
-
I don’t see a documented config flag to force fresh OAuth logins back to inline
access/refresh. Also, thisoauthRefis OpenClaw’s internal OAuth secret storage shape, not the user-facing static SecretRef config path, so the normal SecretRef knobs don’t look applicable. -
I would not patch
refreshOAuthCredentialglobally as the first choice: that function only receives a credential, notprofileId/agentDir, so it is the wrong layer to reliably hydrate owner-scoped oauthRef material. The supported hydrated path appears to beresolveApiKeyForProfile({ store, profileId, agentDir: ownerAgentDir }). For a local pnpm patch, I’d patch the Codex auth-bridge path: either remove/avoid the earlyforceRefresh && !persistedOAuthCredential && overlaidOAuthCredentialbranch, or hydrate before callingrefreshOAuthCredentialForRuntime. -
agentRuntime.id: "pi"onopenai/gpt-5.5is probably not the right workaround. Docs distinguish:
openai-codex/gpt-5.5= Codex OAuth through PIopenai/gpt-5.5+embeddedHarness.runtime: "codex"= native Codex app-server- direct
openai/gpt-5.5API-key route is only for when OpenAI enables it on the API
So the short-term workaround I’d try before rollback is switching Ember to openai-codex/gpt-5.5 through PI, then start a fresh session. If you specifically need the native Codex app-server harness, rollback to 2026.5.7 may be cleaner for uptime.
On the last point: in the installed code I checked, forceOAuthRefresh: true is set in refreshCodexAppServerAuthTokens, which handles the app-server’s account/chatgptAuthTokens/refresh request. I don’t see it being set directly on the initial account/login/start call. Practically, the app-server may request refresh immediately after login/start, but the
unconditional flag is on the refresh callback path, not the login/start call itself.
Confirmed:
-
Managed Codex binary exists in the VM:
/pnpm/global/5/.pnpm/@openai+codex@0.130.0/node_modules/@openai/codex/
bin/codex.js
-> codex-cli 0.130.0 -
Per-agent Codex homes exist:
/home/openclaw/.openclaw/state/agents/ember/agent/codex-home
/home/openclaw/.openclaw/state/agents/shravan/agent/codex-home
/home/openclaw/.openclaw/state/agents/alevtina/agent/codex-home -
Ember auth order check:
Agent: ember
Provider: openai-codex
Auth state file: $OPENCLAW_HOME/.openclaw/state/agents/ember/agent/
auth-state.json
Order override: (none) -
Probe did not complete:
openclaw models status --agent ember --probe --probe-provider openai-
codex --json
timed out after 20s -
Logs still show:
- agent harness selected: agentId=ember, provider=openai-codex,
selectedHarnessId=codex - codex app-server stderr: bubblewrap missing, using bundled bubblewrap
- codex app-server startup timed out
- OAuth token refresh failed for openai-codex: 401 token_expired
- agent harness selected: agentId=ember, provider=openai-codex,
So this is now verified as not just “missing codex binary” or “missing /
home/openclaw/.codex”.
The remaining suspect area is exactly what you said:
Can the app-server refresh callback prove it is resolving Ember’s selected
openai-codex profile, resolving the correct ownerAgentDir, hydrating the
oauthRef secret, and handing a real refresh token/access token to the
Codex refresh layer?
The diagnostic fields I’d want upstream are:
profileId
agentDir
ownerAgentDir
credential source: persisted | overlaid | passed
hasAccess
hasRefresh
hasOauthRef
oauthRef.id
expires
resolvedAccessAfterHydration: boolean
resolvedRefreshAfterHydration: boolean
That’s a good narrowed repro. At this point I’d attach this exact confirmation to #81941: https://github.com/openclaw/openclaw/issues/81941
The --probe timeout is also signal, not noise. It means the auth/provider live path is hanging or blocked before it can give a clean ok/auth result, while the actual routed app-server turn then fails with the 401. So I’d include both:
models status --checksays profile metadata is healthymodels status --probe ...times out- app-server turn fails
token_expired
I agree the remaining question is no longer binary/home setup. The upstream diagnostic should prove, in the app-server refresh callback, whether the credential is:
profileId
agentDir
ownerAgentDir
source: persisted | overlaid | passed
hasAccess
hasRefresh
hasOauthRef
oauthRef.id
expires
resolvedAccessAfterHydration
resolvedRefreshAfterHydration
And specifically: if the path takes the forceRefresh && !persistedOAuthCredential && overlaidOAuthCredential branch, does that credential get oauthRef material hydrated before it reaches the OpenAI Codex provider refresh code? From the 2026.5.12 artifact, that is the suspicious gap.
› what openclaw command is tere to rest all the auths
i ahve 3 agetns no defaults
There isn’t a clean “reset every auth for every agent” command that I’d recommend using casually.
For one model provider on the default agent, the command is:
openclaw infer model auth logout --provider openai-codex
Then log in again:
openclaw models auth login --provider openai-codex
Docs: https://docs.openclaw.ai/cli/infer
Important caveat for your Ember case: that logout helper targets the configured default agent’s auth store. It does not look like it has a --agent ember flag. Ember’s model auth lives under:
~/.openclaw/agents/ember/agent/auth-profiles.json
~/.openclaw/agents/ember/agent/auth-state.json
~/.openclaw/credentials/auth-profiles/
So for “reset Ember auth completely”, I’d first make a backup, then move the Ember auth files aside rather than deleting them. Also restart the gateway after changing auth files. Don’t use openclaw reset --scope full unless you really want to wipe much more than auth.
Got it. With multiple agents and no meaningful default, don’t use the default-agent auth logout as your main reset tool.
For each agent, auth is per-agent here:
$OPENCLAW_HOME/.openclaw/state/agents/<agentId>/agent/auth-profiles.json
$OPENCLAW_HOME/.openclaw/state/agents/<agentId>/agent/auth-state.json
So for your three agents, do a recoverable move-aside, not delete:
ts=$(date +%Y%m%d-%H%M%S)
for agent in ember shravan alevtina; do
dir="$OPENCLAW_HOME/.openclaw/state/agents/$agent/agent"
[ -f "$dir/auth-profiles.json" ] && mv "$dir/auth-profiles.json" "$dir/auth-profiles.json.bak-$ts"
[ -f "$dir/auth-state.json" ] && mv "$dir/auth-state.json" "$dir/auth-state.json.bak-$ts"
done
openclaw gateway restart
Then re-login for the agent you want to test first. If OPENCLAW_HOME isn’t set in your shell, replace it with the actual home root you showed, likely /home/openclaw. Keep the backups until the new login is confirmed working.
i restarted afte rremove all alut so only codex home auth is there stills aem isseu ⚠️ Model login expired on the gateway for openai-codex. Re-auth with openclaw models auth login --provider openai-codex, then try again.
why openai-cdoex i dont udnertand
Yeah, then I’d stop spending time on “clean auth state” as the fix. You’ve now tested the important thing: removing OpenClaw auth profiles and restarting still leaves the Codex app-server path producing the same openai-codex refresh-expired error.
One important distinction: Codex home auth and OpenClaw model auth are not interchangeable in every path. codex-home can prove the managed Codex CLI/app-server has login material, but the failing OpenClaw bridge is still doing an openai-codex refresh handoff and hitting the same bug.
Practical next step for uptime:
- If you can live without native Codex app-server: switch the session/model route to
openai-codex/gpt-5.5through PI, then start a fresh session. - If you need native Codex app-server specifically: rollback to the last known-good 2026.5.7 image for now.
Don’t keep re-running OAuth login; this no longer looks like operator auth setup. Please add this latest “removed OpenClaw auth, only codex-home auth remains, same failure” note to #81941: https://github.com/openclaw/openclaw/issues/81941
Totally fair confusion.
openai and openai-codex are different pieces in OpenClaw:
openai/gpt-5.5is the model name you selected.codexis the app-server harness/runtime used to run that model.openai-codexis the auth provider OpenClaw uses for ChatGPT/Codex subscription OAuth.
So even though the model route says openai/gpt-5.5, the Codex app-server still needs ChatGPT/Codex subscription auth. In OpenClaw that auth profile is called openai-codex.
That’s why the error says:
Model login expired on the gateway for openai-codex
It does not mean you manually chose the wrong provider. It means the openai/gpt-5.5 -> codex runtime -> ChatGPT/Codex OAuth chain is failing at the auth bridge.
the default profile hade hauth taht cause dthe problem. that took waty too long to debug. so teh issue i wan to udnertand is how the hell to log o9nly itno teh new codex runtiem ask that was the soruces of the probemm
Yeah, that’s frustrating. I should have pushed harder on “which profile is actually selected” earlier.
The source of the problem is: with no auth order override, OpenClaw auto-picks an openai-codex auth profile for the agent/runtime. If a stale/bad default profile exists, the Codex runtime can get dragged through that instead of the auth you thought you were using.
There are two different logins:
- OpenClaw model auth profile login:
OPENCLAW_AGENT_DIR=/home/openclaw/.openclaw/state/agents/ember/agent \
openclaw models auth login --provider openai-codex
Then pin that exact profile for Ember:
openclaw models auth order set --agent ember --provider openai-codex 'openai-codex:<email-or-profile-id>'
- Native Codex runtime/CODEX_HOME login:
CODEX_HOME=/home/openclaw/.openclaw/state/agents/ember/agent/codex-home \
node /pnpm/global/5/.pnpm/@openai+codex@0.130.0/node_modules/@openai/codex/bin/codex.js login
Verify:
CODEX_HOME=/home/openclaw/.openclaw/state/agents/ember/agent/codex-home \
node /pnpm/global/5/.pnpm/@openai+codex@0.130.0/node_modules/@openai/codex/bin/codex.js login status
The annoying part: I don’t see a nice supported OpenClaw command that means “for this agent, use only native Codex CODEX_HOME auth and ignore all openai-codex auth profiles” for normal routed agent turns. So today the safe path is either:
- keep exactly one good
openai-codexprofile per agent and pin it withauth order set, or - remove stale
openai-codexprofiles so the default one cannot be selected.
That missing “native Codex auth only” switch is worth adding to #81941 too.
so why the hell did they release this udpate to force the codcex runtiem?s
I get why it feels like that. From the docs/changelog, the intent was not “break everyone onto Codex runtime”; it was to make the new native Codex app-server route the correct path for openai/gpt-5.5, while keeping openai-codex/gpt-5.5 as the PI/OAuth route.
The painful part is the migration/repair behavior: old or mixed configs can get rewritten or resolved toward:
openai/gpt-5.5 + codex runtime
instead of:
openai-codex/gpt-5.5 through PI
That is a big blast-radius change when auth profiles are stale or multi-agent. Your setup exposed the worst version of it: default/stale openai-codex auth + new Codex runtime bridge + no obvious “use only CODEX_HOME native auth” switch.
For uptime, I’d explicitly pin away from the new app-server path until the bug is fixed:
openclaw config set agents.defaults.model.primary openai-codex/gpt-5.5
and remove/override any embeddedHarness.runtime: "codex" / model-scoped agentRuntime.id: "codex" for that agent, then start a fresh session. If that config keeps getting repaired back, rollback is the saner operational move.
Yep, that post is exactly why your confusion is justified.
It says the “done right” path is:
openclaw models auth login --provider openai
openclaw config set agents.defaults.model.primary openai/gpt-5.5
and that auth can come from “the subscription profile, an ordered backup profile, or an app-server account in the agent’s Codex home.”
But the docs/source paths we were looking at still expose a lot of openai-codex naming, and the runtime error reports openai-codex. So from the operator side it looks like:
- blog says: use
openai - older docs/help say: use
openai-codex - runtime says: failing provider is
openai-codex - app-server supposedly can use Codex-home auth, but the bridge still selected a stale/default profile
That naming/routing split is the real UX bug, not just your setup.
For your goal, I would try the blog path cleanly for one agent:
OPENCLAW_AGENT_DIR=/home/openclaw/.openclaw/state/agents/ember/agent \
openclaw models auth login --provider openai
openclaw config set agents.defaults.model.primary openai/gpt-5.5
openclaw gateway restart
Then fresh session and check /codex account plus /model status.
And I’d add to #81941: the public blog says --provider openai and Codex-home/app-server account should be valid auth sources, but the runtime failure and guidance still point to openai-codex. That mismatch directly caused this debugging spiral.
The clean mental model is:
OpenClaw chooses a model + runtime
|
v
Codex app-server starts inside that agent
|
v
Codex app-server needs a ChatGPT/Codex account token
There are two possible auth sources for that last step:
- OpenClaw auth profile
~/.openclaw/agents/<agent>/agent/auth-profiles.json
~/.openclaw/credentials/auth-profiles/<secret>.json
This is what openclaw models auth login --provider openai / openai-codex creates. OpenClaw then injects/bridges that token into Codex app-server.
- Codex native auth inside the agent’s Codex home
~/.openclaw/agents/<agent>/agent/codex-home/
This is what CODEX_HOME=... codex login creates. Codex app-server can use it natively.
The confusing/broken part is selection order. In 2026.5.12, even when Codex-home auth exists, OpenClaw may still select an OpenClaw openai-codex auth profile first and bridge that into app-server. If that selected profile is stale/bad, the turn fails before the native Codex-home auth can save you.
So the practical rule is:
- If using OpenClaw-managed auth: keep one correct profile per agent and pin it with
openclaw models auth order set --agent <agent> --provider openai-codex <profileId>. - If trying to use native Codex-home auth only: remove or avoid stale OpenClaw
openai-codexprofiles, because there does not seem to be a clear supported “ignore OpenClaw auth profiles, use only CODEX_HOME” switch yet.
That missing explicit switch is the part that should be fixed/documented.
cehck if this analysis is right
What changed in newer OpenClaw:
- OpenClaw stopped materializing Codex auth.json bridge files.
Evidence: CHANGELOG.md says Codex-owned runtimes now use normal
CODEX_HOME / ~/.codex auth directly. - Native Codex app-server uses per-agent CODEX_HOME.
Evidence: extensions/codex/src/app-server/auth-bridge.ts sets
CODEX_HOME to the agent-owned Codex home. - Auth priority still prefers OpenClaw auth profiles first.
Evidence: docs/providers/openai.md says auth order is:
first OpenAI auth profiles
then app-server existing account / Codex CLI sign-in
then env API-key fallback
So the working state we found makes sense:
Ember works when:
agents/ember/agent/codex-home/auth.json exists
and stale OpenClaw auth-profiles.json does not shadow it.
What is not the answer
══════════════════════
openclaw models auth login --provider openai-codex
That writes OpenClaw auth profiles. In our setup that was the trap, because those profiles
outrank native Codex CLI auth and can produce the stale “Model login expired” path.
I also checked openclaw migrate codex: it migrates skills/plugins/config review state, not
live Codex OAuth auth. Docs explicitly list Codex auth/config as manual-review/archive-
style, not “make this agent logged in.”
Actual current clean command
════════════════════════════
For Ember, the native-auth command is still:
export CODEX_HOME=/home/openclaw/.openclaw/state/agents/ember/agent/codex-home
node /pnpm/global/5/.pnpm/@openai+codex@*/node_modules/@openai/codex/bin/codex.js login
--device-auth
The improvement we should make in agent-vm is an ergonomic wrapper around that, probably:
agent-vm controller codex-login --zone sunfam --agent ember
or similar. That wrapper would only do three things: resolve the per-agent codex-home, find
the bundled Codex CLI, run codex login --device-auth with CODEX_HOME set.
Mostly yes. I’d make two corrections/clarifications:
-
“OpenClaw stopped materializing Codex auth.json bridge files” is correct. Changelog explicitly says Codex-owned runtimes use normal
CODEX_HOME/~/.codexauth directly. -
“Native Codex app-server uses per-agent CODEX_HOME” is correct. The 2026.5.12 code sets
CODEX_HOMEto<agentDir>/codex-homeunless overridden. -
The auth priority claim is directionally right, but the naming is messy. The installed docs still say:
openai-codex/gpt-5.5= PI route with Codex OAuthopenai/gpt-5.5+ Codex runtime = app-server route- keep using
openai-codexfor auth/profile commands
The blog says --provider openai, which conflicts with the installed docs/runtime wording. That mismatch is part of the bug report.
Your conclusion is right: Ember working with:
agents/ember/agent/codex-home/auth.json exists
and no stale OpenClaw auth profile shadows it
makes sense.
I also agree openclaw models auth login --provider openai-codex is not the answer if your goal is “native Codex app-server auth only.” That command creates OpenClaw auth profiles, and those can outrank the Codex-home account and recreate the stale-profile failure.
The wrapper idea is solid:
agent-vm controller codex-login --zone sunfam --agent ember
should resolve the agent dir, set CODEX_HOME=<agentDir>/codex-home, find the managed @openai/codex binary, and run the Codex login flow there.