openclaw - 💡(How to fix) Fix [Bug]: `message_sent` / `before_message_write` hooks never fire for webchat and openclaw-tui outbound paths [1 comments, 2 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#70928Fetched 2026-04-24 10:37:46
View on GitHub
Comments
1
Participants
2
Timeline
1
Reactions
0
Timeline (top)
commented ×1

Outbound message lifecycle hooks — including message_sent, message_sending, agent_end, and before_message_write — are never triggered when the assistant replies through the webchat or openclaw-tui channels. This is a specific manifestation of the fragmentation described in #50126, which currently enumerates Telegram, outbound-send-service, Discord, and WhatsApp, but does not mention webchat/tui.

Any hook that depends on knowing when an assistant reply has been emitted is silently broken for users running the default local install (webchat / openclaw-tui are the primary first-run surfaces).

Error Message

  1. Actual: handler is never invoked. No entry in the hook log. No error either — it is silent.

Root Cause

  • Any workspace or plugin hook that wants to react to the assistant sending a reply cannot observe those replies when the surface is webchat or openclaw-tui.
  • Common use-cases that quietly break:
    • Desktop / OS notification when assistant finishes a reply
    • Conversation-stream / audit log consumers
    • Metrics/telemetry on outbound throughput
    • Guardrails that want a post-send hook to verify compliance
  • Because these are the default surfaces, new OpenClaw users will silently observe zero hook fires and conclude hooks are broken end-to-end.

Fix Action

Fix / Workaround

Scanning the bundled dist shows that hooks for the assistant reply lifecycle are attached at the channel delivery layer (e.g. deliverOutboundPayloads / deliverReplies). #50126 describes this in detail and lists which channels are and are not wired up. Webchat and openclaw-tui do not appear in any of the enumerated dispatch tables in #50126, and empirically do not appear to invoke the hook runner on outbound reply.

By contrast, compaction-lifecycle hooks (before_compaction, after_compaction) are invoked from core runtime code (compaction-runtime-context-*.js, selection-*.js) and fire correctly on webchat/tui. This is additional evidence that the gap is specifically in the webchat/tui outbound path, not in the hook registration or dispatcher itself.

  • Option B (local fix): in the webchat/openclaw-tui outbound dispatch path, pass sessionKeyForInternalHooks and hookRunner (or their equivalents) so message_sending / message_sent fire symmetrically with the core deliverOutboundPayloads path.
  • Option A (architectural): follow the OutboundDeliveryObserver suggestion in #50126 so every channel dispatch path goes through one hook-firing seam.

Code Example

---
   metadata:
     openclaw:
       emoji: "📩"
       events: ["message_sent"]
   ---

---

"hooks": {
     "internal": {
       "enabled": true,
       "entries": {
         "notification-on-send": { "enabled": true }
       }
     }
   }
RAW_BUFFERClick to expand / collapse

[Bug]: message_sent / before_message_write hooks never fire for webchat and openclaw-tui outbound paths

Repo: openclaw/openclaw Related: #50126 (umbrella: inconsistent hook coverage across outbound paths), #47472 (plugin hook never fires for extension plugins)


Summary

Outbound message lifecycle hooks — including message_sent, message_sending, agent_end, and before_message_write — are never triggered when the assistant replies through the webchat or openclaw-tui channels. This is a specific manifestation of the fragmentation described in #50126, which currently enumerates Telegram, outbound-send-service, Discord, and WhatsApp, but does not mention webchat/tui.

Any hook that depends on knowing when an assistant reply has been emitted is silently broken for users running the default local install (webchat / openclaw-tui are the primary first-run surfaces).

Impact

  • Any workspace or plugin hook that wants to react to the assistant sending a reply cannot observe those replies when the surface is webchat or openclaw-tui.
  • Common use-cases that quietly break:
    • Desktop / OS notification when assistant finishes a reply
    • Conversation-stream / audit log consumers
    • Metrics/telemetry on outbound throughput
    • Guardrails that want a post-send hook to verify compliance
  • Because these are the default surfaces, new OpenClaw users will silently observe zero hook fires and conclude hooks are broken end-to-end.

Environment

  • OpenClaw: 2026.4.20
  • Node: v24.13.0
  • OS: macOS 25.4.0 (Darwin, arm64)
  • Surfaces tested: webchat, openclaw-tui
  • Agent: laststance-manager (default workspace-bound agent)
  • Runtime: anthropic/claude-opus-4-7

Reproduction

  1. Create a workspace hook, for example ~/clawd/hooks/notification-on-send/HOOK.md:

    ---
    metadata:
      openclaw:
        emoji: "📩"
        events: ["message_sent"]
    ---

    with a companion handler.ts that calls terminal-notifier or simply writes a line to a log file.

  2. Enable the hook in ~/.openclaw/openclaw.json:

    "hooks": {
      "internal": {
        "enabled": true,
        "entries": {
          "notification-on-send": { "enabled": true }
        }
      }
    }
  3. Start an openclaw-tui or webchat session and have the assistant produce any reply.

  4. Expected: handler runs → notification fires / log line appended.

  5. Actual: handler is never invoked. No entry in the hook log. No error either — it is silent.

We also verified the same non-firing behaviour for before_message_write and agent_end. The hook registration itself is correct (the same HOOK.md + handler.ts pair does fire under different event names such as before_compaction; see notes below).

What we observed in the source

Scanning the bundled dist shows that hooks for the assistant reply lifecycle are attached at the channel delivery layer (e.g. deliverOutboundPayloads / deliverReplies). #50126 describes this in detail and lists which channels are and are not wired up. Webchat and openclaw-tui do not appear in any of the enumerated dispatch tables in #50126, and empirically do not appear to invoke the hook runner on outbound reply.

By contrast, compaction-lifecycle hooks (before_compaction, after_compaction) are invoked from core runtime code (compaction-runtime-context-*.js, selection-*.js) and fire correctly on webchat/tui. This is additional evidence that the gap is specifically in the webchat/tui outbound path, not in the hook registration or dispatcher itself.

Suggested direction (aligned with #50126)

Prefer the minimal, channel-local fix first, and leave the architectural unification for #50126 proper:

  • Option B (local fix): in the webchat/openclaw-tui outbound dispatch path, pass sessionKeyForInternalHooks and hookRunner (or their equivalents) so message_sending / message_sent fire symmetrically with the core deliverOutboundPayloads path.
  • Option A (architectural): follow the OutboundDeliveryObserver suggestion in #50126 so every channel dispatch path goes through one hook-firing seam.

Happy to open a PR targeting Option B for the webchat/tui paths once a maintainer confirms the preferred direction. If it is already covered by the in-flight PR #12584 ("wire outbound message lifecycle hooks"), please point us there and we can help test / verify coverage for webchat + openclaw-tui.

Notes

  • Workaround today: call terminal-notifier (or any other notifier) from the assistant reply itself via the exec tool. This works but is a per-turn manual step and is exactly the kind of boilerplate hooks are supposed to eliminate.
  • We are happy to provide additional logs, a minimal reproduction repo, or a PR against Option B — whichever is most useful to maintainers.

extent analysis

TL;DR

The most likely fix is to implement a local fix for the webchat and openclaw-tui outbound paths by passing the necessary parameters to invoke the message_sending and message_sent hooks.

Guidance

  • Review the deliverOutboundPayloads function to understand how hooks are currently being invoked for other channels.
  • Implement a local fix (Option B) by passing sessionKeyForInternalHooks and hookRunner in the webchat and openclaw-tui outbound dispatch paths.
  • Verify that the hooks are firing correctly by checking the hook log and testing the notification functionality.
  • Consider implementing the architectural fix (Option A) suggested in #50126 for a more unified solution.

Example

// Example of how to pass sessionKeyForInternalHooks and hookRunner in the webchat outbound dispatch path
const sessionKey = 'webchat-session-key';
const hookRunner = getHookRunner();
deliverOutboundPayloads(webchatPayload, sessionKey, hookRunner);

Notes

  • The local fix (Option B) may not be the most scalable solution, and the architectural fix (Option A) should be considered for a more unified approach.
  • The workaround of calling terminal-notifier from the assistant reply itself is not a long-term solution and should be replaced with a proper hook implementation.

Recommendation

Apply the local fix (Option B) to invoke the message_sending and message_sent hooks for the webchat and openclaw-tui channels, and consider implementing the architectural fix (Option A) in the future for a more unified solution.

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

openclaw - 💡(How to fix) Fix [Bug]: `message_sent` / `before_message_write` hooks never fire for webchat and openclaw-tui outbound paths [1 comments, 2 participants]