Skip to content

fix(telegram): send Direct Messages topics with direct_messages_topic_id#21941

Closed
max-chad wants to merge 1 commit into
NousResearch:mainfrom
max-chad:bot/20260508-telegram-dm-topic-direct-messages
Closed

fix(telegram): send Direct Messages topics with direct_messages_topic_id#21941
max-chad wants to merge 1 commit into
NousResearch:mainfrom
max-chad:bot/20260508-telegram-dm-topic-direct-messages

Conversation

@max-chad

@max-chad max-chad commented May 8, 2026

Copy link
Copy Markdown

Fixes Telegram Direct Messages topic delivery after Bot API/PTB split topic routing into separate fields.\n\nRoot cause: Hermes stored Telegram Direct Messages topic ids in source.thread_id and sent them as message_thread_id, which is for forum/group topics. Telegram rejects that with 'Thread not found'; the existing fallback retried without thread_id, so replies landed in the root/global DM view.\n\nChange:\n- route positive private/direct chat topic ids via direct_messages_topic_id;\n- preserve message_thread_id for group/forum topics;\n- keep General forum-topic send behavior unchanged;\n- add regressions for explicit dm metadata and current gateway metadata shape.\n\nValidation:\n- .venv/bin/python -m pytest tests/gateway/test_telegram_thread_fallback.py -q → 13 passed\n- .venv/bin/python -m compileall -q gateway/platforms/telegram.py\n- .venv/bin/python -m py_compile gateway/platforms/telegram.py tests/gateway/test_telegram_thread_fallback.py\n- git diff --check

@GodsBoy

GodsBoy commented May 8, 2026

Copy link
Copy Markdown
Contributor

Updating after reading PR #22053 by @leehack, which proposes a different (and structurally more correct) fix for the same issue and supersedes the approach in this PR.

The scope analysis from earlier still applies: the original diff fixes one outgoing send site, and gateway/platforms/telegram.py has ~15 other outgoing sites that still pass bare message_thread_id (text fallbacks, media sends, approval keyboards, /model picker, slash confirm, update prompts, callback-query reply, DM topic seed message, voice, audio, animation, multi-image, plus typing indicator). #22053 covers all of those.

The bigger issue is the field choice. After comparing both diffs, the underlying Bot API behavior is subtler than this PR's approach captures:

Hermes creates private-chat topic lanes via create_forum_topic in private chats. That works structurally because Topics mode supports it, but Telegram's Bot API does NOT expose these as Bot API "Direct Messages topics" on incoming updates. They are not represented as direct_messages_topic_id in the Bot API 10.0 model. So sending with direct_messages_topic_id (this PR's approach) does not route them correctly either; Telegram does not recognize Hermes-created topic lanes as Direct Messages topics.

The actual mechanism Telegram supports for keeping replies in these lanes is reply_to_message_id against the inbound topic anchor. That is what #22053 implements:

  1. Forum/supergroup topics: message_thread_id (unchanged)
  2. True Bot API Direct Messages topics: explicit direct_messages_topic_id metadata still works (opt-in)
  3. Hermes-created private DM topic lanes: reply-anchor fallback (no thread kwarg, send replies to the inbound anchor)

#22053 also propagates the routing through shared helpers in gateway/platforms/base.py and the reply-anchor plumbing in gateway/run.py so it covers retry, dispatch, and follow-up turns alongside the direct send sites.

Recommend closing this PR as superseded so the maintainer reviews only one fix. The _topic_send_kwargs single-funnel abstraction here was on the right track; #22053 keeps that idea (_thread_kwargs_for_send) and points it at reply-anchor routing for the Hermes-DM-topic case.

Thanks for filing. The discussion in this thread helped clarify the bug surface.

@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Thanks for filing this — you correctly identified the post-Bot-API-10.0 regression and that direct_messages_topic_id was a relevant Bot API field. We ended up merging the broader fix in #22410 (salvage of #22053 by @leehack), which preserves your direct_messages_topic_id opt-in path as case 2 of a three-case routing model:

  1. Forum / supergroup topics: message_thread_id (unchanged).
  2. True Bot API Direct Messages topics: explicit direct_messages_topic_id metadata opt-in — your contribution here.
  3. Hermes-created private DM topic lanes: reply-anchor fallback (message_thread_id + reply_to_message_id together).

The third case turned out to be the more common one for our users — Hermes creates private-chat topic lanes via create_forum_topic, but those aren't classified as Bot API "Direct Messages topics" in incoming updates, so direct_messages_topic_id doesn't route them. The merged fix covers all three cases.

Your single-funnel _topic_send_kwargs abstraction was on the right track — #22053 used the same pattern (_thread_kwargs_for_send) and extended it across all ~15 outgoing send sites in gateway/platforms/telegram.py.

Closing as superseded by #22410 — thanks for the contribution and the discussion that helped clarify the bug surface!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants