fix(tools): resolve whatsapp phone numbers to lid format - #14738
Conversation
|
Hi @alt-glitch, I reviewed #3097 and #3219, and I think this PR is the most direct fix for #14486. #14486 is primarily an outbound delivery bug: By contrast:
Both are useful, but neither directly fixes the failing outbound This PR also,
So my take is that |
Adds a resolution pipeline `_resolve_whatsapp_phone_to_jid` to the
`send_message_tool`. Updates `_parse_target_ref` and `_send_whatsapp`
to use the resolution pipeline when bare phone numbers are provided.
Passes through already valid JIDs (ending with `@lid`, `@s.whatsapp.net`,
`@g.us`).
This resolves the issue where AI tool calls and cron reminders failed
to send WhatsApp messages because they passed bare phone numbers
instead of the newly enforced Linked Identity Device (LID) formats.
It checks the local bridge mapping files (`lid-mapping-{phone}.json`)
to gracefully convert phone numbers to LIDs.
Comprehensive unit tests were added in `test_send_message_tool.py`
testing legacy JIDs, LIDs, group JIDs, and fallback mechanisms.
Fixes: NousResearch#14486
|
Hey @ysnav, thanks for taking a look into the issue I created! also, @alt-glitch, could you please take a look into this PR? |
…suffixes - Extracts phone-to-LID mapping logic from `tools/send_message_tool.py` into a shared `resolve_whatsapp_outbound_target` helper in `gateway/whatsapp_identity.py`. - Restores explicit passthrough for known WhatsApp JIDs (`@lid`, `@s.whatsapp.net`, `@g.us`) in `_parse_target_ref()`. - Strips unknown suffixes and falls back to resolving the prefix as a bare phone number. - Adds comprehensive tests isolating `HERMES_HOME` to guarantee reproducible legacy fallback and suffix validation behavior. - Normalizes `chatId` inside the live `WhatsAppAdapter.send()` to prevent initial cron delivery rejections.
b668f73 to
963d218
Compare
Thanks @Isaac4real, I have streamlined the code, and resolved the conflicts! I am awaiting review for this PR. |
|
Hey @alt-glitch, can you please help review this PR? |
|
Fixed on main via #50379 (salvage of #8639) — bare WhatsApp phone targets are now normalized to @sgaofen's #8639 was the earliest of this cluster, so it was used as the base and credited first; thanks @ysnav for independently catching and fixing the same bug. Closing as duplicate. |
What does this PR do?
This PR fixes a critical bug where AI-initiated tool calls and cron reminders failed to send messages over WhatsApp because they used bare phone numbers instead of the required Linked Identity Device (LID) formats.
Context: JIDs vs. LIDs
1 JID (Jabber ID): The traditional WhatsApp routing identifier. For direct messages, it looks like
[phone_number]@s.whatsapp.net. For groups, it looks like[group_id]@g.us.2 LID (Linked Identity Device): WhatsApp's modern, privacy-focused identifier format (e.g.,
77214955630717@lid). The underlying Baileys bridge now strictly enforces this format for newer accounts and multi-device setups.Why we can't fully ditch JIDs: We must continue supporting JIDs because group chats (
@g.us) still rely entirely on the JID format. Additionally, we need to maintain legacy JID fallbacks (@s.whatsapp.net) for older accounts or edge cases where an LID isn't known yet.The Bug
Incoming messages from WhatsApp to Hermes were working perfectly. This is because the local Baileys bridge natively handles incoming LIDs and automatically maps them to phone numbers for authorization (via
allowlist.js).However, the system broke on outgoing messages initiated by the AI (via tools) or by background Cron jobs. These systems only knew the user's bare phone number (e.g.,
+1234567890). Whensend_message_toolsent this bare phone number to the bridge, the bridge rejected it because it expects a fully qualified LID or JID.The Fix
This PR implements a resolution pipeline that bridges the gap between the agent's knowledge (phone numbers) and the bridge's requirements (LIDs):
_resolve_whatsapp_phone_to_jidto thesend_message_tool. When a bare phone number is provided, it reads the local bridge session files (~/.hermes/whatsapp/session/lid-mapping-{phone}.json) created during the bridge handshake to gracefully convert the phone number to its proper LID._parse_target_refand_send_whatsappto use this pipeline. If an already-valid JID is passed in (containing@lid,@s.whatsapp.net, or@g.us), it passes through untouched.@s.whatsapp.netformat.Comprehensive unit tests were added in
test_send_message_tool.pyto ensure legacy JIDs, LIDs, group JIDs, and fallback mechanisms are all routed correctly.Related Issue
Fixes #14486
Type of Change
Changes Made
tools/send_message_tool.py: Added_resolve_whatsapp_phone_to_jidand_ensure_whatsapp_jidhelpers. Updated_parse_target_refand_send_whatsapprouting to automatically resolve bare phone numbers and respect valid WhatsApp JIDs.tests/tools/test_send_message_tool.py: Added test classTestWhatsAppPhoneToLidResolutionandTestEnsureWhatsAppJidto cover mapping file lookups, legacy fallbacks, and standard JID passthrough.How to Test
~/.hermes/whatsapp/session/.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AFor New Skills
hermes --toolsets skills -q "Use the X skill to do Y"Screenshots / Logs
Tested manually as well, by asking the agent to remind me at 18:39 via whatsapp, and it did remind me