openclaw - 💡(How to fix) Fix Allow generic plugins to claim/drop inbound messages (inbound_claim for non-channel plugins) [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#54913Fetched 2026-04-08 01:34:34
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Participants

Fix Action

Fix / Workaround

Current Workaround

If opening inbound_claim to generic plugins is too broad, a narrower alternative would be a new hook (e.g. before_dispatch or message_gate) that:

  1. Fires after inbound_claim but before agent dispatch
  2. Receives senderId, channel, isGroup, and message content
  3. Returns { handled: true } to drop the message
  4. Available to all plugins regardless of type
RAW_BUFFERClick to expand / collapse

Use Case

A generic plugin that manages contact gating (blocking, rate limiting, message caps) needs to silently drop inbound messages from blocked or rate-limited users before the LLM is invoked. This saves token cost on messages that should never be processed and provides a hard guarantee that blocked users receive no response — even if the LLM is jailbroken or ignores a context injection directive.

Currently, the only pre-LLM hook that can drop messages is inbound_claim, but it only fires for channel plugins that own a conversation binding. Generic plugins have no mechanism to prevent a message from reaching the agent.

Current Workaround

A generic plugin can use before_prompt_build to inject a "do not respond" directive into the agent's context. This works in practice but:

  • Not guaranteed — relies on the LLM obeying the instruction. A sufficiently determined prompt injection can bypass it.
  • Wastes tokens — the LLM still runs, consuming API tokens on a message that should have been dropped.
  • No sender identity in contextPluginHookAgentContext doesn't include senderId, so for group messages the plugin has to parse sender metadata from event.prompt. This works but is fragile and undocumented.

Proposal

Allow inbound_claim to fire for all registered plugin hooks, not just channel plugins with conversation bindings. When a generic plugin registers an inbound_claim handler via api.on('inbound_claim', ...), it should receive the same event and context (including senderId, isGroup, channel) and be able to return { handled: true } to drop the message.

This would enable plugins that implement access control, rate limiting, abuse prevention, or moderation to enforce hard boundaries at the gateway level — deterministically, before any LLM invocation.

Alternative (Smaller Change)

If opening inbound_claim to generic plugins is too broad, a narrower alternative would be a new hook (e.g. before_dispatch or message_gate) that:

  1. Fires after inbound_claim but before agent dispatch
  2. Receives senderId, channel, isGroup, and message content
  3. Returns { handled: true } to drop the message
  4. Available to all plugins regardless of type

This issue was created with AI assistance.

extent analysis

Fix Plan

To address the issue, we can implement a new hook, message_gate, that allows generic plugins to silently drop inbound messages from blocked or rate-limited users. Here are the steps:

  • Introduce a new hook, message_gate, that fires after inbound_claim but before agent dispatch.
  • The message_gate hook should receive the following parameters:
    • senderId
    • channel
    • isGroup
    • message content
  • The hook should return an object with a handled property, where handled: true indicates that the message should be dropped.

Example code for the message_gate hook:

api.on('message_gate', (event) => {
  const { senderId, channel, isGroup, message } = event;
  // Check if the sender is blocked or rate-limited
  if (isBlocked(senderId) || isRateLimited(senderId)) {
    return { handled: true };
  }
  // If not blocked or rate-limited, allow the message to proceed
  return { handled: false };
});

Verification

To verify that the fix worked, you can test the message_gate hook by sending a message from a blocked or rate-limited user and checking that the message is not processed by the LLM.

Extra Tips

  • Make sure to document the message_gate hook and its parameters to ensure that plugin developers understand how to use it.
  • Consider adding logging or monitoring to track when the message_gate hook drops messages, to help with debugging and analytics.

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 Allow generic plugins to claim/drop inbound messages (inbound_claim for non-channel plugins) [1 participants]