#13431: feat(whatsapp): add built-in Markdown to WhatsApp format transform
channel: whatsapp-web
stale
Cluster:
WhatsApp Enhancements and Fixes
## Summary
Adds automatic conversion of standard Markdown to WhatsApp-compatible formatting for outbound messages. Enabled by default.
## Problem
LLMs output standard Markdown (`**bold**`, `~~strike~~`, `# headers`, etc.) but WhatsApp uses its own formatting syntax (`*bold*`, `~strike~`, no headers). Currently users need to patch source files or train agents to output WhatsApp-specific syntax.
Fixes #12129
## Solution
Built-in transform that runs automatically on outbound WhatsApp messages:
### Transforms
- `**bold**` or `__bold__` → `*bold*`
- `~~strikethrough~~` → `~strikethrough~`
- `# Headers` → `*Headers*` (bold)
- `[text](url)` → `text (url)`
- `` → `alt (url)`
- `---` horizontal rules → removed
- Preserves code blocks and inline code (WhatsApp supports them natively)
### Config Options
```json
{
"channels": {
"whatsapp": {
"formatting": {
"markdownTransform": true // default
}
}
}
}
```
Also supports per-account override:
```json
{
"channels": {
"whatsapp": {
"accounts": {
"myaccount": {
"formatting": {
"markdownTransform": false
}
}
}
}
}
}
```
### Implementation
Applied after `convertMarkdownTables()` and before chunking in both delivery paths:
1. **Auto-reply** (`deliverWebReply`) — main path for agent responses
2. **Outbound** (`sendMessageWhatsApp`) — message tool and explicit sends
Transform ordering follows the issue recommendation: runs after table conversion to avoid `convertMarkdownTables()` re-introducing `**` markers.
## Testing
- 27 unit tests covering all transforms and edge cases
- Build passes
- Tested manually with WhatsApp channel
## Files Changed
- `src/markdown/whatsapp.ts` — new transform function
- `src/markdown/whatsapp.test.ts` — unit tests
- `src/config/types.whatsapp.ts` — config types
- `src/config/zod-schema.providers-whatsapp.ts` — Zod schema
- `src/web/auto-reply/deliver-reply.ts` — integrate transform
- `src/web/auto-reply/monitor/process-message.ts` — pass config
- `src/web/outbound.ts` — integrate transform
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR adds a WhatsApp-specific Markdown normalization pass that converts common Markdown constructs (bold/strike/headers/links/images/hr) into WhatsApp-friendly formatting. The transform is wired into both outbound send paths: auto-reply delivery (`src/web/auto-reply/deliver-reply.ts`) and explicit outbound sends (`src/web/outbound.ts`), and it’s controlled via new `channels.whatsapp.formatting.markdownTransform` config (with per-account override) defined in the WhatsApp config types and Zod provider schema.
Main integration is: convert markdown tables → (optionally) transform markdown to WhatsApp format → chunk and send.
<h3>Confidence Score: 3/5</h3>
- This PR is close to mergeable, but there are a couple correctness issues in the new markdown transform that can corrupt output or violate type expectations.
- The new transform is integrated in the right places and is feature-scoped, but (1) placeholder restoration is not robust (non-global replace + user-collidable placeholders) and (2) the exported transform function can return null/undefined despite being typed as returning string; both can break downstream message handling.
- src/markdown/whatsapp.ts (placeholder restore + input/output type contract); src/markdown/whatsapp.test.ts (null/undefined behavior expectations)
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#7395: fix(whatsapp): strip markdown bold/italic from URLs before sending
by lailoo · 2026-02-02
85.3%
#10196: fix(whatsapp): sanitize raw mention IDs in outbound messages
by koala73 · 2026-02-06
79.8%
#8052: fix(whatsapp): strip leading whitespace from outbound messages
by FelixFoster · 2026-02-03
78.8%
#13424: feat(whatsapp): add Newsletter/Channel JID support
by agentz-manfred · 2026-02-10
78.0%
#7458: fix: pass filename through to WhatsApp document sends (#7446)
by gavinbmoore · 2026-02-02
77.6%
#8224: feat(whatsapp): extract @mentions into dedicated module
by zurizuriaria · 2026-02-03
76.7%
#9237: Fix: WhatsApp QR code not rendering in chat
by vishaltandale00 · 2026-02-05
76.4%
#16147: fix: use a single asterisk to wrap the bold text in whatsapp
by albertominetti · 2026-02-14
76.3%
#20626: feat(whatsapp): add linkPreviewPolicy for URL exfiltration protection
by arniesaha · 2026-02-19
75.8%
#12700: fix(tts): deliver WhatsApp voice as opus bubble instead of MP3 (#12...
by lailoo · 2026-02-09
75.7%