Skip to content

[Bug]: Telegram streaming.mode="partial" completely disabled when replyToMode is not "off" #73505

Description

@choury

Bug type

Regression (worked before, now fails)

Summary

When channels.telegram.replyToMode is set to "first" (or any non-"off" value), Telegram streaming preview (streaming.mode: "partial") is completely disabled. The bot produces no visible output during generation, then delivers all messages at once when the run completes.

Steps to reproduce

  1. Set channels.telegram.replyToMode to "first" (non-default) in openclaw.json
  2. Set channels.telegram.streaming.mode to "partial"
  3. Send a message to the bot and observe response delivery

Expected behavior

Streaming preview should work normally — text appears character by character (or in chunks) via editMessageText on the preview message. The replyToMode setting should only affect which message is replied to, not whether streaming is active.

Actual behavior

Zero visible output during generation. All response messages arrive at once after the run finishes. Streaming is completely non-functional.

Root cause

In extensions/telegram/src/bot-message-dispatch.ts (dist: bot-msflwCEW.js in 2026.4.26):

const hasNativeQuoteReply = replyToMode !== "off" && Object.keys(replyQuoteByMessageId).length > 0;
const canStreamAnswerDraft = previewStreamingEnabled && !hasNativeQuoteReply && ...

When replyToMode !== "off", the handler always calls addTelegramNativeQuoteCandidate(replyQuoteByMessageId, msg.message_id, ...), which unconditionally populates replyQuoteByMessageId. This makes Object.keys(replyQuoteByMessageId).length > 0 always true, so hasNativeQuoteReply is always true, and canStreamAnswerDraft is always false.

The intended reason to disable streaming is when the reply contains a Telegram quote (i.e. reply_parameters.quote), because that parameter cannot be passed via editMessageText. A plain reply_to_message_id is fully compatible with streaming — it is passed on the first sendMessage call and subsequent editMessageText calls work fine. The code already correctly passes draftReplyToMessageId into createTelegramDraftStream, confirming the two features are designed to coexist.

Suggested fix

// Before (bug)
const hasNativeQuoteReply = replyToMode !== "off" && Object.keys(replyQuoteByMessageId).length > 0;

// After
const hasNativeQuoteReply = replyToMode !== "off" && replyQuoteText != null && replyQuoteMessageId != null;

This limits the streaming-disable guard to only genuine Telegram quote replies (where the user has selected quoted text), leaving plain reply-to-message streaming fully functional.

Configuration

{
  "channels": {
    "telegram": {
      "replyToMode": "first",
      "streaming": {
        "mode": "partial"
      }
    }
  }
}

Version

OpenClaw 2026.4.26

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions