openclaw - 💡(How to fix) Fix [Feature]: Confirm before_dispatch is the right hook for forwarding selected inbound messages to an external webhook (skip agent dispatch) [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#78568Fetched 2026-05-07 03:35:18
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
2
Timeline (top)
closed ×1commented ×1

Looking for guidance on the recommended way to forward selected inbound messages from a WhatsApp group to an external HTTP webhook and skip the agent reply, so an external service can react to operator commands without the LLM intercepting them. I've identified before_dispatch as the right hook but want to confirm before publishing a third-party plugin.

Root Cause

Looking for guidance on the recommended way to forward selected inbound messages from a WhatsApp group to an external HTTP webhook and skip the agent reply, so an external service can react to operator commands without the LLM intercepting them. I've identified before_dispatch as the right hook but want to confirm before publishing a third-party plugin.

Fix Action

Fix / Workaround

Looking for guidance on the recommended way to forward selected inbound messages from a WhatsApp group to an external HTTP webhook and skip the agent reply, so an external service can react to operator commands without the LLM intercepting them. I've identified before_dispatch as the right hook but want to confirm before publishing a third-party plugin.

  1. Match inbound messages by group JID (and optionally body pattern).
  2. Forward them to an authenticated HTTP endpoint (our own service that runs the runbook).
  3. Suppress the model dispatch so the agent doesn't reply.

Use the existing before_dispatch plugin hook (src/plugins/hooks.ts:988-1014, fired from src/auto-reply/reply/dispatch-from-config.ts:1022-1055) and have the plugin return { handled: true } after a successful POST. Reading the source, this looks like exactly the right primitive — claim the message, OpenClaw records recordProcessed("completed", { reason: "before_dispatch_handled" }) and the LLM never runs.

Code Example

export default definePluginEntry({
  id: "inbound-webhook-forward",
  register(api) {
    api.registerHook("before_dispatch", async (event, ctx) => {
      const cfg = api.pluginConfig as ForwardConfig;
      const route = cfg.routes.find(r => r.groupJid === ctx.from);
      if (!route) return undefined; // pass through
      await fetch(route.url, { method: "POST", headers: { Authorization: `Bearer ${route.token}` }, body: JSON.stringify(event) });
      return { handled: true };
    });
  },
});
RAW_BUFFERClick to expand / collapse

Summary

Looking for guidance on the recommended way to forward selected inbound messages from a WhatsApp group to an external HTTP webhook and skip the agent reply, so an external service can react to operator commands without the LLM intercepting them. I've identified before_dispatch as the right hook but want to confirm before publishing a third-party plugin.

Problem to solve

We run an alerting flow where Zabbix posts incidents into a WhatsApp group via OpenClaw, and operators reply with short commands like !restart 06 to trigger automated runbooks (SSM commands on EC2). With the default agent reply pipeline, those commands get answered by the LLM (e.g. "bash is disabled in this conversation") instead of being routed to our automation backend.

We need a way to:

  1. Match inbound messages by group JID (and optionally body pattern).
  2. Forward them to an authenticated HTTP endpoint (our own service that runs the runbook).
  3. Suppress the model dispatch so the agent doesn't reply.

Proposed solution

Use the existing before_dispatch plugin hook (src/plugins/hooks.ts:988-1014, fired from src/auto-reply/reply/dispatch-from-config.ts:1022-1055) and have the plugin return { handled: true } after a successful POST. Reading the source, this looks like exactly the right primitive — claim the message, OpenClaw records recordProcessed("completed", { reason: "before_dispatch_handled" }) and the LLM never runs.

Plugin shape (rough):

export default definePluginEntry({
  id: "inbound-webhook-forward",
  register(api) {
    api.registerHook("before_dispatch", async (event, ctx) => {
      const cfg = api.pluginConfig as ForwardConfig;
      const route = cfg.routes.find(r => r.groupJid === ctx.from);
      if (!route) return undefined; // pass through
      await fetch(route.url, { method: "POST", headers: { Authorization: `Bearer ${route.token}` }, body: JSON.stringify(event) });
      return { handled: true };
    });
  },
});

Asks:

  1. Is before_dispatch indeed the recommended hook for this pattern, or is there a more idiomatic primitive (e.g. a dedicated channel-side filter) I missed?
  2. Is there an existing third-party plugin (Clawhub or otherwise) that already does generic outbound webhook forwarding for inbound messages? Didn't find one in extensions/extensions/webhooks/ is the inverse direction (HTTP → TaskFlow).
  3. Would a small reference plugin demonstrating "claim and forward via before_dispatch" be useful enough to add to the docs, or is this niche enough to keep entirely third-party?

Alternatives considered

  • Patch extensions/whatsapp/.../process-message.ts directly with env-var-driven forward (what we run today). Works in production but is a fork-style local patch, doesn't survive any rebase on main. We'd like to migrate off of it.
  • runMessageReceived hook — fires for every inbound, but is fire-and-forget and can't suppress the agent reply, so the LLM still runs and answers. Not suitable for our use case.
  • Use the existing extensions/webhooks plugin — wrong direction (it accepts HTTP and binds to TaskFlows, not the other way around).

Impact

  • Affected users: Anyone integrating OpenClaw with external command/control systems (alerting, runbooks, SSM/Ansible, ticket bots) where specific groups should bypass the LLM and be handled by a dedicated backend.
  • Severity: Without this, operators see noisy LLM replies on every operational command. The current workaround is a fork-style patch — fine for one team, sharp edge for the community.
  • Frequency: Every inbound command in the configured groups. Low traffic for us (~tens of messages/day), but always-on.

Real behavior proof (current local-patch implementation)

We run a local patch of process-message.ts that injects an env-var-driven hook before the agent pipeline. End-to-end validated 2026-05-06: operator sends !restart 06 in the alert group → patch forwards to our internal HTTP endpoint → automation bot processes → SSM SendCommand runs (command id 33c798af-…, status success) → reply ✅ in the group. Diffs are in an internal repo; happy to attach the redacted unified diffs here on request.

The plugin route via before_dispatch would be a clean replacement that doesn't fork OpenClaw.

Notes

  • AI-assisted issue (Claude Opus 4.7) — I'll handle any plugin write-up myself.
  • Happy to write the reference plugin and submit it to Clawhub or as a docs PR if you confirm before_dispatch is the intended primitive here.

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