1. Openclaw 里 Codex 认证失败到底卡在哪
如果你在 Openclaw 里集成 Codex,命令行单独跑codex登录一切正常,浏览器回调页面也显示授权成功,但 Openclaw 这边就是弹OpenAI OAuth failed或者Token exchange failed,那基本可以确定:问题不在你的账号,而在 Openclaw 读取凭证的路径和格式跟 Codex CLI 对不上。
这个场景我见得太多了。Codex CLI 登录后会把凭证写到~/.codex/auth.json,里面是auth_mode、tokens.access_token、tokens.refresh_token、tokens.account_id、last_refresh这一套结构。而 Openclaw 的 agent 在启动时,会去自己的目录~/.openclaw/agents/{agent-id}/agent/auth-profiles.json里找 OAuth profile,字段名要求是access、refresh、expires、accountId。两边的字段名、时间格式、嵌套层级全不一样,Openclaw 读不到就会直接判定认证失败。
更麻烦的是,Codex 的 OAuth token 是有有效期的。access_token通常 8 小时左右过期,refresh_token用来续期。如果 Openclaw 拿到的expires时间戳算错了,或者根本没写refresh字段,那第一次请求可能勉强过,过一会儿就 401。CI 场景下更明显:本地手动登录一次能用,流水线里跑几分钟就挂,因为 token 刷新链路断了。
所以排查思路要分两层:第一层是凭证有没有被 Openclaw 正确读到,第二层是读到的凭证能不能自动续期。只解决第一层,你会在几小时后再次遇到 401;两层都解决,才能稳定跑下去。
这里还有一个容易被忽略的点:Openclaw 的 agent 目录可能不止一个。如果你配置了多个 agent,路径是~/.openclaw/agents/{agent-id}/agent,{agent-id}要换成你实际用的那个。只配了一个 agent 时才是main。很多人改了半天没生效,就是因为改错了 agent 目录。
另外,团队版 Codex 有时候没有独立的 API Key,只能走 OAuth。这种情况下你不能简单粗暴地填一个OPENAI_API_KEY了事,必须把 OAuth 的 token 三元组完整映射过去。这也是为什么本文重点讲auth.json到auth-profiles.json的转换,而不是让你重新注册一套 Key。
如果你希望彻底绕开这种本地凭证搬运的麻烦,也可以把 Codex 的请求通道统一到 TaoToken 的 API 上,用一把 Key 走https://taotoken.net/api,这样 Openclaw 里只需要配 Base URL + Key + Model ID,不再依赖auth.json的 OAuth 刷新。两种方案我都会给出来,你可以按自己的团队情况选。
先说结论:认证失败九成不是网络问题,而是凭证格式和路径问题。下面按“先修凭证、再验请求、最后排错”的顺序走一遍。
2. TaoToken 前置准备:统一 Key 与 API 通道
在动手改auth-profiles.json之前,建议先把 TaoToken 的通道准备好。原因很简单:OAuth 方案依赖 Codex 官方 token 的刷新,一旦 refresh 失败,你还是会回到 401。而用 TaoToken 的统一 Key,Openclaw 侧只需要一个稳定的 Base URL 和 Key,模型 ID 直接指定,认证链路短很多,CI 里也更可控。
你需要先拿到一把 API Key。登录 TaoToken 控制台,在 API Keys 页面创建一个新 Key,复制出来。这个 Key 就是后面 Openclaw 配置里的OPENAI_API_KEY或者 provider 的apiKey字段。注意不要把它提交到 Git,CI 里用环境变量注入。
Base URL 用https://taotoken.net/api,不要加多余的路径后缀。很多 401 是因为把 Base URL 写成了带/v1或者带/chat/completions的完整地址,Openclaw 或 Codex 再拼一次就 404 或 401。
模型 ID 方面,Codex 场景常用的是gpt-5-codex这类编码模型,具体以你控制台里可用的模型列表为准。Openclaw 的 provider 配置里要显式写 Model ID,不能留空。
如果你只是想先验证通道通不通,可以打开模型对话页面发一条最小请求,确认 Key 有效、余额正常、模型可调用。这一步能排除掉“Key 本身无效”这种低级问题,省得后面在 Openclaw 里绕圈。
对于长期在 CI 里跑 Codex 的团队,建议直接用 Coding Plan 这类按周期计费的方式,避免 OAuth token 过期导致流水线随机失败。OAuth 方案适合个人本地开发,团队流水线还是统一 Key 更稳。
准备好这三样东西:Base URL、API Key、Model ID。后面无论是改auth-profiles.json还是配 Openclaw 的 provider,都围绕这三件套展开。如果你决定继续用 OAuth 方案,TaoToken 这步可以跳过,但建议至少留一把 Key 作为 fallback,OAuth 刷新失败时能快速切换。
3. 可复制配置:auth.json 到 auth-profiles.json 的完整映射
这一节是核心。先找到 Codex CLI 登录后生成的auth.json。Windows 在C:\Users\你的用户名\.codex\auth.json,WSL 或 Linux 在~/.codex/auth.json。用编辑器打开,你会看到类似这样的结构:
{ "auth_mode": "chatgpt", "OPENAI_API_KEY": null, "tokens": { "id_token": "eyJhbGciOi...", "access_token": "eyJhbGciOi...", "refresh_token": "rt_g3MXvek9...", "account_id": "e7aa930b-374a-442b-a84d-640d38277a49" }, "last_refresh": "2026-04-07T14:37:23.394214192Z" }注意access_token和refresh_token都是长字符串,复制时不要断行、不要漏字符。last_refresh是 ISO 8601 时间字符串。
接下来找到 Openclaw 的 agent 目录。单 agent 时是~/.openclaw/agents/main/agent,多 agent 时是~/.openclaw/agents/{agent-id}/agent。如果这个目录下没有auth-profiles.json,就新建一个。目标格式如下:
{ "version": 1, "profiles": { "openai-codex:default": { "type": "oauth", "provider": "openai-codex", "access": "把 auth.json 里的 access_token 粘到这里", "refresh": "把 auth.json 里的 refresh_token 粘到这里", "expires": 1776414669925, "accountId": "e7aa930b-374a-442b-a84d-640d38277a49" } }, "usageStats": { "openai-codex:default": { "errorCount": 0, "lastUsed": 1775550669925 } } }映射关系必须严格对应:access_token→access,refresh_token→refresh,account_id→accountId。expires字段最容易出错,它不是直接抄last_refresh,而是last_refresh的时间戳加上 8 小时(28800 秒),单位是毫秒。
举个例子,last_refresh是2026-04-07T14:37:23Z,转成时间戳约1775572643000,加 8 小时28800000,得到1775601443000。你可以用 Python 一行算出来:
from datetime import datetime, timezone last_refresh = "2026-04-07T14:37:23.394214192Z" dt = datetime.fromisoformat(last_refresh.replace("Z", "+00:00")) expires_ms = int(dt.timestamp() * 1000) + 8 * 3600 * 1000 print(expires_ms)usageStats里的lastUsed可以填当前时间戳,errorCount初始为 0。这个字段不影响认证,但保留结构更规范。
如果你决定走 TaoToken 统一 Key 方案,那就不需要auth-profiles.json这套 OAuth 结构,而是在 Openclaw 的 provider 配置里写:
{ "provider": "openai", "baseURL": "https://taotoken.net/api", "apiKey": "你的 TaoToken Key", "model": "gpt-5-codex" }三件套齐全:Base URL、Key、Model ID。这样 Openclaw 不再依赖auth.json,也就没有 OAuth refresh 的问题。
改完文件后保存,注意 JSON 不能有尾逗号,不能有注释。用python -m json.tool auth-profiles.json校验一下格式,能过再重启。
4. 验证请求:一次最小调用确认认证恢复
配置改完不要急着跑完整任务,先用最小请求验证。第一步重启 Openclaw 网关:
openclaw gateway restart然后查看模型列表,确认 Openclaw 能识别到 Codex provider:
openclaw models list如果列表里能看到openai-codex:default或者你配置的模型 ID,说明凭证已经被读到了。如果列表为空或者报 provider 未注册,回到上一节检查auth-profiles.json的路径和 JSON 格式。
接下来发一次最小请求。如果你用的是 OAuth 方案,可以直接在 Openclaw 里跑一个最简单的 prompt:
openclaw run --agent main --prompt "reply with ok"预期返回里包含ok,且没有 401 或Token exchange failed。如果返回正常,说明 access token 有效、通道打通。
如果你用的是 TaoToken 统一 Key 方案,可以用 curl 直接验证通道:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer 你的Key" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-5-codex", "messages": [{"role": "user", "content": "reply with ok"}] }'返回 JSON 里有choices[0].message.content且内容为ok,就说明 Key、Base URL、Model ID 三件套都正确。这一步过了,再回到 Openclaw 里跑任务基本不会再有认证问题。
验证时还要注意一点:OAuth 方案的expires如果算错,第一次请求可能成功,但 Openclaw 在后台刷新时会失败。你可以观察网关日志里有没有refresh相关报错。如果几分钟后就 401,多半是expires或refresh字段的问题。
CI 场景下建议把验证步骤做成流水线的一个前置 job,每次跑任务前先发一次最小请求,失败就快速失败,不要等到主任务跑到一半才报认证错误。
5. 常见报错排查:401、local proxy failed、reading choices
实际排查中,报错信息能帮你快速定位。下面按真实遇到的错误逐条对照。
401 Unauthorized最常见。如果是 OAuth 方案,先检查access字段是不是完整复制,有没有被编辑器自动换行截断。再检查expires是否已经过期,过期了 Openclaw 会用refresh去续,如果refresh也无效,就会 401。如果是 TaoToken 方案,检查 Key 是否复制完整、有没有多余空格、Base URL 是不是https://taotoken.net/api。
local proxy failed通常出现在 Openclaw 启动阶段,说明它尝试通过本地代理去请求认证端点但失败了。先确认你没有配置任何本地代理环境变量,比如HTTP_PROXY、HTTPS_PROXY。这些变量会干扰 Openclaw 的请求。清掉再重启网关。
reading choices这类报错一般是响应体解析失败,说明请求发出去了但返回的不是预期 JSON。常见原因是 Base URL 写错,比如写成了https://taotoken.net/api/v1/chat/completions,Openclaw 又拼了一次路径,结果返回 HTML 错误页。把 Base URL 改成https://taotoken.net/api即可。
OAuth refresh failed说明 refresh token 失效。Codex 的 refresh token 有时效,长期不用的账号需要重新登录 Codex CLI 生成新的auth.json,再重新映射一次。团队版账号如果被管理员重置了会话,也会导致 refresh 失效。
Token exchange failed出现在回调阶段,通常是 Openclaw 拿到的授权码换 token 时参数不对。检查auth-profiles.json里的provider是不是openai-codex,type是不是oauth。字段名写错会导致 Openclaw 用错误的流程去换 token。
还有一种情况是改了auth-profiles.json但没重启网关,Openclaw 还在用内存里的旧凭证。每次改完文件必须openclaw gateway restart。
如果以上都排查完还是失败,建议切到 TaoToken 统一 Key 方案,用三件套配置绕开 OAuth 链路。这样至少能确认是凭证问题还是通道问题。
6. 稳定跑下去:把认证配置固化到工作流
认证修好只是第一步,真正省心的是把它固化下来。本地开发时,我习惯把auth-profiles.json的生成写成一个脚本,每次 Codex CLI 重新登录后跑一次,自动完成字段映射和expires计算,避免手抄出错。
CI 场景下,不要把auth-profiles.json提交到仓库。用环境变量注入 TaoToken 的 Key,在流水线启动时生成配置文件。这样 Key 轮换时只改环境变量,不用动代码。
如果你同时用多个 agent,记得每个 agent 目录下的auth-profiles.json都要更新,或者用软链接指向同一份。只改main而实际跑的是别的 agent,是最隐蔽的坑。
最后留一个实用技巧:在 Openclaw 的启动脚本里加一行最小请求验证,认证失败就直接退出,不要让它带着坏凭证跑任务。这样报错发生在启动阶段,排查成本最低。
需要创建 Key 或查看接入文档,可以从 API Keys 和接入文档入口进去。验证模型是否可用,用模型对话页面发一条消息最快。长期在 CI 里跑编码任务,建议看 Coding Plan,比按次调用更可控。