#12584: feat(hooks): wire outbound message lifecycle hooks
docs
gateway
stale
size: M
Cluster:
Message Sending Hooks Enhancement
## Why
Message lifecycle hooks were not fully wired across outbound delivery paths, limiting observability and intervention points for message guardrails. This PR completes outbound lifecycle wiring and propagates session context so hook consumers can attribute events reliably.
## Detailed Changes
- Wired outbound plugin hooks in delivery pipeline:
- `message_sending`
- `message_sent` (success/failure/cancel-aware)
- Added message hook context fields in outbound flow:
- `sessionKey`
- `sessionId`
- Added `sessionKey` into `message_received` hook context from dispatch flow
- Applied session-key normalization touch-up in dispatch store lookup path
## Related Links and Issues
- Existing source PR: #9761
- Related issues:
- Closes #8807
- Closes #7067
- Closes #9871
- #9387
- #9524
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR completes wiring for outbound message lifecycle plugin hooks by invoking `message_sending` (with cancel/modify support) and `message_sent` (success/failure/cancel-aware) across outbound delivery paths, including text chunking, Signal chunk formatting, and media sends. It also extends hook context with `sessionKey`/`sessionId` and propagates these fields through several call sites (gateway send, cron isolated-agent, heartbeat, auto-reply routing) so hook consumers can better attribute events.
Core changes live in `src/infra/outbound/deliver.ts`, which now runs the hooks around per-chunk/per-attachment sends and ensures failures are attributed to the attempted content. Tests were expanded substantially in `src/infra/outbound/deliver.test.ts` to cover chunk rewrite limits, cancel behavior, and accurate failure reporting.
<h3>Confidence Score: 4/5</h3>
- This PR is close to safe to merge, but there is a concrete session-context propagation bug that undermines the stated observability goal in at least one outbound send path.
- Most hook wiring changes in `deliver.ts` are internally consistent and are backed by new regression tests for chunk rewrite/cancel/failure attribution. However, `sendMessage()` appears to pass `sessionKey` from the mirror config rather than from the actual session context, so hook consumers will still miss session attribution in common direct-send flows unless this is corrected.
- src/infra/outbound/message.ts
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#9906: feat: wire message_sending hook in outbound delivery
by teempai · 2026-02-05
86.0%
#8084: fix(plugins): wire up message_sending hook in outbound delivery
by lailoo · 2026-02-03
85.0%
#10109: feat(plugins): invoke message_received and message_sent hooks
by nezovskii · 2026-02-06
80.7%
#20859: fix(hooks): wire message_sent hook into reply dispatcher for all ch...
by davidrudduck · 2026-02-19
80.2%
#19922: feat(hooks): add message:received and message:sent hook events
by NOVA-Openclaw · 2026-02-18
80.0%
#7771: Hooks: wire lifecycle events and tests
by rabsef-bicrym · 2026-02-03
78.2%
#11597: feat(hooks): implement message:received hook
by gnufoo · 2026-02-08
76.7%
#16618: feat: bridge message lifecycle hooks to workspace hook system
by DarlingtonDeveloper · 2026-02-14
76.6%
#7545: feat(hooks): add message:received hook for pre-turn automation
by wangtian24 · 2026-02-02
76.3%
#19565: feat: add agent lifecycle hook events (session, message, error)
by tag-assistant · 2026-02-17
75.3%