#16942: fix(whatsapp): add typingIndicator config to avoid rate limits
channel: whatsapp-web
stale
size: XS
trusted-contributor
Cluster:
WhatsApp and Google Chat Fixes
## Summary
Add a new `typingIndicator` configuration option for the WhatsApp channel. When set to `"none"`, it disables the typing indicator (composing presence) sent before each outbound message. This helps avoid WhatsApp rate limits that can trigger `"restricted"` status on new accounts with few contacts.
## Changes
- Add `typingIndicator` type (`"none" | "composing"`) to WhatsApp config schema
- Add `typingIndicator` to `ResolvedWhatsAppAccount` type
- Modify outbound message sending to check config before sending typing indicator
- Default behavior unchanged (sends typing indicator as before)
## Testing
- Build passes successfully
- Existing outbound tests pass
- Manual testing: Set `typingIndicator: "none"` in config to disable typing indicator
Fixes openclaw/openclaw#16912
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Adds a `typingIndicator` configuration option (`"none" | "composing"`) for WhatsApp to allow disabling the composing presence indicator sent before outbound messages. This addresses rate-limiting issues on new WhatsApp accounts with few contacts (openclaw/openclaw#16912).
- Added `WhatsAppTypingIndicatorConfig` type and `typingIndicator` field to both root-level `WhatsAppConfig` and per-account `WhatsAppAccountConfig`
- Added Zod validation in the shared schema (`z.enum(["none", "composing"]).optional()`)
- Added `typingIndicator` to `ResolvedWhatsAppAccount` with proper fallback chain (account → root config → `undefined`)
- Modified `sendMessageWhatsApp` in `outbound.ts` to conditionally skip `sendComposingTo` when `typingIndicator` is `"none"`
- Default behavior is preserved: when `typingIndicator` is unset (`undefined`), typing indicator is still sent
- No new tests were added for the `typingIndicator: "none"` code path, though existing tests pass since the default behavior is unchanged
<h3>Confidence Score: 4/5</h3>
- This PR is safe to merge with minimal risk — it's an additive, opt-in configuration change with backward-compatible defaults.
- The changes are focused and well-structured. Type definitions, Zod schema, account resolution, and outbound logic are all consistent. The `!== "none"` check correctly preserves default behavior when the config is unset. The only minor concern is the new `resolveWhatsAppAccount` call in the hot outbound path, which includes synchronous filesystem I/O for legacy auth detection, though this pattern is used elsewhere. No new tests cover the "none" path specifically, but existing tests verify the default behavior still works.
- `src/web/outbound.ts` — new `resolveWhatsAppAccount` call adds synchronous filesystem I/O to the outbound message path
<sub>Last reviewed commit: 0a583a1</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#17326: fix(whatsapp): group composing indicator, echo prevention, and pres...
by globalcaos · 2026-02-15
75.9%
#14789: fix: per-account dmPolicy ignored in checkInboundAccessControl
by croll83 · 2026-02-12
75.8%
#8052: fix(whatsapp): strip leading whitespace from outbound messages
by FelixFoster · 2026-02-03
75.2%
#22106: fix(whatsapp): honor selfChatMode override for group mentions
by sportclaw · 2026-02-20
74.9%
#4390: fix(whatsapp): allow media from allowlisted groups without groupAllow…
by Sarang19114 · 2026-01-30
74.9%
#13431: feat(whatsapp): add built-in Markdown to WhatsApp format transform
by asklee-klawd · 2026-02-10
74.9%
#20626: feat(whatsapp): add linkPreviewPolicy for URL exfiltration protection
by arniesaha · 2026-02-19
74.5%
#19303: Fix WhatsApp internal error leakage + cron.run timeout defaults
by koala73 · 2026-02-17
74.5%
#17882: fix: drop WhatsApp pairing reply for unconfigured accounts
by adit-negi · 2026-02-16
74.3%
#10196: fix(whatsapp): sanitize raw mention IDs in outbound messages
by koala73 · 2026-02-06
74.3%