#7545: feat(hooks): add message:received hook for pre-turn automation
docs
channel: whatsapp-web
## Summary
Adds a new hook event type `message:received` that fires before a message is processed by the agent. This enables:
- Running custom logic on incoming messages (e.g., memory curation with memfas)
- Injecting context into the message body via `injectedContext`
- Optionally skipping message processing via `skipProcessing`
## Changes
- **`src/hooks/internal-hooks.ts`**: Added `MessageReceivedHookContext` type and `isMessageReceivedEvent()` guard
- **`src/web/auto-reply/monitor/on-message.ts`**: Wired up hook for WhatsApp channel
- **`src/hooks/internal-hooks.test.ts`**: Added 10 new tests (28 total, all passing)
## Hook Context
```typescript
type MessageReceivedHookContext = {
message: string;
messageId?: string;
senderId?: string;
senderName?: string;
channel: string;
chatId?: string;
isGroup: boolean;
sessionKey: string;
agentId: string;
injectedContext?: string; // mutable - prepended to message
skipProcessing?: boolean; // mutable - skip agent turn
skipReason?: string; // mutable - logged if skipped
};
```
## Usage
```typescript
// hooks/my-hook.js
export default async function(event) {
if (event.type !== 'message' || event.action !== 'received') return;
// Inject context
event.context.injectedContext = 'Relevant memory: user likes pizza';
// Or skip processing
if (isSpam(event.context.message)) {
event.context.skipProcessing = true;
event.context.skipReason = 'spam detected';
}
}
```
## Future Work
- Wire up other channels (Discord, Telegram, Slack, Signal, iMessage)
- The pattern is identical - just add the hook trigger before each channel's dispatch
Closes #7541
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR introduces a new internal hook event `message:received` (type `message`, action `received`) with a dedicated context shape and a runtime type guard (`src/hooks/internal-hooks.ts`). The WhatsApp web auto-reply handler now triggers this hook before calling `processMessage()`, allowing hooks to request skipping processing or to inject a context prefix into the inbound message (`src/web/auto-reply/monitor/on-message.ts`). Tests were extended to cover handler registration/triggering and the new `isMessageReceivedEvent` guard (`src/hooks/internal-hooks.test.ts`).
Key items to double-check before merging:
- The current injection path mutates `msg.body` but `processMessage()` still computes and logs `combinedBody` separately, so the agent input (`RawBody`) and the logged/contextual `Body` can diverge.
- The lockfile now contains two axios snapshot variants; ensure this is intentional and produced by the expected pnpm version/settings.
<h3>Confidence Score: 3/5</h3>
- This PR is reasonably safe to merge but has a couple of behavioral/consistency concerns worth addressing.
- Core hook plumbing and tests look straightforward, but the WhatsApp wiring currently injects context by mutating `msg.body` in a way that can diverge from how `processMessage()` constructs/logs `combinedBody`, and the pnpm-lock change introduces an additional axios resolution variant that should be verified as intentional.
- src/web/auto-reply/monitor/on-message.ts, pnpm-lock.yaml
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#11597: feat(hooks): implement message:received hook
by gnufoo · 2026-02-08
89.4%
#19922: feat(hooks): add message:received and message:sent hook events
by NOVA-Openclaw · 2026-02-18
87.7%
#7580: feat: add message:received internal hook with prompt injection
by rodrigoschott · 2026-02-03
87.4%
#10109: feat(plugins): invoke message_received and message_sent hooks
by nezovskii · 2026-02-06
86.5%
#10706: feat(hooks): add message:received internal hook for Telegram
by thebtf · 2026-02-06
84.9%
#15577: feat(hooks): add message:preprocessed hook event
by heybeaux · 2026-02-13
83.1%
#22431: feat(hooks): add channel:connected hook event
by dion-jy · 2026-02-21
81.8%
#16618: feat: bridge message lifecycle hooks to workspace hook system
by DarlingtonDeveloper · 2026-02-14
80.3%
#22293: Hooks: add message-filter bundled hook with inbound message pre-filter
by MegaPhoenix92 · 2026-02-21
79.7%
#9906: feat: wire message_sending hook in outbound delivery
by teempai · 2026-02-05
79.5%