Skip to content

[Bug]: Telegram tool-progress preview silently disabled when channels.telegram.replyToMode != "off" (doc/runtime mismatch) #73487

Description

@GodsBoy

Bug type

Behavior bug (silent feature disable, no warning, doc mismatch)

Summary

Per docs/channels/telegram.md and docs/concepts/streaming.md, Telegram tool-progress preview updates (the Working… • tool: X lines shown during tool execution) are documented as enabled by default since v2026.4.22. In practice, when the user has any value other than "off" for channels.telegram.replyToMode, the entire tool-progress preview path is silently disabled because answerLane.stream is never created. No warning is logged. Docs do not mention this exclusion.

Environment

  • OpenClaw: 2026.4.26 (be8c246)
  • OS: Ubuntu 24.04 (Hetzner CCX13 / 8GB)
  • Node: NodeSource v24.14.1 (/usr/bin/node), system install
  • Channel: Telegram DM
  • Primary model: openai-codex/gpt-5.5
  • Auth: ChatGPT OAuth via Codex CLI

Repro

  1. Set channels.telegram.replyToMode: "first" (or any value other than "off").
  2. Confirm channels.telegram.streaming.mode: "partial" and streaming.preview.toolProgress: true (default per docs since v2026.4.22).
  3. Restart the gateway.
  4. In a Telegram DM with the agent, send a prompt that triggers tool use (e.g., please run cat /etc/hostname and tell me the result).
  5. Expected per docs: Working… • tool: ... preview message visible during tool execution.
  6. Actual: no tool-progress message ever appears. The agent eventually replies with the final answer, but the user has no visibility into what tools were used while the model was running.

Root cause

In extensions/telegram/src/bot-message-dispatch.ts (compiled to bot-msflwCEW.js):

const hasNativeQuoteReply = replyToMode !== "off" && Object.keys(replyQuoteByMessageId).length > 0;
const canStreamAnswerDraft = previewStreamingEnabled && !hasNativeQuoteReply && !accountBlockStreamingEnabled && !forceBlockStreamingForReasoning;
// ...
const lanes = {
    answer: createDraftLane("answer", canStreamAnswerDraft),
    // ...
};
const answerLane = lanes.answer;
const previewToolProgressEnabled = Boolean(answerLane.stream) && resolveChannelStreamingPreviewToolProgress(telegramCfg);

When hasNativeQuoteReply === true:

  • canStreamAnswerDraft is forced to false
  • createDraftLane("answer", false) returns a lane with no stream
  • answerLane.stream is undefined
  • previewToolProgressEnabled = Boolean(undefined) && ... = false
  • pushPreviewToolProgress early-returns on every call, silently dropping all tool events

The architectural reason for the exclusion is sound (Telegram's quote-reply requires the final message reference at send time, which is incompatible with the preview-edit model). The bug is that the exclusion is silent and undocumented.

Evidence (live runtime trace)

Instrumented bot-message-dispatch.ts with console.error markers and reproduced both states on the same gateway. Verbatim journalctl output:

With replyToMode: "first" (broken):

canStreamAnswerDraft=false | previewStreamingEnabled=true hasNativeQuoteReply=true accountBlockStreamingEnabled=false forceBlockStreamingForReasoning=false
dispatcher init: previewToolProgressEnabled=false answerLaneStream=false resolvedTP=true
pushPreviewToolProgress called: line="tool: process" enabled=false suppressed=false hasStream=false   ← dropped
pushPreviewToolProgress called: line="tool: session_status" enabled=false suppressed=false hasStream=false   ← dropped
[... 333 tool events, all dropped ...]

With replyToMode: "off" (working):

canStreamAnswerDraft=true | previewStreamingEnabled=true hasNativeQuoteReply=false accountBlockStreamingEnabled=false forceBlockStreamingForReasoning=false
dispatcher init: previewToolProgressEnabled=true answerLaneStream=true resolvedTP=true
pushPreviewToolProgress called: line="exec" enabled=true suppressed=false hasStream=true   ← rendered
pushPreviewToolProgress called: line="tool: process" enabled=true suppressed=false hasStream=true   ← rendered
KILL-SWITCH FIRED: answerLane streaming text="Brave search for..." wiping 0 previewLines   ← clean transition to answer

Tool-progress preview message visible to the user (screenshot omitted from this report; reproduce locally).

Expected behavior

One or more of:

  1. (Doc) docs/channels/telegram.md notes that streaming.preview.toolProgress is silently disabled when replyToMode != "off". Docs currently imply they are independent.
  2. (Validation) openclaw doctor warns when both replyToMode != "off" and streaming.preview.toolProgress: true (default) are configured for Telegram.
  3. (Architectural) Tool-progress lines fall back to separate persistent messages (the same delivery path as /verbose on) when hasNativeQuoteReply blocks the preview path, so users get tool visibility regardless of quote-reply settings.

Suggested minimum fix

Option (1) is a one-line doc addition. Option (2) is a ~10-line doctor check. Option (3) is a real architectural change.

I'd be happy to open a PR for option (1) and (2) together if the maintainers prefer.

Related

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