Skip to content

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

Open
khalidovicGPT wants to merge 4 commits intoopenclaw:mainfrom
khalidovicGPT:feat/message-received-blocking
Open

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

Conversation

@khalidovicGPT
Copy link

@khalidovicGPT khalidovicGPT commented Feb 6, 2026

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 -->

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

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 on lines +242 to +245
async function runMessageReceived(
event: PluginHookMessageReceivedEvent,
ctx: PluginHookMessageContext,
): Promise<PluginHookMessageReceivedResult | undefined> {
Copy link
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 on lines +242 to +244
async function runMessageReceived(
event: PluginHookMessageReceivedEvent,
ctx: PluginHookMessageContext,
Copy link
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

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

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
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