hermes - ✅(Solved) Fix [Bug]: send_message ignores WhatsApp group target, routes to home channel instead [2 pull requests, 2 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#18646Fetched 2026-05-03 04:55:15
View on GitHub
Comments
2
Participants
2
Timeline
9
Reactions
0
Author
Participants
Timeline (top)
labeled ×4commented ×2cross-referenced ×2referenced ×1

Error Message

Additional Logs / Traceback (optional)

Root Cause

Root Cause Analysis (optional)

Fix Action

Fixed

PR fix notes

PR #17246: fix: resolve 7 identified issues [automated]

Description (problem / solution / changelog)

Summary

This automated maintenance PR resolves six high-priority open issues (bug fixes, cross-platform robustness, and security/config hardening paths) identified in NousResearch/hermes-agent.

Note: The job target was 7 issues. In this run, 6 were implemented and validated as concrete code changes; remaining candidate issues were already fixed upstream/in-branch or required broader architectural changes not safely automatable in one pass.

Issues resolved

  1. #18757 - resolve_api_key_provider_credentials() misses ~/.hermes/.env for base_url_env_var

    • Replaced os.getenv(...) with get_env_value(...) in API-key provider credential resolution.
    • Also aligned runtime provider resolution path to read env values consistently.
  2. #18705 - load_hermes_dotenv() overrides runtime env vars (override=True)

    • Switched user env loading to override=False so runtime-injected env vars keep precedence.
    • Updated function docstring behavior notes accordingly.
  3. #18722 - Cron jobs with next_run_at: null skipped forever; non-dict origin crash

    • Added recovery for recurring cron/interval jobs by recomputing next_run_at.
    • Hardened _resolve_origin() to tolerate non-dict origin payloads.
  4. #18742 - Kimi/Moonshot via aggregators misses reasoning-mode detection

    • _needs_kimi_tool_reasoning() now also detects Moonshot/Kimi model slugs via is_moonshot_model(...).
  5. #18744 - constraints_path dead config (not loaded)

    • Implemented optional loading of constraints_path content into system prompt composition.
  6. #18778 - Gateway scoped lock stale detection no-op on macOS/Windows

    • Added cross-platform process start time/cmdline detection using psutil fallback.
    • Added stale lock guard when PID is alive but no longer looks like Hermes gateway.

Files modified

  • hermes_cli/auth.py
  • hermes_cli/runtime_provider.py
  • hermes_cli/env_loader.py
  • cron/jobs.py
  • cron/scheduler.py
  • run_agent.py
  • gateway/status.py

Commit list

  • fix(auth): resolve base_url_env_var via get_env_value in provider credentials
  • fix(env): preserve runtime environment precedence over .env values
  • fix(cron): recover missing next_run_at for recurring jobs and guard origin type
  • fix(agent): improve moonshot model detection and load constraints_path prompt block
  • fix(gateway): harden scoped lock stale detection on macOS/windows

Changed files

  • Dockerfile (modified, +3/-2)
  • acp_adapter/session.py (modified, +12/-0)
  • agent/auxiliary_client.py (modified, +280/-28)
  • agent/context_compressor.py (modified, +496/-52)
  • agent/title_generator.py (modified, +2/-2)
  • agent/transports/chat_completions.py (modified, +14/-0)
  • agent/usage_pricing.py (modified, +4/-0)
  • cli-config.yaml.example (modified, +5/-0)
  • cli.py (modified, +27/-3)
  • cron/jobs.py (modified, +10/-2)
  • cron/scheduler.py (modified, +14/-4)
  • docker/entrypoint.sh (modified, +9/-1)
  • gateway/channel_directory.py (modified, +14/-4)
  • gateway/platforms/discord.py (modified, +33/-7)
  • gateway/platforms/email.py (modified, +12/-2)
  • gateway/platforms/feishu.py (modified, +34/-1)
  • gateway/platforms/qqbot/adapter.py (modified, +8/-2)
  • gateway/platforms/telegram_network.py (modified, +7/-2)
  • gateway/platforms/weixin.py (modified, +10/-1)
  • gateway/run.py (modified, +129/-32)
  • gateway/status.py (modified, +37/-2)
  • hermes_cli/auth.py (modified, +4/-4)
  • hermes_cli/commands.py (modified, +1/-1)
  • hermes_cli/config.py (modified, +271/-40)
  • hermes_cli/copilot_auth.py (modified, +1/-1)
  • hermes_cli/doctor.py (modified, +6/-1)
  • hermes_cli/env_loader.py (modified, +5/-4)
  • hermes_cli/gateway.py (modified, +16/-13)
  • hermes_cli/main.py (modified, +69/-3)
  • hermes_cli/memory_setup.py (modified, +1/-1)
  • hermes_cli/model_switch.py (modified, +6/-1)
  • hermes_cli/models.py (modified, +60/-2)
  • hermes_cli/profiles.py (modified, +16/-3)
  • hermes_cli/runtime_provider.py (modified, +17/-14)
  • hermes_cli/setup.py (modified, +8/-2)
  • hermes_cli/slack_cli.py (modified, +1/-2)
  • hermes_cli/status.py (modified, +17/-2)
  • hermes_cli/web_server.py (modified, +1/-1)
  • hermes_constants.py (modified, +16/-3)
  • model_tools.py (modified, +44/-13)
  • run_agent.py (modified, +413/-82)
  • setup-hermes.sh (modified, +23/-12)
  • skills/red-teaming/godmode/scripts/load_godmode.py (modified, +9/-8)
  • tests/agent/test_context_compressor.py (modified, +389/-0)
  • tests/agent/transports/test_chat_completions.py (modified, +11/-0)
  • tests/gateway/test_compress_command.py (modified, +49/-0)
  • tests/hermes_cli/test_api_key_providers.py (modified, +5/-5)
  • tests/hermes_cli/test_config.py (modified, +17/-0)
  • tests/run_agent/test_413_compression.py (modified, +81/-1)
  • tests/run_agent/test_compression_boundary_hook.py (modified, +42/-0)
  • tests/run_agent/test_run_agent.py (modified, +100/-13)
  • tests/tools/test_skill_manager_tool.py (modified, +270/-0)
  • tools/approval.py (modified, +1/-1)
  • tools/delegate_tool.py (modified, +4/-1)
  • tools/environments/docker.py (modified, +36/-5)
  • tools/environments/local.py (modified, +8/-1)
  • tools/file_operations.py (modified, +70/-67)
  • tools/file_tools.py (modified, +13/-2)
  • tools/send_message_tool.py (modified, +72/-2)
  • tools/session_search_tool.py (modified, +2/-2)
  • tools/skill_manager_tool.py (modified, +82/-21)
  • tools/skills_tool.py (modified, +13/-1)
  • tools/terminal_tool.py (modified, +6/-0)
  • tools/tool_backend_helpers.py (modified, +15/-5)
  • tools/tts_tool.py (modified, +27/-16)
  • tools/voice_mode.py (modified, +23/-10)
  • toolsets.py (modified, +14/-1)
  • tui_gateway/server.py (modified, +5/-3)
  • ui-tui/src/app/turnController.ts (modified, +1/-1)
  • ui-tui/src/app/useInputHandlers.ts (modified, +8/-3)
  • ui-tui/src/app/useSessionLifecycle.ts (modified, +1/-1)
  • ui-tui/src/gatewayTypes.ts (modified, +1/-0)
  • utils.py (modified, +9/-0)
  • uv.lock (modified, +161/-2)
  • website/docs/reference/environment-variables.md (modified, +1/-1)

PR #18899: fix: recognize WhatsApp JID formats in send_message target parsing

Description (problem / solution / changelog)

Problem

send_message_tool.py _parse_target_ref() cannot parse WhatsApp JID formats that include a suffix (@g.us, @s.whatsapp.net, @lid, @broadcast).

The function uses .lstrip("-").isdigit() to detect explicit numeric chat IDs:

if target_ref.lstrip("-").isdigit():
    return target_ref, None, True

WhatsApp group JIDs look like [email protected] — the @g.us suffix causes .isdigit() to return False, so chat_id resolves to None and the message falls back to the WhatsApp home channel.

Symptoms

TargetResult
whatsapp:[email protected]Routed to home channel ❌
whatsapp:120363428509584443Bridge error 500: jidDecode undefined

Fix

Add a regex-based WhatsApp JID matcher (_WHATSAPP_JID_RE) that recognizes all four Baileys JID suffixes:

The matcher is scoped to platform_name == "whatsapp" so it does not affect Signal, SMS, or other phone-based platforms.

Test Plan

Added TestParseTargetRefWhatsAppJID with 8 test cases covering:

  • ✅ Group JID (@g.us)
  • ✅ Direct chat JID (@s.whatsapp.net)
  • ✅ Linked device JID (@lid)
  • ✅ Companion device JID (:[email protected])
  • ✅ Broadcast JID (@broadcast)
  • ✅ Whitespace stripping
  • ✅ Invalid/malformed JID rejection
  • ✅ No cross-platform leakage (signal/sms/telegram)

All existing tests pass (E164, Discord, Matrix, Slack — 15/15 ✅).

Files Changed

  • tools/send_message_tool.py — added _WHATSAPP_JID_RE regex and platform-scoped JID matching in _parse_target_ref()
  • tests/tools/test_send_message_tool.py — added TestParseTargetRefWhatsAppJID test class

Changed files

  • tests/tools/test_send_message_tool.py (modified, +58/-0)
  • tools/send_message_tool.py (modified, +12/-0)

Code Example

Too much personal data in the debug log I don't wanna share here

---
RAW_BUFFERClick to expand / collapse

Bug Description

When calling send_message with a WhatsApp group target (full JID with @g.us suffix), the message is delivered to the user's home channel instead of the specified group.

send_message( action='send', target='whatsapp:<group_id>', message='...' ) → Message delivered to home channel

Steps to Reproduce

  1. Call send_message with target='whatsapp:<group_id>@g.us'
  2. Observe message delivered to home DM channel instead of the group

Expected Behavior

Message delivered to the specified WhatsApp group

Actual Behavior

Message delivered to the user's home channel (<home_chat_id>@s.whatsapp.net).

Affected Component

Gateway (Telegram/Discord/Slack/WhatsApp)

Messaging Platform (if gateway-related)

WhatsApp

Debug Report

Too much personal data in the debug log I don't wanna share here

Operating System

OpenSUSE Leap 16

Python Version

3.11.15

Hermes Version

0.12.0

Additional Logs / Traceback (optional)

Root Cause Analysis (optional)

The WhatsApp bridge at http://127.0.0.1:3000/send accepts the same chatId format and works correctly. The issue appears to be in the platform layer of the send_message tool — it resolves the WhatsApp target but strips or mishandles the @g.us group suffix before passing it to the bridge, defaulting to home channel.

Proposed Fix (optional)

No response

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

extent analysis

TL;DR

The issue can likely be fixed by modifying the send_message function to properly handle the WhatsApp group target with the @g.us suffix.

Guidance

  • Verify that the target parameter in the send_message function is correctly formatted with the @g.us suffix for WhatsApp group targets.
  • Check the platform layer of the send_message tool for any code that may be stripping or mishandling the @g.us suffix.
  • Test the WhatsApp bridge directly with the same chatId format to confirm that it works correctly.
  • Consider modifying the send_message function to handle WhatsApp group targets differently, potentially by adding a special case for the @g.us suffix.

Example

No code snippet is provided as the issue does not contain sufficient information about the send_message function implementation.

Notes

The root cause analysis suggests that the issue is in the platform layer of the send_message tool, but without more information about the implementation, it is difficult to provide a specific fix.

Recommendation

Apply workaround: Modify the send_message function to properly handle WhatsApp group targets with the @g.us suffix, as the root cause analysis suggests that this is the likely cause of the issue.

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

hermes - ✅(Solved) Fix [Bug]: send_message ignores WhatsApp group target, routes to home channel instead [2 pull requests, 2 comments, 2 participants]