安装了飞书官方出品的 openclaw-lark 插件后,系统里同时存在两套飞书插件:
两套插件互相打架,形成死锁:
feishu.enabled = true:三个账号(拖鞋/热巴/敖丙)WebSocket 正常,但所有飞书工具调用报错「检测到旧版插件未禁用」feishu.enabled = false:工具恢复正常,但主账号(拖鞋)WebSocket 不启动,收不到消息更烦的是,两套插件都在抢 feishu 这个 channel id,导致不同 Agent 的回复路径不一样:热巴和敖丙走 openclaw-lark 的流式卡片(打字机效果),拖鞋走内置插件的静态路径(等很久一次蹦出来)。
src/core/tool-client.js 第 111-119 行:
const feishuEntry = this.config.plugins?.entries?.feishu;
if (feishuEntry && feishuEntry.enabled !== false) {
throw new Error('❌ 检测到旧版插件未禁用...');
}
只要内置插件没被显式禁用,openclaw-lark 的所有工具调用直接抛异常拒绝执行。本意是强制迁移,但没考虑到内置插件还承担着其他功能。
src/core/accounts.js 的 getLarkAccount() 里有一个隐藏假设:default 账号的凭证必须放在 channels.feishu 顶层,而不是 accounts.default 下。
const accountOverride = accountMap && requestedId !== DEFAULT_ACCOUNT_ID
? accountMap[requestedId]
: undefined; // default 账号不读 accounts.default!
其他账号(media、aobing)走 accountMap[requestedId],正常读取。但 default 账号永远走顶层。
所以当 feishu.enabled = false 时,内置插件停了,openclaw-lark 接管,但因为 appId/appSecret 放在 accounts.default 里而不是顶层,default 账号 configured = false,被跳过,WebSocket 不启动。
整个过程没有报错,就是静默不连接。
两步搞定:
第一步:禁用内置插件
cat ~/.openclaw/openclaw.json | \
jq '.plugins.entries.feishu.enabled = false' \
> /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
第二步:把 default 账号凭证提升到顶层
cat ~/.openclaw/openclaw.json | jq '
.channels.feishu.appId = .channels.feishu.accounts.default.appId |
.channels.feishu.appSecret = .channels.feishu.accounts.default.appSecret |
.channels.feishu.dmPolicy = "open" |
.channels.feishu.groupPolicy = "open" |
.channels.feishu.allowFrom = ["*"]
' > /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json
重启 Gateway,搞定。
框架级配置的「隐式约定」很难靠文档发现。 这两个坑都是通过读源码才搞清楚的。遇到「配置看起来没问题但就是不工作」的情况,先查源码,不要一直试参数。
另一个教训:两个插件争同一个 channel id 时,谁在前谁赢,结果不确定。 多账号场景下,不同 Agent 可能走不同路径,表现完全不一样,很难调试。