最近需要为自己的 AI Agent 添加飞书消息通道,让用户可以通过飞书私聊与机器人对话。本以为半小时能搞定的事,结果折腾了一整天,从配置语法错误、权限缺失、事件订阅问题,到最后配置 key 名称错误,踩遍了所有可能的坑。
本文记录了完整的调试过程,希望能帮助其他开发者少走弯路。
目标
- ✅ 支持飞书私聊消息接收
- ✅ 支持单用户白名单限制
- ✅ 正常回复消息
准备工作
1. 创建飞书应用
- 访问 飞书开放平台
- 创建企业自建应用
- 获取
App ID和App Secret
2. 权限配置
进入应用的”权限管理”页面,添加以下权限:
contact:contact.base:readonly- 用于获取用户显示名称(必需)
3. 事件订阅配置
这是最关键的一步!进入”事件与回调”页面:
- 订阅方式:选择「使用 长连接 接收事件/回调」
- 订阅事件:必须添加
im.message.receive_v1- 接收消息事件(必须!)im.message.message_read_v1- 消息已读事件(可选)
注意:如果不订阅 im.message.receive_v1,飞书服务器永远不会推送消息事件给机器人,WebSocket 保持连接但收不到任何消息!
4. 发布版本
配置权限和事件后,点击”创建版本”并发布,才能生效。
OpenClaw 配置
1. 飞书通道配置
编辑 OpenClaw 配置文件 ~/.openclaw/openclaw.json:
{
"channels": {
"feishu": {
"enabled": true,
"appId": "cli_xxxxxxxxxxxxxxxx", // 替换为你的 App ID
"appSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // 替换为你的 App Secret
"domain": "feishu",
"dmPolicy": "allowlist",
"allowFrom": [
"ou_xxxxxxxxxxxxxxxxxxxxxxxxxx" // 替换为你的 User ID(ou_ 开头)
],
"groupPolicy": "allowlist",
"groupAllowFrom": []
}
}
}
关键配置说明:
dmPolicy: "allowlist"- 私聊使用白名单模式allowFrom- 注意这里不是dmAllowFrom!飞书插件使用allowFrom作为 DM 白名单groupPolicy: "allowlist"- 群聊也使用白名单(这里设置空数组,不响应群聊)
2. Agent 绑定配置
配置哪个 agent 处理飞书消息:
{
"bindings": [
{
"agentId": "main",
"match": {
"channel": "telegram",
"accountId": "your_telegram_account"
}
},
{
"agentId": "main",
"match": {
"channel": "feishu"
}
}
]
}
💡 踩坑记录:最初配置时,错误地在同一个 binding 中写了两个 channel,导致 JSON 语法错误(重复 key):
// ❌ 错误配置
{
"agentId": "main",
"match": {
"channel": "telegram",
"channel": "feishu", // 重复 key!
"accountId": "valt"
}
}
应该拆分成两个独立的 binding:
// ✅ 正确配置
[
{
"agentId": "main",
"match": {
"channel": "telegram",
"accountId": "valt"
}
},
{
"agentId": "main",
"match": {
"channel": "feishu"
}
}
]
3. 插件启用
确保 feishu 插件已启用:
{
"plugins": {
"entries": {
"feishu": {
"enabled": true
}
}
}
}
调试过程
问题 1:配置语法错误 - 重复 channel key
现象:
- 配置文件中 JSON 有重复的
channelkey - 虽然有警告,但初始启动看似正常
解决:拆分为两个独立的 binding 配置
问题 2:收不到消息 - WebSocket 已连接但无事件
现象:
- 日志显示 WebSocket client started, ws client ready
- 但从未收到任何消息事件
- 测试发送消息时完全无反应
排查过程:
- 检查配置的
dmPolicy和allowFrom- 看起来都正常 - 尝试放开所有权限(设置
dmPolicy: "open")- 仍然收不到 - 查看飞书插件源码,发现处理逻辑没问题
- 关键发现:WebSocket 连接成功不代表能收到消息
根本原因:飞书开发者后台没有配置事件订阅!
飞书使用的是事件推送机制:
- 用户给机器人发消息
- 飞书服务器检查你的应用是否订阅了”接收消息”事件
- 如果没有订阅,飞书就不会推送这个事件给你的 WebSocket
- OpenClaw 永远收不到消息
解决:
- 进入飞书开发者后台 → 事件与回调
- 订阅方式:选择”使用 长连接 接收事件/回调”
- 必须添加:
im.message.receive_v1事件 - 保存并发布版本
问题 3:权限错误 - 无法获取用户名称
现象:
The bot encountered a Feishu API permission error.
Permission grant URL: https://open.feishu.cn/app/cli_xxx/auth?q=contact:contact.base:readonly
原因:机器人尝试获取发送消息用户的显示名称时,缺少 contact:contact.base:readonly 权限。
解决:
- 打开权限授权链接
- 在权限管理中添加
contact:contact.base:readonly - 重新发布版本
问题 4:配置 key 名称错误
现象:
feishu[default]: received message from ou_xxx in oc_xxx (p2p)
feishu[default]: sender ou_xxx not in DM allowlist
明明配置了白名单,却提示不在 allowlist 中。
原因:使用了错误的配置 key 名称
错误配置:
{
"dmPolicy": "allowlist",
"dmAllowFrom": ["ou_xxx"] // ❌ 错误!
}
飞书插件实际上使用的是 allowFrom 而不是 dmAllowFrom。这是在配置时凭直觉添加了前缀,但插件代码中并未这样设计。
正确配置:
{
"dmPolicy": "allowlist",
"allowFrom": ["ou_xxx"] // ✅ 正确!
}
教训:修改配置前应该先查看插件的配置 schema 定义,而不是凭直觉猜测 key 名称。
验证方法
1. 检查 WebSocket 连接状态
openclaw logs --follow
看到以下日志表示连接成功:
[feishu] feishu[default]: WebSocket client started
[info]: [ '[ws]', 'ws client ready' ]
2. 测试消息接收
从飞书私聊给机器人发送消息,应该在日志中看到:
[feishu] feishu[default]: received message from ou_xxx in oc_xxx (p2p)
3. 测试消息回复
如果权限和事件都配置正确,应该能正常收到机器人回复。
最终配置汇总
飞书开发者后台
| 配置项 | 值 |
|---|---|
| 应用类型 | 企业自建应用 |
| 权限 | contact:contact.base:readonly |
| 订阅方式 | 长连接(WebSocket) |
| 订阅事件 | im.message.receive_v1 |
OpenClaw 配置
{
"channels": {
"feishu": {
"enabled": true,
"appId": "cli_xxxxxxxxxxxxxxxx",
"appSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"domain": "feishu",
"dmPolicy": "allowlist",
"allowFrom": [
"ou_xxxxxxxxxxxxxxxxxxxxxxxxxx"
],
"groupPolicy": "allowlist",
"groupAllowFrom": []
}
},
"bindings": [
{
"agentId": "main",
"match": {
"channel": "feishu"
}
}
],
"plugins": {
"entries": {
"feishu": {
"enabled": true
}
}
}
}
总结
从配置飞书通道开始到最终可用,遇到了以下问题:
- ✅ JSON 配置语法错误(重复 key)
- ✅ 飞书后台事件订阅缺失(最关键的坑)
- ✅ 权限不足
- ✅ 配置 key 名称错误
关键经验:
-
事件订阅是必须的:即使 WebSocket 连接成功,如果没有订阅
im.message.receive_v1事件,飞书服务器不会推送任何消息。 -
配置 key 名称要准确:应该查看插件的 schema 定义,而不是凭直觉或参考其他通道的命名习惯。
-
版本发布很重要:修改权限和事件配置后,必须创建版本并发布才能生效。
-
日志是最好的调试工具:遇到问题时,首先查看日志,根据错误信息和警告线索定位问题。
希望这篇记录能帮助其他开发者避免重复踩坑!🚀