hermes - ✅(Solved) Fix Telegram groups can split into unexpected sessions when inbound messages carry message_thread_id without user-created topics [1 pull requests]

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…

PR fix notes

PR #13338: fix(telegram): avoid unexpected thread session splits

Description (problem / solution / changelog)

Fixes #13195.

Root cause: Telegram group and supergroup messages can include raw message_thread_id values even when the operator did not explicitly configure forum-topic routing. Hermes copied every inbound thread ID into source.thread_id, and build_session_key() then treated it as a hard session boundary, fragmenting one visible group conversation into multiple sessions.

Fix summary:

  • Collapse raw Telegram group thread IDs out of session routing by default.
  • Continue preserving explicitly configured group topics so topic skill bindings still work.
  • Add an opt-in telegram.preserve_group_thread_ids setting for operators who want raw per-thread sessions.
  • Collapse Telegram general topic 1 back to the parent group session.
  • Add regression coverage for default parent-session behavior, opt-in preservation, explicit topic preservation, and config bridging.

Tests:

  • uv run --frozen --python 3.11 --extra dev pytest -o addopts= tests/gateway/test_dm_topics.py tests/gateway/test_config.py -q -> 61 passed
  • git diff --check -- gateway/platforms/telegram.py gateway/config.py tests/gateway/test_dm_topics.py tests/gateway/test_config.py

Changed files

  • gateway/config.py (modified, +10/-0)
  • gateway/platforms/telegram.py (modified, +15/-4)
  • tests/gateway/test_config.py (modified, +16/-0)
  • tests/gateway/test_dm_topics.py (modified, +75/-0)

Code Example

group_sessions_per_user: false
telegram_ignore_group_thread_id_for_sessions: true

---

group_threads_share_parent_session: true
RAW_BUFFERClick to expand / collapse

Bug Description

In Telegram supergroups, Hermes currently treats any inbound message_thread_id as a distinct session dimension. In practice, Telegram can attach message_thread_id to group messages even when operators did not explicitly create forum topics. This causes one logical group conversation to split into multiple gateway sessions unexpectedly.

The result is confusing behavior such as:

  • /model changed in one visible group conversation but later messages execute in a different session
  • collaborators in the same group cannot reliably continue each other's context
  • a single group accumulates multiple session keys that look like separate threads even though users did not intentionally create topics

Why this is a problem

Current session key construction in gateway/session.py always appends thread_id for non-DM messages when present. That means Telegram's inbound message_thread_id becomes a hard session boundary even when the operator wants "one shared session per group".

For operators using Hermes as a collaborative group bot, this is surprising and breaks expected UX.

Evidence / Observed Behavior

In one Telegram supergroup, the same chat produced these session keys over time:

  • agent:main:telegram:group:-1003952440142:5203187663
  • agent:main:telegram:group:-1003952440142:8206193897
  • agent:main:telegram:group:-1003952440142:46
  • agent:main:telegram:group:-1003952440142:56
  • agent:main:telegram:group:-1003952440142:80
  • agent:main:telegram:group:-1003952440142:205

The :46, :56, :80, :205 entries are not user IDs. They came from inbound Telegram message_thread_id values stored as source.thread_id.

The corresponding session origins show examples like:

  • user_id=8206193897, thread_id=56
  • user_id=8206193897, thread_id=46
  • user_id=5203187663, thread_id=80
  • user_id=5203187663, thread_id=205

Notably, these session records had chat_topic: null, so this does not look like Hermes successfully mapping named configured topics. It looks like raw Telegram thread/message-thread identifiers being treated as session partitions.

Relevant Code Path

Telegram adapter:

  • gateway/platforms/telegram.py
    • reads message.message_thread_id
    • stores it as source.thread_id

Session routing:

  • gateway/session.py
    • build_session_key() always appends thread_id when present

Expected Behavior

Hermes should offer an explicit way to ignore Telegram group message_thread_id for session routing when operators want one shared session per parent group.

At minimum, there should be a config option along the lines of:

group_sessions_per_user: false
telegram_ignore_group_thread_id_for_sessions: true

or

group_threads_share_parent_session: true

so that all messages in the same Telegram group resolve to the parent group session, even if Telegram includes message_thread_id.

Actual Behavior

If Telegram includes message_thread_id, Hermes creates or routes to a separate session for that thread ID. This can happen even when users did not knowingly create topics, causing session fragmentation and model/session mismatch.

Suggested Solution

Any of these would help:

  1. Add a config toggle to ignore thread_id for Telegram group session key construction.
  2. Restrict thread-based session splitting to explicitly configured / known forum topics.
  3. Add a fallback mode where group-level session routing wins unless the operator explicitly opts into per-thread sessions.

Version / Environment

Observed on:

  • Hermes Agent v0.8.0 (2026.4.8)
  • Telegram gateway
  • Group/supergroup sessions

Additional Context

This is different from existing Telegram routing issues that are specifically about sending replies back into the right thread. The problem here is inbound session fragmentation: Telegram's message_thread_id becomes a session boundary too aggressively.

extent analysis

TL;DR

To fix the issue, add a config option to ignore Telegram group message_thread_id for session routing, allowing operators to opt for one shared session per parent group.

Guidance

  • Identify the build_session_key() function in gateway/session.py and consider modifying it to conditionally append thread_id based on a new config option.
  • Introduce a config toggle, such as telegram_ignore_group_thread_id_for_sessions, to control whether message_thread_id is used for session key construction in group conversations.
  • Review the Telegram adapter in gateway/platforms/telegram.py to ensure it correctly handles the new config option and ignores message_thread_id when required.
  • Test the changes with different scenarios, including group conversations with and without explicitly created topics, to verify the fix.

Example

# Example config snippet
group_sessions_per_user: false
telegram_ignore_group_thread_id_for_sessions: true

Notes

The solution requires careful consideration of the implications of ignoring message_thread_id on session routing and potential interactions with other features, such as reply routing.

Recommendation

Apply a workaround by adding a config option to ignore thread_id for Telegram group session key construction, allowing operators to opt for one shared session per parent group, as this provides a flexible solution that can be easily reverted or modified if needed.

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 Telegram groups can split into unexpected sessions when inbound messages carry message_thread_id without user-created topics [1 pull requests]