
在 Termux 里把 OpenClaw Node 跑起来、Gateway 批准了 Android 手机节点、MQTT broker 也连上发/photo back却收到 401这种场景比设备掉线更让人迷惑。401 通常不是 ADB 没连上而是模型通道的 Key 或 Base URL 没填对OpenClaw 需要先把自然语言解析成 Skill 调用参数这一步要访问模型 APIADB 和 MQTT 的本地执行是下一步。把 TaoToken 的 Key 建好、Base URL 填成 https://taotoken.net/api 后手机拍照和灯控会继续按原来的 Node/Skill 跑。先打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册并创建一把 API Key再回 OpenClaw 改模型供应商配置。1. 401 先从 OpenClaw 日志里拆开看模型通道还是 ADB 本地1.1 在 Termux 与 Gateway 日志里找 Unauthorized在廉价安卓机上装完 Termux执行pkg update pkg upgrade再补上pkg install nodejs git termux-api随后用npm install -g openclaw把 Node 端装好。启动时常见命令是openclaw node run --host 192.168.1.100 --port 18789 --display-name Android-NodeGateway 侧执行openclaw nodes pending能看到待审批节点再用openclaw nodes approve request-id批准。这套流程只负责让设备节点上线它和模型通道没有直接关系。真正把「用后置摄像头拍一张」解析成camera.snap或adb shell am start -a android.media.action.IMAGE_CAPTURE的那一步才需要访问模型 API。如果模型 API 的 Key 不对、Base URL 指向了错误路径日志里会出现401 Unauthorized而 ADB 设备列表可能还是正常的。很多排障之所以绕远是因为把设备链路和模型链路混在一起看。先确认 401 来自哪个 HTTP 请求再决定是修 Key、修 Base URL还是修 ADB 权限。1.2 ADB 与 MQTT 的本地错误不会长成 401ADB 报错通常是device not found、more than one device/emulator、unauthorizedMQTT 报错通常是ECONNREFUSED、Connection refused、Not authorized。这些和模型 API 返回的 HTTP 401 不是一回事。把adb devices在 Termux 或 PC 上跑一遍把mosquitto_sub -t home/sensor/temperature -v跑一遍如果本地链路正常再回头看 OpenClaw 的模型供应商设置。这条统一通道只负责模型 API 的 Key 与兼容地址ADB 命令和 MQTT 发布仍由 OpenClaw 的 Node/Skill 在本地执行。也就是说401 修好之后/photo back能不能拍到照片仍取决于手机端相机应用、ADB 授权、allowlist/light on能不能亮灯仍取决于 MQTT broker 地址、topic 和继电器接线。把两层分开排查会快很多。2. 在 OpenClaw 模型接入处填 TaoToken Base URL2.1 准备 Key 和模型 ID打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册进入控制台创建 API Key记下以YOUR_API_KEY占位的那串值。模型 ID 不要凭印象写去同一站点的模型广场看当时列表复制你要用的那个 ID。原文里没有单独讲模型 Key 的获取这一步属于补齐通道配置如果跳过OpenClaw 在解析/photo back时就会在模型请求阶段收到 401。拿到 Key 后先不要急着改一堆文件。把 Key、Base URL、模型 ID 三样放在手边后面无论 OpenClaw 用配置文件还是环境变量都围绕这三样填。Key 从 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建模型 ID 以模型广场当时列表为准Base URL 固定写https://taotoken.net/api末尾不要加/v1。2.2 ~/.openclaw/config.yaml 里的 provider 段OpenClaw 的模型接入一般落在~/.openclaw/config.yaml有些版本拆到gateway.yaml或通过环境变量覆盖字段名以你本机openclaw config输出为准。核心是三件事provider 选 OpenAI 兼容或自定义Base URL 填https://taotoken.net/api末尾不要加/v1API Key 填YOUR_API_KEYmodel 填从模型广场复制的 ID。# ~/.openclaw/config.yaml model: provider: openai-compatible base_url: https://taotoken.net/api api_key: YOUR_API_KEY model_id: YOUR_MODEL_ID注意 Base URL 和官网落地页不是同一个地址。注册、创建 Key、看模型广场、看用量走 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end填进 OpenClaw 的 Base URL 走https://taotoken.net/api。如果把?utm_source...拼到/api后面或者把/v1多写一层都会让请求落到错误路径401 或 404 都会出现。2.3 重启 Gateway 和 Node 让配置生效改完配置后先在 Gateway 侧停掉进程再重新拉起Termux 里的 Node 也重新执行openclaw node run避免旧环境变量残留。如果 OpenClaw 版本支持环境变量覆盖可以用下面方式临时验证变量名仍以你本机文档为准export OPENCLAW_MODEL_BASE_URLhttps://taotoken.net/api export OPENCLAW_MODEL_API_KEYYOUR_API_KEY export OPENCLAW_MODEL_IDYOUR_MODEL_ID openclaw node run --host 192.168.1.100 --port 18789 --display-name Android-Node重启后用openclaw nodes list确认 Android 节点仍在线。如果节点掉了先重新审批如果节点在线但发指令仍 401就回到配置文件检查 Key 是否被引号、空格或旧值覆盖。配置文件和环境变量同时存在时以实际加载到进程里的那一份为准。3. 401 消失后ADB 拍照 Skill 继续按原路径跑3.1 android-control Skill 的职责边界原文的~/.openclaw/skills/android-control/index.ts做的是把 action 映射成 ADB 命令。模型只负责把「后置摄像头拍一张」翻译成{ action: screenshot, ... }或camera.snap调用真正执行adb shell input tap、adb shell screencap -p、adb pull的是本地 Skill。重写后的 handler 可以保持同样思路但不要依赖模型直连手机。// ~/.openclaw/skills/android-control/index.ts import { execFile } from node:child_process; import { promisify } from node:util; const run promisify(execFile); export async function handler(input: { action: tap | swipe | screenshot | input; deviceId?: string; x?: number; y?: number; text?: string; }) { const serial input.deviceId ?? process.env.ANDROID_SERIAL; if (!serial) return { code: 1, message: 没有可用 Android 设备 }; const adb (args: string[]) run(adb, [-s, serial, ...args]); if (input.action tap) { await adb([shell, input, tap, String(input.x), String(input.y)]); return { code: 0, message: tap ${input.x},${input.y} }; } if (input.action input) { await adb([shell, input, text, input.text ?? ]); return { code: 0, message: text injected }; } if (input.action screenshot) { const stamp Date.now(); const remote /sdcard/openclaw-${stamp}.png; const local /tmp/openclaw-${stamp}.png; await adb([shell, screencap, -p, remote]); await adb([pull, remote, local]); await adb([shell, rm, remote]); return { code: 0, data: { localPath: local } }; } return { code: 1, message: 未实现: ${input.action} }; }3.2 /photo back 从飞书指令到本地 adb 的桥~/.openclaw/commands/photo.yaml可以继续保持命令声明handler 里调用上面的 Skill。区别在于401 排除后模型能把facingback解析成参数Skill 收到参数再执行本地命令。拍照等待三秒、取最新 DCIM 文件、adb pull到/tmp这些仍是本地行为。若手机没装支持命令行拍照的应用ADB 可能只拉起相机界面不会自动按快门这属于设备侧限制不是模型通道问题。# ~/.openclaw/commands/photo.yaml name: photo description: 远程触发手机拍照 usage: /photo [front|back] handler: ./handlers/photo.ts options: - name: facing type: string enum: [front, back] default: backhandler 里可以继续用execFile调用adb把最新照片路径读出来再转 base64 返回。重复拍照时注意清理/sdcard上的临时文件否则廉价手机存储很快会被占满。3.3 截图、安装 APK、读传感器别混进模型通道原文还提到安装 APK、读取传感器。这些动作在exec-approvals.json里用 allowlist 控制例如只允许/system/bin/input、/system/bin/screencap拒绝/system/bin/reboot、/system/bin/rm。模型通道只影响「指令解析」这一段。即使通道 Key 正确节点权限没批、allowlist 没配本地 ADB 命令照样会被 OpenClaw 拦截。排障时要分开看401 看模型通道权限拒绝看节点审批和白名单。传感器读取通常需要额外权限部分设备还要 root。不要因为 401 修好后传感器仍失败就回头怀疑 Base URL。先看 OpenClaw 返回的具体错误码再决定是补权限还是换方案。4. MQTT 灯控与增氧机的模型调用链4.1 mqtt-control Skill 只发布消息原文的 MQTT Skill 用mqtt.connect发布 topic。重写时可以保留「连接 broker、发布、断开」的结构但不要让它承担模型 Key 的职责。模型负责把「打开客厅灯」解析成{ topic: home/light/living/set, message: { state: ON } }本地 Skill 再发到 mosquitto 或 emqx。若 401 出现在模型请求阶段灯控指令根本到不了 MQTT publish所以先修通道再修设备。// ~/.openclaw/skills/mqtt-control/index.ts import mqtt from mqtt; export async function handler(input: { topic: string; message: string | Recordstring, unknown; qos?: 0 | 1 | 2; }) { const broker process.env.MQTT_BROKER ?? mqtt://127.0.0.1:1883; const payload typeof input.message string ? input.message : JSON.stringify(input.message); return new Promise((resolve) { const client mqtt.connect(broker, { connectTimeout: 3000 }); client.on(connect, () { client.publish(input.topic, payload, { qos: input.qos ?? 0 }, (err) { client.end(); if (err) resolve({ code: 1, message: err.message }); else resolve({ code: 0, message: published ${input.topic} }); }); }); client.on(error, (err) { client.end(); resolve({ code: 1, message: mqtt: ${err.message} }); }); }); }4.2 /light on 与鱼塘增氧机的定时关闭/light living on可以走home/light/living/set消息体{ state: ON }。鱼塘增氧机可以走fishpond/aerator/set开启后按duration分钟设置定时关闭并给飞书发通知。这些逻辑都在本地 Node/Skill 里。模型只把「打开增氧机 30 分钟」拆成 action 和 duration。401 修好后这条链路恢复如果 MQTT broker 的用户名密码不对报错会变成连接失败而不是模型 401。空调控制也类似topic 可以按home/ac/living/set设计消息体里带temperature和mode。这些参数由模型解析发布动作由本地 Skill 完成。不要把 broker 密码塞进模型提示词也不要让模型直接连 broker。4.3 多设备协同时 401 容易复发的两个位置多设备协同里PC 节点、手机节点、MQTT 节点可能各自有模型调用入口。只在 Gateway 配了统一通道Node 侧如果还有独立模型配置仍会 401。另一个位置是定时任务或后台脚本直接读旧环境变量重启后没加载新 Key。排查时把每个会发起模型请求的进程列出来统一把 Base URL 指向https://taotoken.net/apiKey 用同一把从 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建的 Key。PC 抓数据、手机收通知、传感器触发自动化这三类流程只要涉及自然语言解析就会走模型请求。哪一端报 401就先看哪一端的配置。不要只改 Gateway 就以为全网生效。5. 验证与排障对照表5.1 先用模型对话页面确认 Key 和模型 ID打开 TaoToken 模型对话用刚才的YOUR_API_KEY发一条测试消息模型选你从模型广场复制的 ID。如果这里就 401说明 Key 本身有问题如果这里正常OpenClaw 还 401问题就在 OpenClaw 配置读取或环境变量。模型对话页面还能帮你确认模型 ID 是否可用。OpenClaw 配置里写错一个字符返回可能不是 401而是 model not found。先把模型对话跑通再去 Termux 里跑 Node排障范围会小很多。5.2 OpenClaw 侧逐条对照现象可能原因处理401 UnauthorizedKey 缺失、失效、环境变量没加载从 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 重新创建 Key填入 OpenClaw 模型配置404 Not FoundBase URL 多写了/v1或路径拼错Base URL 改成https://taotoken.net/api末尾不加/v1model not found模型 ID 不在当前账号可用列表去模型广场复制当时可用的 IDadb: device not foundUSB/WiFi 调试断连本地执行adb devices检查和模型通道无关MQTT connect failedBroker 地址、端口或认证不对本地检查 broker 配置模型只负责解析 topic 和消息体5.3 看用量确认请求到了统一通道去 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 看用量记录跑一次/photo back后应该能看到调用。如果用量没涨说明 OpenClaw 还在走旧地址或旧 Key。把用量记录和 OpenClaw 日志时间对一下能快速判断请求有没有真正发出去。6. 跑通拍照和灯控后去控制台对一下这次调用6.1 重启后先跑哪三条命令配置保存并重启 Gateway 与 Node 后先在模型对话页面用同一把 Key 发一条消息确认模型 ID 和 Base URL 没填错然后回到 Termux让 Android 节点重新上线并批准再发/photo back和/light on。如果拍照返回 base64、灯控返回 published说明 401 已经解决。之后再去跑鱼塘增氧机或多设备协同就不会把通道问题和设备问题混在一起。6.2 长期挂节点时把 Key 和用量管起来长期挂 OpenClaw 节点可以打开 Coding Plan 看套餐Key 在 控制台 API Keys 创建。最后再回 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 对一下这次调用有没有记上账。