1. 为什么要在 Arduino UNO Q 上把 Codex 鉴权改到 TaoToken
Arduino UNO Q 这块板子有意思的地方在于,它既是能跑 Arduino sketches 的开发板,又是一台完整的 Debian 13 单板计算机。我在上面跑 Nanobot 做自动化编程时,最头疼的不是算力,而是鉴权配置太散:Claude Code 一套 Key、Codex 一套 auth.json、Nanobot 内部调用 LLM 又是另一套环境变量。板子掉电重启后,经常出现某个通道鉴权失效,Nanobot 的自我学习任务就卡在那里不动了。
把 Codex 的 auth.json 统一改到 TaoToken 的 API 通道,本质上是做一件事:让板载环境里所有需要调用大模型的地方,都走同一个入口。TaoToken 是一个聚合式的大模型 API 接入服务,提供统一的 Key 和 Base URL,支持 OpenAI 兼容协议。对于 Arduino UNO Q 这种资源有限、又需要长期无人值守运行的设备来说,统一鉴权入口能显著减少配置漂移。
这篇是系列第二篇,聚焦实操配置迁移。适合已经在 Q 板上跑通 Nanobot、并且用 Codex 或 Claude Code 做过辅助编程的读者。如果你还没装 Nanobot,建议先看第一篇把基础环境搭好。下面我会给出可直接复制的 auth.json 片段、逐项验证动作,以及我踩过的报错对照表。
需要先明确一点:Codex 的 auth.json 默认走的是官方 OAuth 流程,文件里存的是 token 和账户信息。我们要做的是把它改成走 API Key 模式,指向 TaoToken 的兼容端点。这样 Nanobot 在调用 Codex 相关能力时,就不会因为 OAuth token 过期而中断。
整个迁移分四步:备份原配置、写入新 auth.json、验证单次请求、接入 Nanobot 自检。每一步都有可复制的命令,你跟着做就行。
2. TaoToken 前置准备与 auth.json 路径确认
在动 auth.json 之前,先把 TaoToken 这边的 Key 拿到手。访问 https://taotoken.net/api-keys 创建 API Key,建议给 Q 板单独建一个,命名成arduino-uno-q-nanobot,方便后续排查是哪个设备在调用。创建后立刻复制保存,页面刷新后就看不到了。
TaoToken 的 API 入口是 https://taotoken.net/api,这个地址要填到 auth.json 的 base_url 字段里。注意不要带多余的路径后缀,OpenAI 兼容客户端会自动拼接/v1/chat/completions。
接下来确认 Q 板上 Codex 的配置目录。SSH 登录后执行:
# 确认当前用户和 home 目录 whoami echo $HOME # 查找 auth.json 实际位置 find /home/arduino -name "auth.json" -path "*codex*" 2>/dev/null ls -la ~/.codex/ 2>/dev/null我实测下来,Codex 在 Debian 环境下通常把配置放在~/.codex/auth.json。如果你的 Nanobot 是以 systemd 用户服务运行的,注意$HOME要对应到/home/arduino,因为服务文件里 WorkingDirectory 指向的是/home/arduino/nanobot。
先备份原文件,这一步别省:
# 创建备份目录 mkdir -p ~/codex-backup # 备份原始 auth.json cp ~/.codex/auth.json ~/codex-backup/auth.json.bak.$(date +%Y%m%d) # 确认备份成功 ls -la ~/codex-backup/同时记录一下当前 Codex 的版本,不同版本 auth.json 的字段结构略有差异:
codex --version 2>/dev/null || echo "codex CLI not in PATH"如果codex命令不在 PATH 里,说明它是通过 Nanobot 的虚拟环境调用的,路径可能是/home/arduino/nanobot/.venv/bin/codex。用绝对路径确认版本:
/home/arduino/nanobot/.venv/bin/codex --version确认完路径和版本,再检查一下 Nanobot 当前用的 provider 配置。Nanobot 的 LLM 提供商注册表在/home/arduino/nanobot/nanobot/providers/registry.py,里面会读取环境变量或配置文件。我们要保证 auth.json 改完后,Nanobot 调用 Codex 时读到的就是新配置。
# 查看 Nanobot 当前环境变量中与 API 相关的项 grep -i "api\|key\|base_url" ~/.nanobot/config.json 2>/dev/null env | grep -i "openai\|codex\|taotoken" 2>/dev/null如果~/.nanobot/config.json不存在,说明 Nanobot 用的是默认配置或环境变量注入。这种情况下,auth.json 就是唯一的鉴权来源,改它最直接。
3. 可复制的 auth.json 配置片段与写入步骤
现在进入核心配置环节。Codex 的 auth.json 在 API Key 模式下,结构比 OAuth 模式简单很多。下面是我在 Q 板上验证通过的完整片段,你可以直接复制,只需要替换sk-开头的 Key。
{ "auth_mode": "apikey", "openai_api_key": "sk-你的TaoToken密钥", "base_url": "https://taotoken.net/api", "model": "gpt-4o", "provider": "openai", "tokens": { "access_token": null, "refresh_token": null, "id_token": null }, "last_refresh": null }几个字段说明一下。auth_mode必须是apikey,这是告诉 Codex 不要走 OAuth 刷新流程。openai_api_key填 TaoToken 创建的 Key。base_url填https://taotoken.net/api,不要加/v1。model字段填你实际要用的模型 ID,TaoToken 支持的模型列表可以在模型对话页面查看,选一个适合代码生成的即可。
写入步骤:
# 确保 .codex 目录存在 mkdir -p ~/.codex # 用 nano 编辑 auth.json nano ~/.codex/auth.json把上面的 JSON 粘贴进去,替换 Key 后保存。然后设置权限,防止其他用户读取:
chmod 600 ~/.codex/auth.json chown arduino:arduino ~/.codex/auth.json如果你用的是 Nanobot 的 systemd 用户服务,还需要确认服务能读到这个文件。检查服务文件里的环境变量:
cat ~/.config/systemd/user/nanobot-gateway.service | grep -A5 Environment如果服务里显式设置了OPENAI_API_KEY或OPENAI_BASE_URL,这些环境变量会覆盖 auth.json。要么删掉这些环境变量,要么把它们改成和 auth.json 一致的值。我建议统一到 auth.json,环境变量只保留 PATH 和必要的运行参数。
改完后重载服务:
systemctl --user daemon-reload systemctl --user restart nanobot-gateway systemctl --user status nanobot-gateway状态显示active (running)就说明服务正常起来了。但服务起来不代表鉴权通了,下一步必须做实际请求验证。
另外,如果你同时用 Claude Code 做辅助编程,Claude Code 的配置在~/.claude/settings.json或环境变量ANTHROPIC_BASE_URL。要让 Claude Code 也走 TaoToken,需要单独配置,参考接入文档里的说明。本篇聚焦 Codex auth.json,Claude Code 的配置迁移放到下一篇。
4. 验证请求与成功结果确认
配置写完后,不要直接跑 Nanobot 的完整任务,先用最小请求验证鉴权链路。这样出问题容易定位。
第一步,用 curl 直接测 TaoToken 端点:
curl -s -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的TaoToken密钥" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "messages": [{"role": "user", "content": "回复OK两个字母"}], "max_tokens": 10 }'如果返回的 JSON 里有choices数组,且message.content包含内容,说明 Key 和端点都通。如果返回 401,说明 Key 有问题;返回 404,说明 base_url 路径不对。
第二步,用 Codex CLI 自身验证:
# 进入 Nanobot 项目目录 cd /home/arduino/nanobot # 用 Codex 执行一个简单查询 /home/arduino/nanobot/.venv/bin/codex "print hello" --model gpt-4o 2>&1 | head -20如果 Codex 能正常返回结果,说明 auth.json 被正确读取。如果报reading choices相关错误,通常是响应格式不匹配,检查 base_url 是否多了/v1。
第三步,验证 Nanobot 内部调用。Nanobot 的 agent 主循环在/home/arduino/nanobot/nanobot/agent/loop.py,它会通过 provider 调用 LLM。触发一次简单的 Nanobot 任务:
# 查看 Nanobot 日志 journalctl --user -u nanobot-gateway -n 50 --no-pager # 或者直接跑一次 gateway 的前台模式看输出 cd /home/arduino/nanobot .venv/bin/nanobot gateway --log-level debug 2>&1 | head -40成功的话,日志里会出现类似provider=openai model=gpt-4o status=200的记录。如果出现local proxy failed或connection refused,说明 Nanobot 尝试走本地代理,需要检查环境变量里有没有残留的HTTP_PROXY设置。
第四步,确认自我学习链路。Nanobot 的 Memory 系统在/home/arduino/nanobot/nanobot/agent/memory.py,当会话消息超过阈值时会触发consolidate,这个过程会调用 LLM。你可以手动触发一次记忆整合来验证:
# 查看当前记忆文件 ls -la ~/.nanobot/workspace/memory/ cat ~/.nanobot/workspace/memory/MEMORY.md 2>/dev/null | head -20如果 MEMORY.md 有内容更新,说明 LLM 调用链路完全通了。这一步验证通过后,Nanobot 的 heartbeat 心跳服务、知识库语义搜索、skill 技能系统就都能正常工作了。
5. 常见报错对照与排查
迁移过程中我遇到过几类典型报错,整理成对照表,你遇到时可以直接定位。
| 报错信息 | 触发位置 | 原因 | 解决动作 |
|---|---|---|---|
401 Unauthorized | curl / Codex | Key 错误或未生效 | 重新复制 TaoToken Key,确认无空格 |
local proxy failed | Nanobot 日志 | 环境变量残留代理设置 | unset HTTP_PROXY HTTPS_PROXY |
reading choices | Codex CLI | base_url 路径错误 | 改为https://taotoken.net/api |
OAuth token expired | Codex CLI | auth_mode 未改 | 确认auth_mode为apikey |
model not found | curl / Nanobot | model ID 拼写错误 | 在模型对话页确认可用模型 ID |
connection refused | Nanobot 启动 | 服务未重启 | systemctl --user restart nanobot-gateway |
permission denied | 读取 auth.json | 文件权限过严 | chmod 600并确认属主 |
重点说两个最容易踩的坑。
第一个是local proxy failed。这个报错在 Q 板上特别常见,因为 Debian 环境可能从系统层面设置了代理变量。排查方法:
# 检查所有代理相关环境变量 env | grep -i proxy # 检查 systemd 服务里的环境变量 systemctl --user show-environment | grep -i proxy # 临时清除 unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY all_proxy ALL_PROXY如果 systemd 用户服务里注入了代理变量,需要在服务文件的[Service]段加一行Environment="NO_PROXY=*",或者直接删掉代理相关行。
第二个是reading choices。这个报错的意思是 Codex 收到了响应,但结构里没有choices字段。原因通常是 base_url 写成了https://taotoken.net/api/v1,导致实际请求路径变成/api/v1/v1/chat/completions。改成https://taotoken.net/api即可。
还有一个隐蔽问题:auth.json 改对了,但 Nanobot 的 provider 注册表里缓存了旧的配置。Nanobot 的registry.py在启动时加载 provider,如果服务没有完全重启,旧配置还在内存里。解决方法是彻底停掉再启动:
systemctl --user stop nanobot-gateway sleep 2 systemctl --user start nanobot-gateway如果以上都排查完还是不通,用 TaoToken 的模型对话页面单独测一下 Key 是否有效。把 Key 填进去发一条消息,能收到回复说明 Key 没问题,问题在 Q 板本地配置。
6. 统一鉴权后的 Nanobot 自动化编程接入
auth.json 迁移完成后,Nanobot 的自动化编程能力才算真正稳定下来。这一节说几个后续可以做的动作,让整套系统跑得更顺。
首先是 Coding Plan 的接入。如果你打算让 Nanobot 长期执行编码任务,比如自动修复代码、生成测试用例,建议用 TaoToken 的 Coding Plan 通道。它的计费和调用方式和普通 API 略有不同,适合高频、长时间的 agent 场景。配置方式是在 auth.json 里把base_url换成 Coding Plan 对应的端点,具体地址在 Coding Plan 页面有说明。
其次是 Claude Code 的配合。我在 Q 板上用 Claude Code 做文件上传下载和代码编辑,用 Nanobot 做后台自动化任务,两者分工明确。Claude Code 的接入配置参考接入文档,核心也是把 Base URL 指向 TaoToken,Key 用同一个。这样两个工具共享鉴权,减少管理成本。
第三是 Nanobot 的 heartbeat 心跳服务。配置在~/.nanobot/config.json的gateway.heartbeat段,默认 30 分钟唤醒一次。统一鉴权后,心跳任务里的 LLM 调用不会再因为 token 过期而失败。你可以把 HEARTBEAT.md 里的任务写得更激进一些,比如每 2 小时检查一次代码仓库状态。
第四是知识库和 skill 的联动。Nanobot 的 knowledge_base_search 工具在/home/arduino/nanobot/nanobot/knowledge/local_kb.py,语义搜索需要调用 embedding 模型。如果 TaoToken 支持 embedding 端点,可以把知识库的向量化也统一过去。这样整个 Nanobot 的 AI 能力都走一个通道,排查问题只需要看一个日志。
最后提醒一点:auth.json 里的 Key 是明文存储的,Q 板如果放在公网可访问的网络里,务必确保 SSH 只允许密钥登录,并且 auth.json 权限设为 600。定期在 TaoToken 控制台轮换 Key,轮换后同步更新 auth.json 并重启服务。
整套配置迁移下来,最耗时的不是写 JSON,而是排查环境变量冲突。建议你在改之前先把env | grep -i proxy和systemctl --user show-environment的输出保存下来,出问题时对比。Nanobot 的日志用journalctl --user -u nanobot-gateway -f实时跟踪,比看前台输出更清楚。