Skip to content

feat(hooks): add blocking capability to message_received hookFeat/message received blocking#10539

Closed
khalidovicGPT wants to merge 4 commits into
openclaw:mainfrom
khalidovicGPT:feat/message-received-blocking
Closed

feat(hooks): add blocking capability to message_received hookFeat/message received blocking#10539
khalidovicGPT wants to merge 4 commits into
openclaw:mainfrom
khalidovicGPT:feat/message-received-blocking

Conversation

@khalidovicGPT

@khalidovicGPT khalidovicGPT commented Feb 6, 2026

Copy link
Copy Markdown

Summary

This PR enhances the message_received hook to support blocking incoming messages before they reach the agent. This enables security plugins to intercept and reject malicious messages (e.g., prompt injection attempts).

Author: ClawForge Team

Changes

1. New Result Type (src/plugins/types.ts)

  • Added PluginHookMessageReceivedResult with block, blockReason, notifyUser, notifyAgent, threatLevel, and auditMetadata fields

2. Hook Implementation (src/plugins/hooks.ts)

  • Changed runMessageReceived from runVoidHook to runModifyingHook
  • Added result merging logic

3. Dispatch Logic (src/auto-reply/reply/dispatch-from-config.ts)

  • Now awaits hook result instead of fire-and-forget
  • Checks for block: true and returns early
  • Sends notifyUser message when blocking

Backward Compatibility

✅ Fully backward compatible

  • Existing void handlers return undefined → message allowed
  • Only handlers explicitly returning { block: true } cause blocking
  • Errors in hooks cause fail-open behavior

Use Case

Enables security plugins like prompt injection detection:

api.on("message_received", async (event) => {
  if (isPromptInjection(event.content)) {
    return { block: true, notifyUser: "Message blocked." };
  }
});

<!-- greptile_comment -->

<h2>Greptile Overview</h2>

<h3>Greptile Summary</h3>

- Extends the `message_received` plugin hook so handlers can return a structured result that can block inbound messages.
- Updates the hook runner implementation to execute `message_received` via the modifying-hook path and merge results.
- Updates `dispatchReplyFromConfig` to await `message_received` and short-circuit message processing (optionally notifying the user) when `block: true` is returned.
- Adds the `PluginHookMessageReceivedResult` type and updates the hook handler map signature accordingly.

<h3>Confidence Score: 3/5</h3>

- This PR is close, but has a couple of type-level issues that should be fixed before merging.
- Core behavior changes are localized and appear consistent with the goal (block on hook result), but `runMessageReceived` currently calls `runModifyingHook` with incorrect generic parameters and the new result type is not re-exported from `src/plugins/hooks.ts`, which can break compilation and/or consumer imports.
- src/plugins/hooks.ts

<!-- greptile_other_comments_section -->

<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>

<!-- /greptile_comment -->

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread src/plugins/hooks.ts
Comment on lines +242 to +245
async function runMessageReceived(
event: PluginHookMessageReceivedEvent,
ctx: PluginHookMessageContext,
): Promise<PluginHookMessageReceivedResult | undefined> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect generic arguments

runModifyingHook is declared as runModifyingHook<K extends PluginHookName, TResult>(hookName: K, ...), but runMessageReceived calls it as runModifyingHook<PluginHookMessageReceivedResult>(...), which supplies the hook name type parameter with the result type. This should be runModifyingHook<"message_received", PluginHookMessageReceivedResult>(...) (as is done in runBeforeAgentStart / runMessageSending), otherwise TS will either fail to compile or infer the wrong types for hookName/event/ctx.

Also appears in: src/plugins/hooks.ts:246.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugins/hooks.ts
Line: 242:245

Comment:
**Incorrect generic arguments**

`runModifyingHook` is declared as `runModifyingHook<K extends PluginHookName, TResult>(hookName: K, ...)`, but `runMessageReceived` calls it as `runModifyingHook<PluginHookMessageReceivedResult>(...)`, which supplies the *hook name* type parameter with the result type. This should be `runModifyingHook<"message_received", PluginHookMessageReceivedResult>(...)` (as is done in `runBeforeAgentStart` / `runMessageSending`), otherwise TS will either fail to compile or infer the wrong types for `hookName`/`event`/`ctx`.

Also appears in: `src/plugins/hooks.ts:246`.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread src/plugins/hooks.ts
Comment on lines +242 to +244
async function runMessageReceived(
event: PluginHookMessageReceivedEvent,
ctx: PluginHookMessageContext,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type exports missing

PluginHookMessageReceivedResult is imported at src/plugins/hooks.ts:24 but it is not included in the export type { ... } block near the top. Consumers importing types from src/plugins/hooks.ts will not be able to reference the new result type even though it exists in src/plugins/types.ts, which breaks the intended public API for this hook result.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugins/hooks.ts
Line: 242:244

Comment:
**Type exports missing**

`PluginHookMessageReceivedResult` is imported at `src/plugins/hooks.ts:24` but it is not included in the `export type { ... }` block near the top. Consumers importing types from `src/plugins/hooks.ts` will not be able to reference the new result type even though it exists in `src/plugins/types.ts`, which breaks the intended public API for this hook result.

How can I resolve this? If you propose a fix, please make it concise.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added stale Marked as stale due to inactivity and removed stale Marked as stale due to inactivity labels Feb 21, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Mar 8, 2026
@openclaw-barnacle

Copy link
Copy Markdown

Closing due to inactivity.
If you believe this PR should be revived, post in #pr-thunderdome-dangerzone on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant