1. 飞书 OpenClaw 机器人 401 报错到底卡在哪一环
你在飞书里给 OpenClaw 机器人发一条消息,会话窗口立刻弹回HTTP 401: Invalid Authentication,单聊、群聊都一样,机器人像没听见一样不返回任何业务结果。这个报错本身不复杂,它就是 HTTP 协议里的「未授权」——服务端认为这次请求的身份凭证无效,直接拒绝执行。麻烦的地方在于,飞书机器人这条链路上有两次鉴权:一次是飞书把用户消息推给你的机器人服务端(上行事件推送),一次是你的机器人主动调飞书开放平台接口(下行 API 调用)。任何一次的身份凭证对不上,飞书都会把 401 透传回会话窗口。
所以排查 401 不能只盯着一个地方看。我一般把它拆成三处:请求头里的鉴权字段格式对不对、Key 的来源是不是最新且一致、配置骨架里凭证有没有被写错或写死。这篇就按这个顺序,把飞书 OpenClaw 机器人接入时最常见的 401 场景走一遍,顺带把 TaoToken 统一 Key 的配置方式讲清楚,最后用 curl 复现 401 再验证修复,让你能自己定位到底是哪一环断了。
适合谁看:正在接飞书自建机器人、用 OpenClaw 做消息通道、被 401 卡住不知道从哪下手的人。下面所有命令和配置都可以直接复制改。
2. 接入前先把 TaoToken 统一 Key 准备好
OpenClaw 这类机器人框架在调用模型或上游服务时,需要一个统一的鉴权入口。TaoToken 的作用就是把这个入口收敛成一个 Key,避免你在 config.toml、settings.json、环境变量里到处散落不同来源的凭证,最后自己都分不清哪个是哪个。Key 来源混乱恰恰是 401 的高频根源之一。
先到控制台把 Key 建出来。打开 https://taotoken.net/console ,登录后进 API Keys 页面新建一个,复制出来先存到安全的地方。注意两点:一是新建后只显示一次,别关掉页面才想起来没复制;二是如果你之前重置过 Key,旧 Key 会立即失效,配置里还留着旧的就会稳定 401。
拿到 Key 之后,建议先确认它能用,再往机器人里塞。用模型对话页面快速验证一下连通性:https://taotoken.net/model-chat ,把 Key 填进去发一条测试消息,能正常返回就说明 Key 本身没问题,问题在机器人配置侧;如果这里就报鉴权失败,那先解决 Key 本身。
如果你是要长期跑编码类或 Agent 类任务,Key 的调用量和稳定性要求更高,可以看下 Coding Plan 的额度说明:https://taotoken.net/coding-plan 。接入文档在 https://taotoken.net/doc ,里面把请求头格式和常见错误码列得比较全,排障时对着看能省不少时间。
3. 可复制的 config.toml 与 settings.json 配置骨架
配置写错是 401 里最冤的一类。下面给两份骨架,一份给用 TOML 的 OpenClaw 配置,一份给用 JSON 的场景,你按自己项目实际用的那份改。
先看config.toml。核心是把 Key 从环境变量读进来,而不是硬编码:
# config.toml [bot] name = "openclaw-feishu" enabled = true [auth] # 从环境变量读取,避免明文写死在仓库里 api_key = "${TAOTOKEN_API_KEY}" # 鉴权头前缀,注意 Bearer 后有一个空格 auth_header = "Authorization" auth_scheme = "Bearer" [feishu] app_id = "${FEISHU_APP_ID}" app_secret = "${FEISHU_APP_SECRET}" verification_token = "${FEISHU_VERIFICATION_TOKEN}" encrypt_key = "${FEISHU_ENCRYPT_KEY}" [upstream] base_url = "https://taotoken.net/api" timeout_ms = 30000再看settings.json,逻辑一样,字段名按你项目里的实际键名对齐:
{ "bot": { "name": "openclaw-feishu", "enabled": true }, "auth": { "apiKey": "${TAOTOKEN_API_KEY}", "authHeader": "Authorization", "authScheme": "Bearer" }, "feishu": { "appId": "${FEISHU_APP_ID}", "appSecret": "${FEISHU_APP_SECRET}", "verificationToken": "${FEISHU_VERIFICATION_TOKEN}", "encryptKey": "${FEISHU_ENCRYPT_KEY}" }, "upstream": { "baseUrl": "https://taotoken.net/api", "timeoutMs": 30000 } }环境变量在启动脚本里注入,别写进配置文件:
export TAOTOKEN_API_KEY="你的Key" export FEISHU_APP_ID="cli_xxxxxxxx" export FEISHU_APP_SECRET="你的AppSecret" export FEISHU_VERIFICATION_TOKEN="你的VerificationToken" export FEISHU_ENCRYPT_KEY="你的EncryptKey"注意:
Bearer和 Key 之间必须恰好一个空格。多一个空格、少一个空格、写成bearer小写,都会让服务端解析失败返回 401。这个坑我见过太多次。
配置骨架里最容易出问题的是三处:Key 用了旧的、auth_scheme拼写或大小写不对、base_url写成了带路径的完整接口地址导致拼接后鉴权头丢失。改完配置记得重启机器人进程,很多框架不会热加载鉴权配置。
4. 用 curl 复现 401 并验证修复
排查 401 最有效的手段是脱离机器人框架,直接用 curl 打一次请求,把变量控制到最少。先复现错误,再验证正确。
先来一个「故意写错」的请求,复现 401:
curl -i -X POST "https://taotoken.net/api/v1/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer wrong_key_here" \ -d '{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "ping"}] }'你会看到返回头里是HTTP/1.1 401 Unauthorized,body 里带Invalid Authentication之类的信息。这一步的意义是确认:只要 Key 不对,服务端就是稳定 401,和飞书那边没关系。
再用正确的 Key 打一次:
curl -i -X POST "https://taotoken.net/api/v1/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${TAOTOKEN_API_KEY}" \ -d '{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "ping"}] }'正常应该返回HTTP/1.1 200 OK,body 里有模型回复。如果这一步通了,说明 Key 和请求头格式都没问题,401 就出在机器人配置或飞书侧凭证上。
接着验证飞书侧的凭证。飞书自建机器人拿 tenant_access_token 的请求长这样:
curl -i -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \ -H "Content-Type: application/json" \ -d '{ "app_id": "'"${FEISHU_APP_ID}"'", "app_secret": "'"${FEISHU_APP_SECRET}"'" }'返回里如果有tenant_access_token字段,说明 App ID 和 App Secret 是对的。如果这里就报错,那 401 的根因在飞书应用凭证,跟 TaoToken 无关,去开放平台核对凭证即可。
拿到 token 后,用它调一次发消息接口验证下行链路:
curl -i -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \ -H "Authorization: Bearer ${TENANT_ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "receive_id": "ou_xxxxxxxx", "msg_type": "text", "content": "{\"text\":\"hello\"}" }'这条通了,说明飞书下行鉴权没问题,剩下的就是事件推送签名校验。签名校验要核对Verification Token、Encrypt Key是否和服务端配置一致,以及服务器系统时间是否和北京时间同步——时间差超过 5 分钟,时间戳校验会直接失败。
5. 本篇常见错排查清单
把上面几步走完,大部分 401 都能定位。下面这些是我实际踩过或见过的具体错法,对着排:
Key 来源不一致:config.toml 里读的是环境变量,但启动脚本里export的是另一个旧 Key,或者.env文件没被加载。表现是 curl 手动测通、机器人一跑就 401。解决方法是打印一下进程实际读到的 Key 前几位,和平台上的对比。
请求头格式错误:Authorization: Bearer<key>中间没空格,或者写成了Authorization: <key>少了 scheme。服务端解析不到凭证就是 401。用curl -v看实际发出的请求头最直接。
tenant_access_token 过期:飞书的 tenant_access_token 有效期 2 小时,app_access_token 30 分钟。代码里如果硬编码了 token 或者没做自动刷新,跑一会儿就 401。必须实现过期前刷新,别缓存太久。
事件推送签名校验失败:Verification Token 或 Encrypt Key 复制时带了空格、换行,或者拼接顺序和官方文档不一致。这类 401 只在用户发消息时出现,主动调 API 反而正常,是个明显的区分特征。
IP 白名单拦截:开放平台开了 IP 白名单,但机器人服务端的公网出口 IP 没加进去。请求直接被拦,返回 401。把出口 IP 全部加白,或者临时关掉白名单验证。
应用未发布或权限未审批:开发状态的应用只对测试人员生效,普通用户交互会被鉴权拦截。确认应用已发布、所需权限已通过管理员审批、机器人功能处于启用状态。
系统时间偏差:服务器时间比标准时间慢或快超过 5 分钟,飞书时间戳校验失效。用date命令看一眼,必要时同步 NTP。
提示:飞书开放平台后台的「开发调试 - 请求日志」会记录每次调用的请求详情和错误码,能直接告诉你是 Token 过期、权限不足还是签名错误。排到最后还找不到原因,就去翻这个日志。
6. 把 Key 和鉴权链路固定下来
401 这类问题,修一次不难,难的是别反复出现。我的做法是把 Key 统一收敛到 TaoToken 一个来源,config.toml 和 settings.json 里只留环境变量引用,任何地方都不硬编码。这样换 Key 只改一处,也不会出现「这个文件里是新的、那个文件里是旧的」这种低级错误。
接入和排障相关的文档放在 https://taotoken.net/doc ,API Keys 在 https://taotoken.net/api-keys 管理,请求地址统一走 https://taotoken.net/api 。如果你用 Claude Code 这类工具做 Agent 开发,Anthropic 兼容接入的说明在 https://taotoken.net/claudecode-anthropic ,配置思路和上面一致,都是把鉴权头格式和 Key 来源固定住。
最后留一个实用习惯:每次改完鉴权配置,先用 curl 打一次最小请求确认 200,再重启机器人。这一步花不了十秒,但能帮你把「配置改了但没生效」和「配置本身写错了」这两类问题分开,省下大量来回试的时间。