#8084: fix(plugins): wire up message_sending hook in outbound delivery
stale
Cluster:
Message Sending Hooks Enhancement
## Summary
Wire up the `message_sending` plugin hook in the outbound delivery pipeline.
## Problem
The `message_sending` hook was defined in `src/plugins/hooks.ts` and exported via `createHookRunner()`, but was never actually called anywhere in the codebase. This made it impossible for plugins to:
- Modify outgoing message content before delivery
- Cancel message delivery (e.g., for content filtering)
## Solution
Call `runMessageSending()` in `deliverOutboundPayloads()` before each message is sent. The hook:
- Receives the message content, destination, and channel metadata
- Can return modified `content` to replace the original
- Can return `cancel: true` to skip delivery entirely
## Changes
- `src/infra/outbound/deliver.ts`: Add hook call before message delivery
- `src/infra/outbound/deliver.test.ts`: Add tests for hook behavior
## Testing
- `pnpm vitest run src/infra/outbound/deliver.test.ts` - all 15 tests pass
- `pnpm lint src/infra/outbound/deliver.ts` - no errors
Fixes #7966
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR wires the `message_sending` plugin hook into the outbound delivery pipeline by calling the global hook runner for each normalized outbound payload, allowing plugins to modify message text or cancel delivery before the channel adapter sends.
It also adds an integration test suite that exercises hook invocation, text modification, cancellation, and the `sendPayload` adapter path, plus a changelog entry documenting the fix.
<h3>Confidence Score: 3/5</h3>
- Mostly safe to merge, but there are a couple of behavior/contract edge cases to confirm.
- Core wiring is straightforward and tests cover the happy paths, but the added try/catch can change failure semantics (especially when `bestEffort` is false), and the hook contract around media-only payloads vs empty content is unclear and could surprise plugin authors.
- src/infra/outbound/deliver.ts
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#9906: feat: wire message_sending hook in outbound delivery
by teempai · 2026-02-05
91.1%
#12584: feat(hooks): wire outbound message lifecycle hooks
by vincentkoc · 2026-02-09
85.0%
#20859: fix(hooks): wire message_sent hook into reply dispatcher for all ch...
by davidrudduck · 2026-02-19
81.5%
#10109: feat(plugins): invoke message_received and message_sent hooks
by nezovskii · 2026-02-06
81.0%
#11597: feat(hooks): implement message:received hook
by gnufoo · 2026-02-08
80.2%
#10679: fix(hooks): invoke gateway_start and gateway_stop in lifecycle
by yassinebkr · 2026-02-06
79.5%
#7771: Hooks: wire lifecycle events and tests
by rabsef-bicrym · 2026-02-03
79.3%
#19922: feat(hooks): add message:received and message:sent hook events
by NOVA-Openclaw · 2026-02-18
78.6%
#11681: feat(plugins): add cancel support to message_received hook
by PrimeTenet · 2026-02-08
78.2%
#7545: feat(hooks): add message:received hook for pre-turn automation
by wangtian24 · 2026-02-02
78.0%