hermes - 💡(How to fix) Fix [Bug]: redact_sensitive_text() unconditionally masks Discord <@snowflake> mentions, breaking multi-bot @-pings

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…

Error Message

Additional Logs / Traceback (optional)

Root Cause

agent/redact.py treats Discord user mention IDs (<@digits>) as sensitive data and rewrites them to <@***> at the persistence boundary. This breaks any multi-bot setup that relies on DISCORD_ALLOW_BOTS=mentions because the snowflake ID is stripped before the message reaches Discord — so Discord renders it as literal plaintext and the mention never resolves.

Fix Action

Fix / Workaround

I've been running this patch locally for a few days with no issues. Happy to submit a PR if you'd like.

Code Example

Report       https://paste.rs/MNvFW
agent.log    https://paste.rs/AedEk
gateway.log  https://paste.rs/qX9T7

---



---

_DISCORD_MENTION_RE = re.compile(r"<@!?(\d{17,20})>")

---

if "<@" in text:
    text = _DISCORD_MENTION_RE.sub(lambda m: f"<@{'!' if '!' in m.group(0) else ''}***>", text)

---

# Discord user/role mentions (<@snowflake_id>)
# Default OFF: mention IDs are public syntax, not secrets.
# Masking them breaks cross-bot @-pings. Opt-in for export use cases only.
if "<@" in text and os.environ.get("HERMES_REDACT_DISCORD_MENTIONS", "").lower() in {"1", "true", "yes", "on"}:
    text = _DISCORD_MENTION_RE.sub(lambda m: f"<@{'!' if '!' in m.group(0) else ''}***>", text)
RAW_BUFFERClick to expand / collapse

Bug Description

agent/redact.py treats Discord user mention IDs (<@digits>) as sensitive data and rewrites them to <@***> at the persistence boundary. This breaks any multi-bot setup that relies on DISCORD_ALLOW_BOTS=mentions because the snowflake ID is stripped before the message reaches Discord — so Discord renders it as literal plaintext and the mention never resolves.

Discord mention IDs are public syntax. Every member of a channel can see them by right-clicking any @-mention. They're not credentials, tokens, or PII — they're the equivalent of a username handle. Masking them serves no security purpose and silently breaks inter-agent communication.

Steps to Reproduce

  1. Set up two Hermes profiles (Bot A and Bot B) on the same Discord server
  2. Configure Bot B with DISCORD_ALLOW_BOTS=mentions (the recommended safe default)
  3. From Bot A's session, use send_message to send a message to a shared channel containing <@BOT_B_ID> in the body
  4. Observe that Bot B never processes the message

Expected Behavior

The message arrives on Discord with a resolved @-mention (clickable blue pill), Bot B's message.mentions array contains its own ID, and its gateway processes the inbound message.

Actual Behavior

The message arrives on Discord as literal plaintext <@***>. The mentions array is empty. Bot B's DISCORD_ALLOW_BOTS=mentions filter correctly drops the message because there's no valid mention present.

Verified via Discord API: fetching the message object shows content: "<@***> [INFO] ..." and mentions: [].

Affected Component

Agent Core (conversation loop, context compression, memory)

Messaging Platform (if gateway-related)

Discord

Debug Report

Report       https://paste.rs/MNvFW
agent.log    https://paste.rs/AedEk
gateway.log  https://paste.rs/qX9T7

Operating System

macOS 15.7.7

Python Version

3.11

Hermes Version

v0.15.1 (tag v2026.5.29)

Additional Logs / Traceback (optional)

Root Cause Analysis (optional)

agent/redact.py line ~155 defines:

_DISCORD_MENTION_RE = re.compile(r"<@!?(\d{17,20})>")

Line ~424 inside redact_sensitive_text() unconditionally applies it:

if "<@" in text:
    text = _DISCORD_MENTION_RE.sub(lambda m: f"<@{'!' if '!' in m.group(0) else ''}***>", text)

redact_sensitive_text() runs on every assistant message at the persistence boundary (agent/chat_completion_helpers.py ~line 870) BEFORE the message enters conversation history, session DB, or platform delivery. So even if the model emits a correct <@digits> mention, the redactor strips the ID before Discord ever sees it.

This also creates a compounding problem: once the mention is masked in conversation history, the model reads <@***> from its own context and reproduces it in future messages — even if the redactor were somehow bypassed later. (This is tracked separately in #34649 as the "self-typed placeholder" variant.)

Proposed Fix (optional)

Gate the Discord mention masking behind an opt-in environment variable. Default behavior preserves mentions (safe for multi-bot). Operators who genuinely need to redact mention IDs for export/audit can opt in:

# Discord user/role mentions (<@snowflake_id>)
# Default OFF: mention IDs are public syntax, not secrets.
# Masking them breaks cross-bot @-pings. Opt-in for export use cases only.
if "<@" in text and os.environ.get("HERMES_REDACT_DISCORD_MENTIONS", "").lower() in {"1", "true", "yes", "on"}:
    text = _DISCORD_MENTION_RE.sub(lambda m: f"<@{'!' if '!' in m.group(0) else ''}***>", text)

Tests in tests/agent/test_redact.py::TestDiscordMentions should be updated to assert preservation by default, with an opt-in test that sets the env var and confirms masking still works when explicitly requested.

I've been running this patch locally for a few days with no issues. Happy to submit a PR if you'd like.

Are you willing to submit a PR for this?

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

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 - 💡(How to fix) Fix [Bug]: redact_sensitive_text() unconditionally masks Discord <@snowflake> mentions, breaking multi-bot @-pings