Skip to content

fix(slack): emit message_sent hook on outbound delivery (mirror Telegram) #89942

Description

@rishitamrakar

Summary

@openclaw/slack does not emit the documented message_sent plugin hook
after a successful outbound Slack delivery, even though the hook is
contracted as observation-only for all outbound paths
(docs/plugins/hooks.md).

A plugin that registers api.on("message_sent", …) receives notifications
for outbound Telegram messages (Telegram fires runMessageSent directly in
extensions/telegram/src/bot/delivery.replies.ts) but never for Slack.

Versions

  • openclaw 2026.5.28
  • @openclaw/slack 2026.5.28
  • Reproduced on a clean local install (macOS, Node 25) with no patches.

Steps to reproduce (real behavior, no mocks)

  1. Install stock [email protected] + @openclaw/[email protected].
  2. Register a plugin that listens on the full Slack outbound hook chain:
api.on("message_received",      ev => log.info("📬 message_received"));
api.on("before_dispatch",       ev => log.info("➡️  before_dispatch"));
api.on("agent_end",             ev => log.info("🏁 agent_end"));
api.on("reply_payload_sending", ev => log.info("📦 reply_payload_sending"));
api.on("message_sending",       ev => log.info("📤 message_sending"));
api.on("message_sent",          ev => log.info("✅ message_sent  ← never fires"));

Configure the plugin with plugins.entries.<id>.hooks.allowConversationAccess = true.

  1. @mention the bot in a Slack channel where it's a member.
  2. Watch the gateway log.

Observed

[plugin] 📬 message_received fired channelId=slack
[plugin] ➡️  before_dispatch fired channelId=slack
[plugin] 🏁 agent_end fired
[plugin] 📦 reply_payload_sending fired channelId=slack
[plugin] 📤 message_sending fired channelId=slack content_preview="Yep, still here…"
                                                            ← message delivers to Slack here
                                                            ← message_sent NEVER fires

The Slack message lands in the channel successfully; only message_sent is silently missing.

Root cause (analysis on latest main)

grep -rln "runMessageSent\b" --include="*.ts" src/ extensions/

returns:

  • src/infra/outbound/deliver.ts — the deprecated deliverOutboundPayloads
  • extensions/telegram/src/bot/delivery.replies.ts — Telegram fires it directly
  • (test / mock files)

extensions/slack/ has zero references. The new sendDurableMessageBatch path
(src/channels/message/send.ts) — which the migrated Slack adapter routes through —
also does not call runMessageSent. Telegram works only because it has its own
adapter-side emit; Slack was migrated to the unified pipeline in 05eda57b3c
("refactor: migrate bundled plugins to message lifecycle") without adding the
equivalent message_sent emission.

Impact

Any plugin attempting to observe message delivery to build something on top
(per-message metrics, post-delivery UI overlays, analytics extractors, audit
logs) currently gets a complete blind spot for Slack while Telegram works
out of the box.

Proposed fix

Mirror Telegram's pattern in the Slack adapter: add an
emitSlackMessageSentHooks helper that fires both the plugin hook and the
internal hook, and call it from sendSlackOutboundMessage after each
successful (and failed) chat.postMessage.

PR with the fix attached.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions