Bug Description
When a user interacts with Hermes inside a Telegram DM Topic (which uses Hermes's telegram_dm_topic_reply_fallback feature to simulate topics via reply anchors), text messages are routed correctly to the topic, but media messages (such as screenshots, images, and documents) are erroneously dropped into the root DM chat (visible as "All Chats" only) instead of staying within the topic thread.
Root Cause The Telegram Bot API does not support the message_thread_id parameter inside Private Chats (DMs) and will throw a BadRequest: message thread not found error if it is provided.
In gateway/platforms/telegram.py, the send method for standard text messages contained an explicit safeguard (if used_thread_fallback...) that stripped message_thread_id before sending, relying solely on reply_to_message_id to route the text message to the correct simulated topic.
However, media sending methods (such as send_multiple_images, send_image_file, send_document) did not have this safeguard. As a result:
Media methods attempted to send with a message_thread_id.
The Telegram Bot API rejected the request with a BadRequest.
Hermes's internal retry mechanism (_send_with_dm_topic_reply_anchor_retry) caught the exception and attempted to recover by stripping both message_thread_id and the reply_to_message_id anchor.
The media was then successfully resent, but without its reply anchor, causing it to drop out of the topic chain and land in the root chat.
Resolution Centralized the thread ID omission logic directly inside the _thread_kwargs_for_send helper method so that it applies globally across all message types.
Steps to Reproduce
To test this and verify the bug has been fixed, follow these steps:
Open your Telegram Direct Message (Private Chat) with Hermes.
Open any specific topic/thread (using a client that supports DM topics like Nagram, or via Hermes's reply-chain threads).
Send a command inside that specific topic that generates media, such as asking Hermes to take a /screenshot or generate an image.
Wait for Hermes to respond with the media.
Expected Behavior
Before the fix (The Bug): Hermes sends the screenshot, but because of the internal error, it loses its topic mapping. You receive it, but it shows up disconnected in your main "All Chats" view rather than inside the topic where you asked for it.
After the fix (Expected): Hermes sends the screenshot and it appears neatly as a direct reply inside the specific topic where you requested it, keeping your conversation history clean and organized.
Actual Behavior
Hermes sends the screenshot, but because of the internal error, it loses its topic mapping. You receive it, but it shows up disconnected in your main "All Chats" view rather than inside the topic where you asked for it.
Affected Component
Gateway (Telegram/Discord/Slack/WhatsApp)
Messaging Platform (if gateway-related)
Telegram
Debug Report
⚠️ This will upload the following to a public paste service:
• System info (OS, Python version, Hermes version, provider, which API keys
are configured — NOT the actual keys)
• Recent log lines (agent.log, errors.log, gateway.log — may contain
conversation fragments and file paths)
• Full agent.log and gateway.log (up to 512 KB each — likely contains
conversation content, tool outputs, and file paths)
Pastes auto-delete after 6 hours.
Collecting debug report...
Uploading...
Debug report uploaded:
Report https://paste.rs/WCmPP
agent.log https://paste.rs/2xqpD
gateway.log https://paste.rs/lT93d
⏱ Pastes will auto-delete in 6 hours.
To delete now: hermes debug delete <url>
Operating System
Windows
Python Version
3.12
Hermes Version
0.15
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
No response
Proposed Fix (optional)
Changes Made File: gateway/platforms/telegram.py Method: _thread_kwargs_for_send
Modified the return statement for the telegram_dm_topic_reply_fallback block to return {"message_thread_id": None} instead of attempting to parse the thread_id.
diff
if reply_to_message_id is None:
direct_topic_id = cls._metadata_direct_messages_topic_id(metadata)
if direct_topic_id is not None:
return {
"message_thread_id": None,
"direct_messages_topic_id": int(direct_topic_id),
}
return {}
-
return {"message_thread_id": cls._message_thread_id_for_send(thread_id)}
-
return {"message_thread_id": None}
direct_topic_id = cls._metadata_direct_messages_topic_id(metadata)
Are you willing to submit a PR for this?
Bug Description
When a user interacts with Hermes inside a Telegram DM Topic (which uses Hermes's telegram_dm_topic_reply_fallback feature to simulate topics via reply anchors), text messages are routed correctly to the topic, but media messages (such as screenshots, images, and documents) are erroneously dropped into the root DM chat (visible as "All Chats" only) instead of staying within the topic thread.
Root Cause The Telegram Bot API does not support the message_thread_id parameter inside Private Chats (DMs) and will throw a BadRequest: message thread not found error if it is provided.
In gateway/platforms/telegram.py, the send method for standard text messages contained an explicit safeguard (if used_thread_fallback...) that stripped message_thread_id before sending, relying solely on reply_to_message_id to route the text message to the correct simulated topic.
However, media sending methods (such as send_multiple_images, send_image_file, send_document) did not have this safeguard. As a result:
Media methods attempted to send with a message_thread_id.
The Telegram Bot API rejected the request with a BadRequest.
Hermes's internal retry mechanism (_send_with_dm_topic_reply_anchor_retry) caught the exception and attempted to recover by stripping both message_thread_id and the reply_to_message_id anchor.
The media was then successfully resent, but without its reply anchor, causing it to drop out of the topic chain and land in the root chat.
Resolution Centralized the thread ID omission logic directly inside the _thread_kwargs_for_send helper method so that it applies globally across all message types.
Steps to Reproduce
To test this and verify the bug has been fixed, follow these steps:
Open your Telegram Direct Message (Private Chat) with Hermes.
Open any specific topic/thread (using a client that supports DM topics like Nagram, or via Hermes's reply-chain threads).
Send a command inside that specific topic that generates media, such as asking Hermes to take a /screenshot or generate an image.
Wait for Hermes to respond with the media.
Expected Behavior
Before the fix (The Bug): Hermes sends the screenshot, but because of the internal error, it loses its topic mapping. You receive it, but it shows up disconnected in your main "All Chats" view rather than inside the topic where you asked for it.
After the fix (Expected): Hermes sends the screenshot and it appears neatly as a direct reply inside the specific topic where you requested it, keeping your conversation history clean and organized.
Actual Behavior
Hermes sends the screenshot, but because of the internal error, it loses its topic mapping. You receive it, but it shows up disconnected in your main "All Chats" view rather than inside the topic where you asked for it.
Affected Component
Gateway (Telegram/Discord/Slack/WhatsApp)
Messaging Platform (if gateway-related)
Telegram
Debug Report
⚠️ This will upload the following to a public paste service: • System info (OS, Python version, Hermes version, provider, which API keys are configured — NOT the actual keys) • Recent log lines (agent.log, errors.log, gateway.log — may contain conversation fragments and file paths) • Full agent.log and gateway.log (up to 512 KB each — likely contains conversation content, tool outputs, and file paths) Pastes auto-delete after 6 hours. Collecting debug report... Uploading... Debug report uploaded: Report https://paste.rs/WCmPP agent.log https://paste.rs/2xqpD gateway.log https://paste.rs/lT93d ⏱ Pastes will auto-delete in 6 hours. To delete now: hermes debug delete <url>Operating System
Windows
Python Version
3.12
Hermes Version
0.15
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
No response
Proposed Fix (optional)
Changes Made File: gateway/platforms/telegram.py Method: _thread_kwargs_for_send
Modified the return statement for the telegram_dm_topic_reply_fallback block to return {"message_thread_id": None} instead of attempting to parse the thread_id.
diff
Are you willing to submit a PR for this?