Problem
When sending messages via openclaw message send or scheduling with openclaw cron add --to, Brazilian phone numbers are sent as-is without normalization. This causes silent delivery failures for Brazilian users.
Background
Brazilian mobile numbers have two formats:
- Carrier format (14 digits):
+55 DD 9XXXX XXXX — used by contacts, phone books, and carriers
- WhatsApp internal format (13 digits):
+55 DD XXXX XXXX — used by WhatsApp protocol (Baileys JID)
In 2010, ANATEL added a 9th digit prefix to all Brazilian mobile numbers. However, WhatsApp internally registers numbers without this extra 9 for most area codes outside SP/RJ/ES (DDDs other than 11-28).
Current behavior
openclaw message send --channel whatsapp --target +5547984178525 --message "hello"
# Gateway reports: ✅ Sent via gateway. Message ID: 3EB0...
# WhatsApp actually sends to: 5547984178525@s.whatsapp.net (WRONG - 14 digits)
# Message is never delivered (number doesn't exist in this format)
The gateway returns success because it handed off to WhatsApp, but the number doesn't resolve on WhatsApp's side. No error is surfaced — it's a silent failure.
Expected behavior
The number should be normalized to WhatsApp format before sending:
+5547984178525 (14 digits) → +554784178525 (13 digits, 9th digit removed)
Affected commands
openclaw message send --target
openclaw cron add --to (delivery destination)
- Any outbound WhatsApp message where the user provides a Brazilian number
Suggested solutions
Option A — Use Baileys onWhatsApp() validation:
Baileys already has sock.onWhatsApp(jid) which checks if a number exists and returns the correct JID. This would handle Brazil, Mexico, and any other country with format discrepancies.
Option B — Add BR/MX normalization to normalizeE164():
In src/whatsapp/normalize.ts, add country-specific rules:
function normalizeBrazilPhone(phone: string): string {
// Brazilian WhatsApp: remove 9th digit for DDDs outside 11-28
// +55DDXXXXXXXXX (14 digits) → +55DDXXXXXXXX (13 digits)
if (phone.startsWith('+55') && phone.length === 14 && phone[5] === '9') {
return phone.slice(0, 5) + phone.slice(6);
}
return phone;
}
Option C — Configuration-based normalization:
Add a whatsapp.phoneNormalization config option (e.g., "region": "BR") so users can opt-in to country-specific normalization.
Workaround
We created a wrapper script (send_msg.py) that normalizes the number before calling openclaw message send. This works for direct messages but doesn't help with cron --to delivery.
Environment
- OpenClaw: 2026.2.17
- WhatsApp: QR code connection (personal)
- Country: Brazil (DDD 47 — Santa Catarina)
References
Problem
When sending messages via
openclaw message sendor scheduling withopenclaw cron add --to, Brazilian phone numbers are sent as-is without normalization. This causes silent delivery failures for Brazilian users.Background
Brazilian mobile numbers have two formats:
+55 DD 9XXXX XXXX— used by contacts, phone books, and carriers+55 DD XXXX XXXX— used by WhatsApp protocol (Baileys JID)In 2010, ANATEL added a 9th digit prefix to all Brazilian mobile numbers. However, WhatsApp internally registers numbers without this extra 9 for most area codes outside SP/RJ/ES (DDDs other than 11-28).
Current behavior
The gateway returns success because it handed off to WhatsApp, but the number doesn't resolve on WhatsApp's side. No error is surfaced — it's a silent failure.
Expected behavior
The number should be normalized to WhatsApp format before sending:
+5547984178525(14 digits) →+554784178525(13 digits, 9th digit removed)Affected commands
openclaw message send --targetopenclaw cron add --to(delivery destination)Suggested solutions
Option A — Use Baileys
onWhatsApp()validation:Baileys already has
sock.onWhatsApp(jid)which checks if a number exists and returns the correct JID. This would handle Brazil, Mexico, and any other country with format discrepancies.Option B — Add BR/MX normalization to
normalizeE164():In
src/whatsapp/normalize.ts, add country-specific rules:Option C — Configuration-based normalization:
Add a
whatsapp.phoneNormalizationconfig option (e.g.,"region": "BR") so users can opt-in to country-specific normalization.Workaround
We created a wrapper script (
send_msg.py) that normalizes the number before callingopenclaw message send. This works for direct messages but doesn't help withcron --todelivery.Environment
References