Skip to content

feat(feishu): sync community contributions from clawdbot-feishu#12662

Merged
cpojer merged 1 commit intoopenclaw:mainfrom
doodlewind:feat/feishu-sync-upstream
Feb 10, 2026
Merged

feat(feishu): sync community contributions from clawdbot-feishu#12662
cpojer merged 1 commit intoopenclaw:mainfrom
doodlewind:feat/feishu-sync-upstream

Conversation

@doodlewind
Copy link
Contributor

@doodlewind doodlewind commented Feb 9, 2026

Summary

Sync community contributions from the independent feishu plugin repo (clawdbot-feishu 0171c12..ee8312a):

  • Message deduplication: Prevents duplicate message processing on WebSocket reconnect/retry, with configurable cache size and throttled cleanup
  • Webhook connection mode: Adds HTTP webhook support for Lark International which does not support WebSocket event subscription
  • Topic session isolation: Per-thread/topic session isolation inside group chats, using chatId:topic:rootId as peer ID
  • Dynamic agent creation: Auto-create agents for DM users based on configurable templates
  • Card schema 2.0: Upgrade interactive card format for proper markdown rendering

Closes

Test plan

  • Verify WebSocket mode still works with dedup enabled
  • Test webhook mode with Lark International app
  • Test topic session isolation in group chats with multiple threads
  • Verify DM dynamic agent creation with dynamicAgentCreation.enabled: true
  • Confirm card rendering with schema 2.0 format

🤖 Generated with Claude Code

Greptile Overview

Greptile Summary

This PR syncs Feishu plugin changes from an upstream community repo, adding (1) in-memory message deduplication to reduce duplicate handling on reconnect/redelivery, (2) a webhook-based connection mode (HTTP server + Lark adapter) for environments without WS subscriptions, (3) optional topic/thread session isolation in group chats via a derived peer id, (4) dynamic DM agent creation by writing new agents/bindings into the config file, and (5) interactive card schema 2.0 formatting for improved markdown rendering.

Key touch points are extensions/feishu/src/bot.ts (inbound parsing/routing/dedup + dynamic agent creation), extensions/feishu/src/monitor.ts (WS vs webhook listener), and extensions/feishu/src/config-schema.ts/types.ts (new config knobs).

Confidence Score: 3/5

  • This PR is close but has a few functional issues that can break DM routing/dynamic agent creation and multi-account webhook startup.
  • Core changes are reasonable, but there are clear inconsistencies in routing peer kinds (dm vs direct), dynamic-agent config writes not being applied to dispatch, and a deterministic port-collision failure mode for multi-account webhook setups that will prevent monitoring from starting.
  • extensions/feishu/src/bot.ts, extensions/feishu/src/dynamic-agent.ts, extensions/feishu/src/monitor.ts

(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!

Sync community contributions from the independent feishu plugin repo
(clawdbot-feishu 0171c12..ee8312a):

- Card format upgrade to schema 2.0 for proper markdown rendering
- Message dedup mechanism to prevent duplicate processing on WS reconnect
- Dynamic agent creation for DM users
- Topic-based session isolation for group chats
- Webhook connection mode support for Lark

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openclaw-barnacle openclaw-barnacle bot added the channel: feishu Channel integration: feishu label Feb 9, 2026
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +688 to 696
let route = core.channel.routing.resolveAgentRoute({
cfg,
channel: "feishu",
accountId: account.accountId,
peer: {
kind: isGroup ? "group" : "direct",
id: isGroup ? ctx.chatId : ctx.senderOpenId,
id: peerId,
},
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent peer kind

resolveAgentRoute is first called with peer.kind set to "direct" for DMs, but if dynamic agent creation triggers you re-resolve using peer.kind: "dm" (and dynamic-agent.ts also creates bindings with peer.kind: "dm"). If the routing/binding system only recognizes "direct" (as used elsewhere in the codebase) this will prevent the new binding from ever matching, leaving DMs stuck on the default route.

This should use the same peer kind consistently (typically "direct") for both binding creation and route resolution.

Also appears in: extensions/feishu/src/dynamic-agent.ts:29-33, 67-71, 109-112.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/feishu/src/bot.ts
Line: 688:696

Comment:
**Inconsistent peer kind**

`resolveAgentRoute` is first called with `peer.kind` set to `"direct"` for DMs, but if dynamic agent creation triggers you re-resolve using `peer.kind: "dm"` (and `dynamic-agent.ts` also creates bindings with `peer.kind: "dm"`). If the routing/binding system only recognizes `"direct"` (as used elsewhere in the codebase) this will prevent the new binding from ever matching, leaving DMs stuck on the default route.

This should use the same peer kind consistently (typically `"direct"`) for both binding creation and route resolution.

Also appears in: `extensions/feishu/src/dynamic-agent.ts:29-33, 67-71, 109-112`.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +194 to +200
const port = account.config.webhookPort ?? 3000;
const path = account.config.webhookPath ?? "/feishu/events";

log(`feishu[${accountId}]: starting Webhook server on port ${port}, path ${path}...`);

const server = http.createServer();
server.on("request", Lark.adaptDefault(path, eventDispatcher, { autoChallenge: true }));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Port collision across accounts

In webhook mode, monitorWebhook defaults to webhookPort ?? 3000 for every account. If multiple Feishu accounts are enabled with connectionMode: "webhook" and don’t explicitly set distinct ports, the second server will fail to listen() (EADDRINUSE) and monitoring for that account will never start.

Consider requiring an explicit port in webhook mode, or deriving unique defaults per account / running a single shared server with per-account routing.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/feishu/src/monitor.ts
Line: 194:200

Comment:
**Port collision across accounts**

In webhook mode, `monitorWebhook` defaults to `webhookPort ?? 3000` for every account. If multiple Feishu accounts are enabled with `connectionMode: "webhook"` and don’t explicitly set distinct ports, the second server will fail to `listen()` (EADDRINUSE) and monitoring for that account will never start.

Consider requiring an explicit port in webhook mode, or deriving unique defaults per account / running a single shared server with per-account routing.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +700 to +707
let effectiveCfg = cfg;
if (!isGroup && route.matchedBy === "default") {
const dynamicCfg = feishuCfg?.dynamicAgentCreation as DynamicAgentCreationConfig | undefined;
if (dynamicCfg?.enabled) {
const runtime = getFeishuRuntime();
const result = await maybeCreateDynamicAgent({
cfg,
runtime,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config writes ignored

maybeCreateDynamicAgent writes the updated config file via runtime.config.writeConfigFile(updatedCfg), but handleFeishuMessage continues dispatching using the original cfg (e.g. dispatchReplyFromConfig({ ctx, cfg, ... })). Since routing and agent selection are config-driven, the newly-created agent/binding may not take effect for the current message (and possibly subsequent messages depending on how cfg is sourced).

If dynamic agent creation is intended to apply immediately, the dispatch path should use effectiveCfg (or otherwise reload config after the write) consistently for routing + dispatch.

Also appears in: extensions/feishu/src/bot.ts:712-726 where effectiveCfg is set but not used later.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/feishu/src/bot.ts
Line: 700:707

Comment:
**Config writes ignored**

`maybeCreateDynamicAgent` writes the updated config file via `runtime.config.writeConfigFile(updatedCfg)`, but `handleFeishuMessage` continues dispatching using the original `cfg` (e.g. `dispatchReplyFromConfig({ ctx, cfg, ... })`). Since routing and agent selection are config-driven, the newly-created agent/binding may not take effect for the current message (and possibly subsequent messages depending on how `cfg` is sourced).

If dynamic agent creation is intended to apply immediately, the dispatch path should use `effectiveCfg` (or otherwise reload config after the write) consistently for routing + dispatch.

Also appears in: `extensions/feishu/src/bot.ts:712-726` where `effectiveCfg` is set but not used later.

How can I resolve this? If you propose a fix, please make it concise.

@cpojer cpojer merged commit 5c2cb6c into openclaw:main Feb 10, 2026
25 checks passed
trevorgordon981 pushed a commit to trevorgordon981/openclaw that referenced this pull request Feb 10, 2026
…claw#12662)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
trevorgordon981 pushed a commit to trevorgordon981/openclaw that referenced this pull request Feb 10, 2026
…claw#12662)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
lucasmpramos pushed a commit to butley/openclaw that referenced this pull request Feb 10, 2026
…claw#12662)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Hansen1018 pushed a commit to Hansen1018/openclaw that referenced this pull request Feb 10, 2026
skyhawk14 pushed a commit to skyhawk14/openclaw that referenced this pull request Feb 13, 2026
…claw#12662)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment