openclaw - ✅(Solved) Fix Feature: Fire message_sending hook in reply dispatch path (not just proactive sends) [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#69606Fetched 2026-04-22 07:50:20
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants

Fix Action

Workaround

Layer 1 (prompt injection via before_prompt_build) handles ~99% of cases. But for defense-in-depth content filtering, the missing hook in the reply path is a gap.

PR fix notes

PR #38340: fix(dispatcher): add beforeDeliver hook, wire message_sending for Discord

Description (problem / solution / changelog)

Problem

Discord same-surface replies bypass deliverOutboundPayloads entirely, which means message_sending plugin hooks never fire. Plugins that rely on this hook to strip or transform outbound text (e.g. removing metadata blocks injected by the LLM) have no way to intercept Discord replies.

The message_sending hook works correctly for cross-surface routing (e.g. web chat → Discord), but not for Discord → Discord (same-surface) because the Discord message handler uses its own deliver callback that calls deliverDiscordReply directly.

Solution

  1. Adds an optional beforeDeliver callback to ReplyDispatcherOptions — runs just before deliver() and may return a modified payload or null to cancel delivery. This is a general-purpose mechanism that any channel can opt into.

  2. Wires beforeDeliver in the Discord message handler to call runMessageSending from the plugin hook runner, matching the behavior that deliverOutboundPayloads already provides for cross-surface routing.

Changes

  • src/auto-reply/reply/reply-dispatcher.ts — New beforeDeliver option + call site in enqueue()
  • src/discord/monitor/message-handler.process.tsbeforeDeliver implementation calling message_sending hooks

Follow-up

Other channel handlers (Signal, Slack, iMessage, web chat) have similar deliver callbacks that bypass the hook pipeline. They could adopt the same beforeDeliver pattern in follow-up PRs.

Changed files

  • extensions/discord/src/monitor/message-handler.process.ts (modified, +43/-0)
  • src/auto-reply/reply/reply-dispatcher.ts (modified, +20/-1)
  • src/plugin-sdk/reply-runtime.ts (modified, +1/-0)

Code Example

LLM → dispatch → createReplyDispatcher → deliver → deliverTextOrMediaReply → sendText → Channel API
RAW_BUFFERClick to expand / collapse

Problem

The message_sending hook currently only fires in the deliverOutboundPayloads path — which handles proactive sends (message tool, session warnings, cron delivery).

Agent replies go through a completely separate path:

LLM → dispatch → createReplyDispatcher → deliver → deliverTextOrMediaReply → sendText → Channel API

This path has reply_dispatch (a claiming hook) but no content-modifying hook like message_sending.

Impact

Plugins that register message_sending hooks for content filtering/modifying cannot intercept agent replies — only proactive sends. This makes message_sending insufficient for output-level content gates.

Concrete Use Case

We built a SPINE privacy gate plugin that scans outbound messages for content that shouldn't leak into certain channels (e.g., personal details in work channels). The plugin registers message_sending and works for proactive sends, but agent replies bypass it entirely.

Expected Behavior

message_sending should fire for all outbound text before it reaches the channel API, regardless of whether it's an agent reply or a proactive send.

Evidence

  • deliverOutboundPayloads (deliver-BNvlWd4P.js) calls applyMessageSendingHook
  • deliverTextOrMediaReply (reply-payload-Db_8BQiX.js) calls params.sendText(chunk) directly ❌
  • createReplyDispatcher (dispatch-JNo_iJw5.js) passes options.deliver which goes to channel-specific delivery without hooks ❌

Workaround

Layer 1 (prompt injection via before_prompt_build) handles ~99% of cases. But for defense-in-depth content filtering, the missing hook in the reply path is a gap.

Suggestion

Either:

  1. Call runMessageSending in the reply dispatch deliver path (before sendText)
  2. Add a new reply_content_sending modifying hook in the dispatch path
  3. Make reply_dispatch support content modification without requiring full delivery takeover

Version: OpenClaw OpenClaw 2026.4.15 (041266a)

extent analysis

TL;DR

To fix the issue, consider adding a message_sending hook call in the reply dispatch deliver path or introducing a new reply_content_sending modifying hook.

Guidance

  • Investigate calling runMessageSending in the deliverTextOrMediaReply function before sendText to ensure content filtering for agent replies.
  • Evaluate the feasibility of adding a new reply_content_sending hook in the dispatch path to support content modification without full delivery takeover.
  • Review the reply_dispatch hook to determine if it can be modified to support content modification without requiring full delivery control.
  • Verify that any changes do not introduce performance or security issues, especially considering the 99% coverage of the existing before_prompt_build layer.

Example

No code snippet is provided due to the complexity and variability of the potential solutions.

Notes

The solution may require careful consideration of performance and security implications, especially given the existing workaround's high coverage rate. The choice between introducing a new hook or modifying the existing reply_dispatch hook should be based on the specific requirements and constraints of the system.

Recommendation

Apply a workaround by calling runMessageSending in the reply dispatch deliver path, as this seems to be the most direct approach to ensuring content filtering for agent replies, given the current system architecture.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING