Summary
PR #22410 (commit b3239572f) fixed DM topic routing for live messages in gateway/platforms/telegram.py::TelegramAdapter.send() after Bot API 10.0 broke sendMessage(message_thread_id=N) for private chats with topics. However, the cron delivery path (tools/send_message_tool.py::_send_telegram) was not updated with the same three-mode routing logic.
Replication
- Create DM topics in a private Telegram chat (Bot API 9.3+)
- Configure a cron with
deliver: telegram:<chat_id>:<thread_id>
- Cron executes → message lands in General topic instead of the specified thread
Root Cause
tools/send_message_tool.py::_send_telegram sends with bare message_thread_id parameter, which Bot API 10.0 (2026-05-08) now rejects for private chats with topics. The fix requires message_thread_id + reply_to_message_id (anchor message) together, as implemented in the gateway adapter.
Expected Behavior
Cron delivery should use the same three-mode routing as TelegramAdapter.send():
- Forum/supergroup →
message_thread_id
- Bot API DM topics →
direct_messages_topic_id
- Hermes-created private DM topic lanes →
message_thread_id + reply_to_message_id (anchor) together
Workaround (temporary)
All 12 crons moved to deliver to General (telegram:<chat_id> without thread_id) with emoji prefixes for visual filtering.
Related
Environment
Summary
PR #22410 (commit
b3239572f) fixed DM topic routing for live messages ingateway/platforms/telegram.py::TelegramAdapter.send()after Bot API 10.0 brokesendMessage(message_thread_id=N)for private chats with topics. However, the cron delivery path (tools/send_message_tool.py::_send_telegram) was not updated with the same three-mode routing logic.Replication
deliver: telegram:<chat_id>:<thread_id>Root Cause
tools/send_message_tool.py::_send_telegramsends with baremessage_thread_idparameter, which Bot API 10.0 (2026-05-08) now rejects for private chats with topics. The fix requiresmessage_thread_id+reply_to_message_id(anchor message) together, as implemented in the gateway adapter.Expected Behavior
Cron delivery should use the same three-mode routing as
TelegramAdapter.send():message_thread_iddirect_messages_topic_idmessage_thread_id+reply_to_message_id(anchor) togetherWorkaround (temporary)
All 12 crons moved to deliver to General (
telegram:<chat_id>without thread_id) with emoji prefixes for visual filtering.Related
Environment
privatewithhas_topics_enabled: true