Skip to content

fix(cron): retry Telegram DM topic delivery with reply anchor on thread-not-found#23249

Open
devsart95 wants to merge 1 commit into
NousResearch:mainfrom
devsart95:fix/cron-telegram-dm-topics-22773
Open

fix(cron): retry Telegram DM topic delivery with reply anchor on thread-not-found#23249
devsart95 wants to merge 1 commit into
NousResearch:mainfrom
devsart95:fix/cron-telegram-dm-topics-22773

Conversation

@devsart95

Copy link
Copy Markdown

Summary

When a cron job delivers output to a Telegram DM topic via telegram:chat_id:thread_id, the _send_telegram function in send_message_tool.py sends with bare message_thread_id — which Bot API 10.0+ (server-side change ~2026-05-08) rejects for private chats with topics. The gateway adapter was fixed in PR #22410, but the cron delivery path was missed.

Root cause

_send_telegram() at line 787-808 sets thread_kwargs["message_thread_id"] for topic delivery. Bot API 10.0 requires message_thread_id + reply_to_message_id (anchor) together for private DM topics. Without the anchor, the API returns "Message thread not found".

Fix

Added an elif branch in the existing send-error handler: when the error contains "thread not found" and message_thread_id was set:

  1. Send anchor: send a minimal placeholder message (.) to the main chat to get a message_id
  2. Retry: resend the actual message with message_thread_id + reply_to_message_id pointing to the placeholder
  3. Cleanup: delete the placeholder (best-effort)

If the anchor retry also fails, the original error is re-raised so the caller sees the root cause.

Three-mode routing now covered

Mode Channel type Parameters Status
1 Forum/supergroup topic message_thread_id ✅ Works (unchanged)
2 Bot API DM topic (direct_messages_topic_id) direct_messages_topic_id ✅ Adapter only (out of scope)
3 Hermes-created private DM topic lane message_thread_id + reply_to_message_id New in tool

Files changed

  • tools/send_message_tool.py — +42 lines in _send_telegram() error handler

Fixes #22773

X: @rojassartorio

…ad-not-found

Bot API 10.0+ (server-side, ~2026-05-08) rejects sendMessage calls that
use bare message_thread_id for private DM topics. The fix (PR NousResearch#22410)
was applied to TelegramAdapter.send() in the gateway, but the cron
delivery path in tools/send_message_tool.py::_send_telegram was not
updated.

When _send_telegram gets "Message thread not found" after including
message_thread_id in the send kwargs, it now:
1. Sends a minimal placeholder message (no thread_id) to get a
   message_id that can serve as a reply anchor
2. Retries the actual message with message_thread_id +
   reply_to_message_id pointing to the placeholder
3. Deletes the placeholder (silent best-effort)

This implements the three-mode routing from TelegramAdapter:
- Forum/supergroup topics -> message_thread_id (unchanged)
- Bot API DM topics -> direct_messages_topic_id (adapter only)
- Hermes-created private DM topic lanes -> message_thread_id +
  reply_to_message_id anchor (new in tool)

Fixes NousResearch#22773

X: @rojassartorio

Co-authored-by: Rojas Sartorio <rojassartorio@users.noreply.github.com>
@salemsayed

Copy link
Copy Markdown

Thanks for working on this. I hit what looks like an adjacent cron-path gap while auditing a live Hermes deployment against current main.

This PR appears to cover the standalone send_message_tool.py path by retrying private DM-topic delivery with a reply anchor after Telegram returns thread not found. That is useful, but there is also a scheduler/live-adapter path that still drops the DM-topic metadata before the Telegram adapter sees it.

Current cron/scheduler.py builds live-adapter metadata as only:

send_metadata = {"thread_id": thread_id} if thread_id else None
runtime_adapter.send(chat_id, text_to_send, metadata=send_metadata)

For explicit Telegram DM-topic cron deliveries such as telegram:<chat_id>:<direct_messages_topic_id>, this means the live adapter sees only thread_id and not direct_messages_topic_id / related DM-topic routing metadata. The Telegram adapter then treats it as a private-topic send without a reply anchor and logs a warning like:

Telegram DM topic delivery requires a reply anchor; use standalone delivery with direct_messages_topic_id

Cron then falls back to the standalone path, so this may not fully break delivery, but it creates repeated warning noise and makes the first attempted path fail even though the target had enough information in the cron deliver value.

I have a small local patch + focused tests for cron/scheduler.py / tests/cron/test_scheduler.py that forwards the DM-topic metadata into the live-adapter send metadata instead of passing only thread_id. The focused tests pass locally. This seems complementary to this PR rather than a duplicate: your change hardens the standalone/tool fallback, while this would prevent the cron live-adapter path from failing first for explicit DM-topic targets.

Would you prefer that patch as an additional commit here, or as a separate small PR linked to #22773?

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

Labels

comp/cron Cron scheduler and job management P2 Medium — degraded but workaround exists platform/telegram Telegram bot adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cron delivery to private DM topics broken after PR #22410 — send_message_tool.py missing three-mode routing

3 participants