Skip to content

fix(whatsapp): convert E.164 chat_id to JID before sending via bridge - #25943

Closed
ByteSide wants to merge 1 commit into
NousResearch:mainfrom
ByteSide:skippy/fix-whatsapp-e164-to-jid
Closed

fix(whatsapp): convert E.164 chat_id to JID before sending via bridge#25943
ByteSide wants to merge 1 commit into
NousResearch:mainfrom
ByteSide:skippy/fix-whatsapp-e164-to-jid

Conversation

@ByteSide

Copy link
Copy Markdown

What does this PR do?

Make send_message work for WhatsApp targets specified in E.164 phone-number form.

_parse_target_ref in tools/send_message_tool.py accepts a WhatsApp target like whatsapp:+15551234567, returns the E.164 string unchanged, and marks it as explicit. The accompanying comment claims "signal-cli and sms/whatsapp adapters expect E.164 format" — this is correct for signal-cli, but the Baileys-backed bridge in scripts/whatsapp-bridge/bridge.js calls sock.sendMessage(chatId, ...), where chatId must be a JID (<digits>@s.whatsapp.net, <digits>@lid, or <digits>@g.us). Calling it with a raw E.164 string raises JID decode failed inside Baileys and the bridge returns HTTP 500.

This is reproducible from any agent reply where the recipient is not yet in the directory listing — the agent then falls back to passing the E.164 string straight through.

Why fix it in _send_whatsapp rather than _parse_target_ref

I deliberately did not change the parser, because _PHONE_PLATFORMS is shared with Signal/SMS where E.164 is the correct downstream format. Normalizing inside _send_whatsapp keeps the parser invariant intact and the conversion local to the only adapter that needs JIDs. Already-formed JIDs (@s.whatsapp.net, @lid, @g.us) pass through unchanged.

Related Issue

Fixes #

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests
  • ♻️ Refactor
  • 🎯 New skill

Changes Made

  • tools/send_message_tool.py _send_whatsapp: add a 4-line normalization block before the HTTP POST. Converts leading-+ digits-only chat_id to <digits>@s.whatsapp.net; everything else (including already-formed JIDs) is unchanged.
  • tests/tools/test_send_message_tool.py: new TestSendWhatsappJidNormalization class with 4 cases:
    • test_e164_target_is_converted_to_jid+1555123456715551234567@s.whatsapp.net in the bridge POST body and in the return value's chat_id.
    • test_already_formed_jid_passes_through15551234567@s.whatsapp.net unchanged.
    • test_lid_jid_passes_through123456789012345@lid unchanged.
    • test_group_jid_passes_through120363045123456789@g.us unchanged.

How to Test

pytest tests/tools/test_send_message_tool.py::TestSendWhatsappJidNormalization -v
pytest tests/tools/test_send_message_tool.py -k whatsapp -q

End-to-end reproduction (against any running gateway with the Baileys bridge):

from tools.send_message_tool import send_message_tool
# Before the fix: returns {"error": "WhatsApp bridge error (500): ... JID decode failed ..."}
# After the fix:  returns {"success": True, "platform": "whatsapp", "chat_id": "<digits>@s.whatsapp.net", ...}
send_message_tool({
    "action": "send",
    "target": "whatsapp:+15551234567",
    "message": "test",
})

Checklist

  • I've read the Contributing Guide.
  • Conventional Commits format (fix(whatsapp): …).
  • No duplicate PR — searched for JID, E.164, whatsapp send_message open PRs.
  • Only the WhatsApp send path is touched.
  • I've run pytest tests/tools/test_send_message_tool.py -k whatsapp -q and all tests pass (existing 6 + new 4).
  • I've added tests covering E.164 → JID conversion and three passthrough cases.
  • Platform: Ubuntu 24.04 LTS, Python 3.13.

Documentation & Housekeeping

  • Inline comment in _send_whatsapp explains the format mismatch and the reason the conversion lives in the adapter (not the parser).
  • No config keys changed.
  • No architecture change.
  • Cross-platform: pure Python string handling, no OS-specific code.
  • No tool schema change — the send_message schema continues to advertise whatsapp:<phone-or-jid> targets.

Screenshots / Logs

Bridge log line that motivated the fix:

{"level":50,"msg":"JID decode failed","input":"+15551234567"}

The Baileys-backed bridge in scripts/whatsapp-bridge/bridge.js calls
sock.sendMessage(chatId, ...), where chatId must be a JID such as
'15551234567@s.whatsapp.net' (DMs), '<digits>@lid', or
'<digits>@g.us' (groups).  Calling it with a raw E.164 string raises
'JID decode failed' inside Baileys and the bridge returns HTTP 500.

_parse_target_ref in tools/send_message_tool.py accepts WhatsApp
targets in E.164 form ('whatsapp:+15551234567') and marks them as
explicit, with a comment that says 'signal-cli and sms/whatsapp
adapters expect E.164 format'.  That is correct for signal-cli but not
for the Baileys bridge.

Symptom: send_message(action='send', target='whatsapp:+15551234567',
message='...') returns 'WhatsApp bridge error (500): {"error":"JID
decode failed"}'.  Reproduces against any inactive WhatsApp contact
where the directory listing does not yet contain the recipient and the
agent falls back to E.164.

Fix: in _send_whatsapp, normalize a leading-'+' digits-only target to
'<digits>@s.whatsapp.net' before posting to the bridge.  Already
formatted JIDs (@s.whatsapp.net, @lid, @g.us) pass through unchanged.

Adds tests/tools/test_send_message_tool.py::TestSendWhatsappJidNormalization
with four cases: E.164 conversion, JID passthrough, @lid passthrough,
group-JID passthrough.  Existing TestSendToPlatformWhatsapp continues
to pass.
@ByteSide
ByteSide force-pushed the skippy/fix-whatsapp-e164-to-jid branch from 4d84b85 to e4d74fd Compare May 14, 2026 21:01
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists platform/whatsapp WhatsApp Business adapter comp/tools Tool registry, model_tools, toolsets duplicate This issue or pull request already exists labels May 14, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #25927 (identical resubmission — same files, same diff, same description). The prior PR was closed ~80s before this one was opened. Also related to #15652 and #20718 which address the same WhatsApp JID normalization.

@teknium1

Copy link
Copy Markdown
Contributor

Fixed on main via #50379 (salvage of #8639) — bare WhatsApp phone targets are now normalized to <digits>@s.whatsapp.net before the bridge call at every outbound send site.

@sgaofen's #8639 was the earliest of this cluster, so it was used as the base and credited first; thanks @ByteSide for independently catching and fixing the same bug. Closing as duplicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tools Tool registry, model_tools, toolsets duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists platform/whatsapp WhatsApp Business adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants