#22919: WhatsApp: add lifecycle status reactions
docs
channel: whatsapp-web
size: L
Cluster:
Reaction Event Handling Enhancements
## Summary
Describe the problem and fix in 2–5 bullets:
- Problem: WhatsApp only sent a one-shot ack reaction and did not reflect run lifecycle state.
- Why it matters: Users could not see queued/thinking/tool/done/error progression like Telegram/Discord, and broadcast runs could race reaction updates.
- What changed: Added lifecycle status reactions for WhatsApp behind `messages.statusReactions.enabled`, reused shared status reaction controller, introduced deterministic single-owner lifecycle updates for broadcast groups, and added dedicated tests/docs/help updates.
- What did NOT change (scope boundary): No Slack lifecycle implementation changes, no new config keys, and default behavior remains unchanged unless lifecycle mode is enabled.
## Change Type (select all)
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [x] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [x] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [x] Integrations
- [x] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes: None
- Related: #21893
- Related: #6790
- Related: #22190
- Related: #23288
## User-visible / Behavior Changes
- WhatsApp now supports lifecycle auto-updating reactions (`queued -> thinking -> tool -> done/error`) when `messages.statusReactions.enabled=true`.
- One-shot ack reaction is skipped in lifecycle mode to avoid duplicate writes.
- In broadcast groups, lifecycle reactions are emitted by only the deterministic owner agent (first valid configured broadcast agent).
- Final lifecycle reaction is kept on WhatsApp (no post-reply cleanup).
## Security Impact (required)
- New permissions/capabilities? (`No`)
- Secrets/tokens handling changed? (`No`)
- New/changed network calls? (`No`)
- Command/tool execution surface changed? (`No`)
- Data access scope changed? (`No`)
- If any `Yes`, explain risk + mitigation:
## Repro + Verification
### Environment
- OS: macOS
- Runtime/container: Node 22+, pnpm
- Model/provider: N/A
- Integration/channel (if any): WhatsApp (web monitor path)
- Relevant config (redacted): `channels.whatsapp.ackReaction.*`, `messages.statusReactions.enabled`
### Steps
1. Enable `channels.whatsapp.ackReaction` and set `messages.statusReactions.enabled=true`.
2. Send inbound WhatsApp message and trigger response flow (including reasoning/tool activity).
3. Observe reaction progression and broadcast behavior with multiple agents configured.
### Expected
- Lifecycle reaction transitions on a single trigger message; non-owner broadcast agents do not emit lifecycle updates.
### Actual
- Matches expected in unit tests and targeted monitor/broadcast test suites.
## Evidence
Attach at least one:
- [x] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
## Human Verification (required)
What you personally verified (not just CI), and how:
- Verified scenarios: lifecycle queued/thinking/tool/done path, dispatch error path, final delivery error path, silent/no-final terminalization, one-shot ack suppression in lifecycle mode, broadcast owner-only lifecycle updates.
- Edge cases checked: missing message id in ack decision resolver; mention bypass via group activation; deterministic owner selection when first configured agent is invalid.
- What you did **not** verify: live WhatsApp device run in this PR flow.
## Compatibility / Migration
- Backward compatible? (`Yes`)
- Config/env changes? (`No`)
- Migration needed? (`No`)
- If yes, exact upgrade steps:
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly: set `messages.statusReactions.enabled=false`.
- Files/config to restore: WhatsApp monitor reaction paths under `src/web/auto-reply/monitor/*` and help/docs updates.
- Known bad symptoms reviewers should watch for: duplicate initial reactions, non-owner reaction updates in broadcast groups, missing terminal reaction state.
## Risks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write `None`.
- Risk: Merge conflicts with active WhatsApp monitor PRs touching `process-message.ts` / ack logic.
- Mitigation: Isolated ack decision helper, explicit lifecycle gating, and targeted tests around lifecycle and broadcast ownership.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Added lifecycle status reactions for WhatsApp that reuse the shared status reaction controller. The implementation introduces deterministic single-owner lifecycle updates for broadcast groups where only the first valid configured broadcast agent emits reactions.
- Refactored `maybeSendAckReaction` to extract decision logic into `resolveWhatsAppAckReactionDecision` for reuse
- One-shot ack reaction is now skipped when lifecycle mode is enabled to avoid duplicate initial reactions
- Broadcast groups pass `lifecycleOwnerAgentId` through the call chain, and non-owner agents suppress all lifecycle reactions
- Final lifecycle reaction is kept on WhatsApp (no post-reply cleanup like some other channels)
- Tests cover lifecycle progression, error handling, broadcast ownership, and silent terminalization scenarios
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The implementation follows established patterns from Telegram/Discord, reuses the shared status reaction controller without modifications, includes comprehensive tests covering edge cases (broadcast ownership, error paths, silent terminalization), and maintains backward compatibility with proper feature gating
- No files require special attention
<sub>Last reviewed commit: 44f36ac</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#20399: feat(whatsapp): surface inbound reaction events to agent session
by andrewchen · 2026-02-18
78.3%
#12894: feat(whatsapp): add reaction notifications support
by ekson73 · 2026-02-09
78.3%
#13641: feat(whatsapp): surface incoming reaction events to agent
by asklee-klawd · 2026-02-10
77.1%
#21346: [AI-assisted] Telegram: add reaction state machine with fallback an...
by Archie818 · 2026-02-19
74.4%
#22367: fix(whatsapp): prevent permanent listener loss after abort during r...
by mcinteerj · 2026-02-21
74.3%
#19303: Fix WhatsApp internal error leakage + cron.run timeout defaults
by koala73 · 2026-02-17
74.1%
#19757: fix(security): OC-91 enforce JID allowlist validation in WhatsApp s...
by aether-ai-agent · 2026-02-18
73.5%
#22106: fix(whatsapp): honor selfChatMode override for group mentions
by sportclaw · 2026-02-20
73.5%
#7287: feat(whatsapp): expose group admin functions
by balthazar-bot · 2026-02-02
73.0%
#23288: feat(whatsapp): group command gating via commands.allowFrom + sende...
by rodrigoscoelho · 2026-02-22
72.8%