hermes - ✅(Solved) Fix [Bug]: WhatsApp reply-to-bot detection fails — device suffix mismatch in botIds vs quotedParticipant [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#29023Fetched 2026-05-20 04:00:34
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
0
Author
Timeline (top)
labeled ×4cross-referenced ×2commented ×1

The _message_is_reply_to_bot() method in gateway/platforms/whatsapp.py consistently returns False for WhatsApp group messages, even when the user explicitly replies (quotes) a bot message. This makes the reply-to-bot admission shortcut unusable on WhatsApp.

Impact: Users in groups with require_mention: true cannot trigger the bot by replying to its messages — they must always @mention the bot, which is impossible for voice/audio messages since WhatsApp voice notes cannot include text mentions.

Root Cause

The bridge sends botIds with the device suffix included (:N → normalized to @N):

// bridge.js line ~244-247
const botIds = Array.from(new Set([
    normalizeWhatsAppId(sock.user?.id),     // "5511999999999@[email protected]"
    normalizeWhatsAppId(sock.user?.lid),    // "99999999999999@10@lid"
].filter(Boolean)));

However, the quotedParticipant from Baileys contextInfo (extracted at bridge.js line ~321) arrives without the device suffix:

quotedParticipant: "[email protected]"    // no @10
botIds:          {"5511999999999@[email protected]", "99999999999999@10@lid"}

Since _message_is_reply_to_bot() does a strict set membership check:

def _message_is_reply_to_bot(self, data: Dict[str, Any]) -> bool:
    quoted_participant = self._normalize_whatsapp_id(data.get("quotedParticipant"))
    if not quoted_participant:
        return False
    return quoted_participant in self._bot_ids_from_message(data)

The match always fails: "[email protected]" in {"5511999999999@[email protected]", "99999999999999@10@lid"}False.

Fix Action

Fix

In gateway/platforms/whatsapp.py, modify _bot_ids_from_message() to also generate ID variants without the device suffix:

def _bot_ids_from_message(self, data: Dict[str, Any]) -> set[str]:
    bot_ids = set()
    for candidate in data.get("botIds") or []:
        normalized = self._normalize_whatsapp_id(candidate)
        if normalized:
            bot_ids.add(normalized)
            # Also add without the device suffix (e.g., "5511999999999@[email protected]" -> "[email protected]")
            parts = normalized.split("@")
            if len(parts) > 2:
                bot_ids.add(f"{parts[0]}@{parts[-1]}")
    return bot_ids

This is safe for both multi-device and non-multi-device:

Workaround

  • Disable require_mention globally (not recommended for noisy groups)
  • Use free_response_chats with the specific group JID (allows all messages, not just replies)
  • Users must @mention the bot (impossible for voice messages)

PR fix notes

PR #29049: fix(whatsapp): match reply-to-bot when botIds carry device suffix

Description (problem / solution / changelog)

Summary

Fixes #29023. WhatsApp reply-to-bot detection (_message_is_reply_to_bot) consistently returned False on multi-device accounts because of a normalized-ID shape mismatch:

  • Baileys delivers quotedParticipant without the device suffix: "[email protected]"
  • sock.user.{id,lid} populates botIds with the device suffix (:N → normalized to @N): "5511999999999@[email protected]"

The set-membership check in gateway/platforms/whatsapp.py therefore never matched, breaking the reply-to-bot admission shortcut in groups configured with require_mention: true. This is especially painful for voice notes, where WhatsApp doesn't support text @mentions at all — there's literally no other way to wake the bot.

Fix

In _bot_ids_from_message, when a normalized bot id has three @-separated parts (i.e. carries a device suffix), add a suffix-stripped alias alongside the original. Legacy two-part ids are unchanged, so single-device accounts keep their existing behavior.

parts = normalized.split("@")
if len(parts) > 2:
    bot_ids.add(f"{parts[0]}@{parts[-1]}")

This is exactly the patch the issue author proposed in the Fix section.

Tests

Added two regression tests in tests/gateway/test_whatsapp_group_gating.py:

  • test_reply_to_bot_matches_device_suffixed_bot_ids — multi-device botIds (:10 suffix) + non-suffixed quotedParticipant must match and admit the message under require_mention=true.
  • test_reply_to_bot_legacy_non_multidevice_unchanged — legacy two-part ids continue to match as before.
$ python -m pytest tests/gateway/test_whatsapp_group_gating.py -q
28 passed in 2.52s

Risk

Tiny, surgical, single-function change. The added alias is only emitted when the id has a third @-separated component, so it cannot affect legacy callers. No other code paths consume _bot_ids_from_message in a way that would break on the extra alias (the other callers use it for split('@', 1)[0] bare-id extraction and in-checks against mentionedIds).

Changed files

  • gateway/platforms/whatsapp.py (modified, +10/-2)
  • tests/gateway/test_whatsapp_group_gating.py (modified, +35/-0)

Code Example

// bridge.js line ~244-247
const botIds = Array.from(new Set([
    normalizeWhatsAppId(sock.user?.id),     // "5511999999999@[email protected]"
    normalizeWhatsAppId(sock.user?.lid),    // "99999999999999@10@lid"
].filter(Boolean)));

---

quotedParticipant: "[email protected]"    // no @10
botIds:          {"5511999999999@[email protected]", "99999999999999@10@lid"}

---

def _message_is_reply_to_bot(self, data: Dict[str, Any]) -> bool:
    quoted_participant = self._normalize_whatsapp_id(data.get("quotedParticipant"))
    if not quoted_participant:
        return False
    return quoted_participant in self._bot_ids_from_message(data)

---

def _bot_ids_from_message(self, data: Dict[str, Any]) -> set[str]:
    bot_ids = set()
    for candidate in data.get("botIds") or []:
        normalized = self._normalize_whatsapp_id(candidate)
        if normalized:
            bot_ids.add(normalized)
            # Also add without the device suffix (e.g., "5511999999999@[email protected]" -> "[email protected]")
            parts = normalized.split("@")
            if len(parts) > 2:
                bot_ids.add(f"{parts[0]}@{parts[-1]}")
    return bot_ids
RAW_BUFFERClick to expand / collapse

[Bug]: WhatsApp reply-to-bot detection fails — device suffix mismatch breaks _message_is_reply_to_bot

Summary

The _message_is_reply_to_bot() method in gateway/platforms/whatsapp.py consistently returns False for WhatsApp group messages, even when the user explicitly replies (quotes) a bot message. This makes the reply-to-bot admission shortcut unusable on WhatsApp.

Impact: Users in groups with require_mention: true cannot trigger the bot by replying to its messages — they must always @mention the bot, which is impossible for voice/audio messages since WhatsApp voice notes cannot include text mentions.

Root Cause

The bridge sends botIds with the device suffix included (:N → normalized to @N):

// bridge.js line ~244-247
const botIds = Array.from(new Set([
    normalizeWhatsAppId(sock.user?.id),     // "5511999999999@[email protected]"
    normalizeWhatsAppId(sock.user?.lid),    // "99999999999999@10@lid"
].filter(Boolean)));

However, the quotedParticipant from Baileys contextInfo (extracted at bridge.js line ~321) arrives without the device suffix:

quotedParticipant: "[email protected]"    // no @10
botIds:          {"5511999999999@[email protected]", "99999999999999@10@lid"}

Since _message_is_reply_to_bot() does a strict set membership check:

def _message_is_reply_to_bot(self, data: Dict[str, Any]) -> bool:
    quoted_participant = self._normalize_whatsapp_id(data.get("quotedParticipant"))
    if not quoted_participant:
        return False
    return quoted_participant in self._bot_ids_from_message(data)

The match always fails: "[email protected]" in {"5511999999999@[email protected]", "99999999999999@10@lid"}False.

Environment

  • Platform: WhatsApp (Baileys bridge, multi-device)
  • Hermes version: Observed May 2026
  • Affected: All WhatsApp groups with require_mention: true

Reproduction

  1. Configure whatsapp.require_mention: true in config.yaml
  2. Join a WhatsApp group with the bot
  3. Have the bot send any message in the group
  4. Reply (quote) the bots message with a text reply
  5. Expected: Bot processes the reply without needing @mention
  6. Actual: Bot silently ignores the message — _message_is_reply_to_bot returns False

Fix

In gateway/platforms/whatsapp.py, modify _bot_ids_from_message() to also generate ID variants without the device suffix:

def _bot_ids_from_message(self, data: Dict[str, Any]) -> set[str]:
    bot_ids = set()
    for candidate in data.get("botIds") or []:
        normalized = self._normalize_whatsapp_id(candidate)
        if normalized:
            bot_ids.add(normalized)
            # Also add without the device suffix (e.g., "5511999999999@[email protected]" -> "[email protected]")
            parts = normalized.split("@")
            if len(parts) > 2:
                bot_ids.add(f"{parts[0]}@{parts[-1]}")
    return bot_ids

This is safe for both multi-device and non-multi-device:

Workaround

  • Disable require_mention globally (not recommended for noisy groups)
  • Use free_response_chats with the specific group JID (allows all messages, not just replies)
  • Users must @mention the bot (impossible for voice messages)

Type of Change

  • 🐛 Bug fix

Files Changed

  • gateway/platforms/whatsapp.py_bot_ids_from_message() — 3 lines added

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING