Skip to content

feat(feishu): add reaction event support (created/deleted)#16716

Merged
Takhoffman merged 4 commits intoopenclaw:mainfrom
schumilin:feat/feishu-reaction-events
Feb 28, 2026
Merged

feat(feishu): add reaction event support (created/deleted)#16716
Takhoffman merged 4 commits intoopenclaw:mainfrom
schumilin:feat/feishu-reaction-events

Conversation

@schumilin
Copy link
Contributor

@schumilin schumilin commented Feb 15, 2026

Why this matters

In Feishu (and Lark), emoji reactions are a core part of how people communicate — they're used constantly to acknowledge messages, express agreement, or give quick feedback without interrupting the conversation flow. This is especially true in Feishu&Lark workplace culture where a 👍 or a +1 (meaning "I agree") carries real conversational weight.

Right now, OpenClaw's Feishu plugin cannot receive reaction events at all. When a user reacts to the bot's message, nothing happens — the bot is blind to it. This makes the bot feel unresponsive and disconnected from the natural rhythm of Feishu conversations.

The infrastructure is already 90% there:

  • reactions.ts has full CRUD (addReactionFeishu, removeReactionFeishu, listReactionsFeishu)
  • typing.ts uses the reaction API for typing indicators (proving the pipeline works)
  • channel.ts declares capabilities.reactions: true

The only missing piece is registering the inbound event handler in monitor.ts. This PR closes that gap.


What this does

  • Registers im.message.reaction.created_v1 and im.message.reaction.deleted_v1 event handlers in the Feishu EventDispatcher
  • Routes reaction events as synthetic inbound messages through handleFeishuMessage, giving the agent a dedicated turn to process each reaction and respond (e.g., react back)
  • Filters out bot self-reactions (by operator_type), typing indicator emoji, and reaction-removed events

Changes

extensions/feishu/src/monitor.ts (~130 lines added):

  • FeishuReactionEvent type definition matching the Feishu API schema
  • handleReactionEvent() — processes reaction events with proper filtering and routing
  • Event handler registration in registerEventHandlers()

Design decisions

Synthetic messages over system events

We initially tried enqueueSystemEvent() (matching the Slack plugin pattern), but found that system events are passive — they only surface during the next agent turn and may be merged or delayed. For Feishu's interactive reaction culture, the agent needs a dedicated turn to process each reaction and respond in kind. Synthetic messages through handleFeishuMessage achieve this.

DM routing for all reactions

Feishu's DM chat_id also uses the oc_ prefix (unlike most platforms), making it impossible to distinguish DM vs group by prefix alone. To avoid group allowlist issues, all reactions are routed as p2p messages via the sender's open_id. This works correctly for single-agent setups. Group-specific session routing can be refined in a follow-up.

Safety filters

  • Bot self-reactions filtered by operator_type === "app" and open_id match
  • Typing indicator (Typing emoji) excluded — used internally
  • Fire-and-forget: reaction processing never blocks message handling

Setup required

Users must subscribe to im.message.reaction.created_v1 in their Feishu Open Platform app console (Events & Callbacks).

Tested

Dogfooded on a live Feishu bot:

  1. ✅ User reacts → bot receives event → agent processes and reacts back
  2. ✅ Bot self-reactions correctly filtered (no loops)
  3. ✅ Typing indicator reactions ignored
  4. ✅ DM reactions route to correct session

Greptile Summary

Adds support for Feishu reaction events (im.message.reaction.created_v1 and im.message.reaction.deleted_v1) by registering handlers in the event dispatcher. Reactions are dispatched as synthetic DM messages through handleFeishuMessage, giving the agent a dedicated turn to process and respond to each reaction. The implementation includes proper filtering for bot self-reactions, typing indicator emoji, and reaction-removed events.

Key changes:

  • Added FeishuReactionEvent type definition matching Feishu API schema
  • Implemented handleReactionEvent() function with filtering logic and synthetic message creation
  • Registered reaction event handlers in registerEventHandlers()
  • Routes all reactions as p2p messages via sender's open_id to avoid group allowlist complexity

Notes:

  • Requires users to subscribe to reaction events in Feishu Open Platform console
  • Group reactions currently route to sender's session rather than group session (documented limitation)
  • Implementation follows fire-and-forget pattern to avoid blocking message handling

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk - adds well-isolated new functionality with proper error handling
  • The implementation is straightforward and follows existing patterns (similar to Slack's reaction handling via system events). The code has good defensive checks (bot self-reactions, typing indicator filtering, error handling). One logical issue exists with message ID collision risk when reactions happen within 1ms, and one style improvement opportunity for unused code cleanup. The synthetic message approach is well-documented and aligns with the stated goal of giving agents dedicated turns for reactions.
  • No files require special attention

Last reviewed commit: 80d4b32

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

@openclaw-barnacle openclaw-barnacle bot added channel: feishu Channel integration: feishu size: S labels Feb 15, 2026
@schumilin schumilin force-pushed the feat/feishu-reaction-events branch 2 times, most recently from 0ab7469 to 80d4b32 Compare February 15, 2026 02:24
@steipete steipete closed this Feb 16, 2026
@steipete steipete reopened this Feb 17, 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.

1 file reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@schumilin schumilin force-pushed the feat/feishu-reaction-events branch 3 times, most recently from b1e1384 to 5c7677c Compare February 17, 2026 10:31
@schumilin schumilin force-pushed the feat/feishu-reaction-events branch 4 times, most recently from eef3ca3 to 6e3f4f1 Compare February 18, 2026 12:52
schumilin and others added 4 commits February 27, 2026 20:36
Register im.message.reaction.created_v1 and im.message.reaction.deleted_v1
event handlers in the Feishu monitor, enabling bots to receive and respond
to emoji reactions on messages.

What this does:
- Adds reaction event handlers to the EventDispatcher registration
- Routes reaction events as synthetic inbound messages through the standard
  handleFeishuMessage pipeline, ensuring the agent gets a dedicated turn to
  process each reaction and respond appropriately
- Filters out bot self-reactions (by operator_type and open_id), typing
  indicator emoji, and reaction-removed events
- Uses crypto.randomUUID() for synthetic message IDs to prevent dedup
  collision when multiple reactions arrive within the same millisecond

Design decisions:
- Synthetic messages over system events: Reactions are dispatched as
  synthetic text messages through handleFeishuMessage rather than
  enqueueSystemEvent. This ensures the agent receives a dedicated turn to
  process each reaction (system events are passive and may be merged/delayed).
- DM routing for all reactions: All reactions are routed as p2p messages
  via the sender's open_id. Feishu DM chat_ids also use 'oc_' prefix, so
  we cannot distinguish group vs DM by prefix alone. This avoids group
  allowlist issues and works correctly for the common case.
- Fire-and-forget in webhook mode: Reaction handlers respect the
  fireAndForget flag to avoid blocking the HTTP response.

Limitations:
- Group chat reactions are routed to the sender's DM session rather than
  the group session. This works for single-agent setups but may need
  refinement for multi-agent configurations.

Note: Users must subscribe to im.message.reaction.created_v1 (and optionally
im.message.reaction.deleted_v1) in their Feishu app console for this to work.
Previously, the reaction event handler dispatched synthetic messages for
ALL reactions a user made, including reactions on other people's messages
in unrelated chats. This caused the agent to receive spurious
notifications and respond inappropriately.

Now the handler fetches the reacted message via getMessageFeishu and
verifies that the message was sent by the bot before creating a
synthetic event. Reactions on non-bot messages are silently dropped
with a debug log.

If the reacted message cannot be fetched (e.g. deleted message,
permission error), the reaction is also skipped to avoid routing
potentially irrelevant events to the agent.

When botOpenId is not available (e.g. probe failed at startup), the
sender check is skipped to maintain backward compatibility.
@Takhoffman Takhoffman force-pushed the feat/feishu-reaction-events branch from f1459ba to 8ba4efa Compare February 28, 2026 02:54
@Takhoffman Takhoffman merged commit 8241145 into openclaw:main Feb 28, 2026
9 checks passed
@Takhoffman
Copy link
Contributor

PR #16716 - feat(feishu): add reaction event support (created/deleted) (#16716)

Merged via squash.

  • Merge commit: 8241145
  • Verified: pnpm install --frozen-lockfile, pnpm build, pnpm check, pnpm test:macmini
  • Changes made:
    • extensions/feishu/src/monitor.ts
    • extensions/feishu/src/monitor.reaction.test.ts
    • extensions/feishu/src/send.ts
    • CHANGELOG.md
  • Why these changes were made:
    • Keep Feishu reaction ingress safe and deterministic: fail closed when bot identity is unavailable, bound message-sender verification latency, preserve webhook fire-and-forget behavior, and test the production reaction resolver directly instead of a test-side reimplementation.
  • Changelog: CHANGELOG.md updated=true required=true opt_out=false

Thanks @schumilin!

r4jiv007 pushed a commit to r4jiv007/openclaw that referenced this pull request Feb 28, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
mylukin pushed a commit to mylukin/openclaw that referenced this pull request Feb 28, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 28, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 28, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
(cherry picked from commit 4b54d39)
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 28, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
(cherry picked from commit 4b54d39)
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Feb 28, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
(cherry picked from commit 4b54d39)
vincentkoc pushed a commit to Sid-Qin/openclaw that referenced this pull request Feb 28, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
vincentkoc pushed a commit to rylena/rylen-openclaw that referenced this pull request Feb 28, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
newtontech pushed a commit to newtontech/openclaw-fork that referenced this pull request Feb 28, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Mar 1, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
wanjizheng pushed a commit to wanjizheng/openclaw that referenced this pull request Mar 1, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 1, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
(cherry picked from commit 8241145)

# Conflicts:
#	extensions/feishu/src/monitor.ts
ansh pushed a commit to vibecode/openclaw that referenced this pull request Mar 2, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
steipete pushed a commit to Sid-Qin/openclaw that referenced this pull request Mar 2, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
safzanpirani pushed a commit to safzanpirani/clawdbot that referenced this pull request Mar 2, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
steipete pushed a commit to Sid-Qin/openclaw that referenced this pull request Mar 2, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
venjiang pushed a commit to venjiang/openclaw that referenced this pull request Mar 2, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
robertchang-ga pushed a commit to robertchang-ga/openclaw that referenced this pull request Mar 2, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
execute008 pushed a commit to execute008/openclaw that referenced this pull request Mar 2, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 3, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
(cherry picked from commit 8241145)

# Conflicts:
#	extensions/feishu/src/monitor.ts
dorgonman pushed a commit to kanohorizonia/openclaw that referenced this pull request Mar 3, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
eminemead pushed a commit to eminemead/evi that referenced this pull request Mar 3, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
(cherry picked from commit 8241145)
sachinkundu pushed a commit to sachinkundu/openclaw that referenced this pull request Mar 6, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
…16716) thanks @schumilin

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: feishu Channel integration: feishu size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants