← Tech

OpenClaw Feishu Plugin Conflict: From Deadlock to Unified Streaming Output

2026-03-18 DevOps OpenClawopenclaw-lark飞书插件冲突

Problem

After installing the official openclaw-lark plugin, the system had two Feishu plugins coexisting:

The two plugins conflicted, creating a deadlock:

Worse: both plugins competed for the feishu channel id. Different agents ended up on different reply paths — Reba and Aobing got streaming card output (typewriter effect), Tuoxie got static output (long wait, then all at once).

Root Cause

Trap 1: openclaw-lark has a hardcoded legacy plugin check

In src/core/tool-client.js, lines 111-119:

const feishuEntry = this.config.plugins?.entries?.feishu;

if (feishuEntry && feishuEntry.enabled !== false) {

throw new Error('❌ Legacy plugin is not disabled...');

}

As long as the built-in plugin isn't explicitly disabled, every openclaw-lark tool call throws immediately. Intended to force migration, but didn't account for the built-in plugin serving other purposes.

Trap 2: openclaw-lark has a hidden assumption about the default account

In src/core/accounts.js, getLarkAccount() has an implicit design rule: the default account's credentials must be at the top-level of channels.feishu, not under accounts.default.

const accountOverride = accountMap && requestedId !== DEFAULT_ACCOUNT_ID

? accountMap[requestedId]

: undefined; // default account never reads accounts.default!

Other accounts (media, aobing) go through accountMap[requestedId] normally. But the default account always falls through to the top-level only.

So when feishu.enabled = false and openclaw-lark takes over, if appId/appSecret are under accounts.default (the intuitive location), the default account gets configured = false, is skipped by getEnabledLarkAccounts(), and its WebSocket never starts — silently.

Fix

Two steps:

Step 1: Disable the built-in plugin

cat ~/.openclaw/openclaw.json | \

jq '.plugins.entries.feishu.enabled = false' \

> /tmp/oc.json && mv /tmp/oc.json ~/.openclaw/openclaw.json

Step 2: Promote default account credentials to the top level

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

Restart the Gateway. Done.

Results

Three GitHub Issues Filed

Key Takeaways

Framework-level "implicit conventions" are nearly impossible to discover from docs alone. Both traps were only found by reading the source. When "the config looks right but it just doesn't work," read the source — don't keep tweaking parameters.

Also: when two plugins compete for the same channel id, whoever wins is non-deterministic. In multi-account setups, different agents may end up on different code paths, behaving completely differently. Very hard to debug.