#10109: feat(plugins): invoke message_received and message_sent hooks
channel: whatsapp-web
stale
Add actual invocations for message hooks that were defined but never called:
- message_received: invoked in process-message.ts when an inbound message is received, includes from, content, timestamp, and metadata (chatType, conversationId, messageId, channel)
- message_sent: invoked in deliver.ts after successful message delivery, includes to, content, and success status
This enables plugins to intercept messages for logging, analytics, or external integrations (e.g., syncing to external databases).
Closes #9524
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR wires up the previously-defined plugin message hooks by invoking `message_received` when a WhatsApp web inbound message is processed and `message_sent` after outbound delivery completes.
The hook calls are placed in `src/web/auto-reply/monitor/process-message.ts` (inbound) and `src/infra/outbound/deliver.ts` (outbound) using the global hook runner (`src/plugins/hook-runner-global.ts`).
Key issue to address before merge: both hook invocations pass an invalid context shape (using `channel` instead of the required `channelId`), so hook handlers will not receive the expected `channelId`. Additionally, `message_sent` currently reports `success: true` based only on `results.length > 0`, which can be incorrect in partial-failure/best-effort scenarios and can mislead plugin integrations.
<h3>Confidence Score: 3/5</h3>
- This PR is close to mergeable but needs fixes to hook context wiring and success semantics.
- The changes are small and localized, but the hook context currently does not match the declared `PluginHookMessageContext` shape (missing required `channelId`), which will break consumers at runtime. The `message_sent.success` flag is also computed in a way that can be observably wrong under `bestEffort` partial failures.
- src/infra/outbound/deliver.ts, src/web/auto-reply/monitor/process-message.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#7545: feat(hooks): add message:received hook for pre-turn automation
by wangtian24 · 2026-02-02
86.5%
#19922: feat(hooks): add message:received and message:sent hook events
by NOVA-Openclaw · 2026-02-18
86.1%
#11597: feat(hooks): implement message:received hook
by gnufoo · 2026-02-08
84.3%
#15577: feat(hooks): add message:preprocessed hook event
by heybeaux · 2026-02-13
81.8%
#9906: feat: wire message_sending hook in outbound delivery
by teempai · 2026-02-05
81.7%
#6630: feat(hooks): add agent:turn_start and agent:turn_end lifecycle events
by drdigital13 · 2026-02-01
81.4%
#8084: fix(plugins): wire up message_sending hook in outbound delivery
by lailoo · 2026-02-03
81.0%
#7580: feat: add message:received internal hook with prompt injection
by rodrigoschott · 2026-02-03
80.8%
#12584: feat(hooks): wire outbound message lifecycle hooks
by vincentkoc · 2026-02-09
80.7%
#11681: feat(plugins): add cancel support to message_received hook
by PrimeTenet · 2026-02-08
80.5%