Skip to content

[Bug]: Internal tool/status messages leak into Telegram chat even when streaming/tool progress is disabled #79804

Description

@jsompis

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

Internal OpenClaw tool/status messages were being delivered into a Telegram direct chat as visible user-facing messages.

The leaked messages appeared as internal tool progress/status cards such as:

  • Exec: ...
  • Write
  • chmod +x
  • stage git changes
  • create git commit
  • push git changes

These messages are implementation details and should not be sent to the user as normal Telegram chat messages.

This happened even though Telegram streaming/progress settings were configured to disable tool progress output.

Observed config included:

{
  "channels": {
    "telegram": {
      "streaming": {
        "mode": "off",
        "preview": {
          "toolProgress": false
        },
        "progress": {
          "toolProgress": false
        }
      }
    }
  }
}

The issue appears to be that Telegram sets suppressDefaultToolProgressMessages, but the shared dispatch path can still emit default tool/status cards when session verbose progress is enabled or when another progress callback path is active.

Steps to reproduce

  1. Configure Telegram channel streaming/progress to disable tool progress:

    {
      "channels": {
        "telegram": {
          "streaming": {
            "mode": "off",
            "preview": {
              "toolProgress": false
            },
            "progress": {
              "toolProgress": false
            }
          }
        }
      }
    }
  2. Use OpenClaw through a Telegram direct chat.

  3. Trigger any assistant action that runs tools, for example:

    • exec
    • file write
    • chmod
    • git add / commit / push
  4. Observe Telegram chat while the assistant is working.

  5. Internal tool/status cards may appear as visible Telegram messages, even though streaming/tool progress is disabled.

Expected behavior

When Telegram streaming is disabled and tool progress flags are false:

  • No internal tool invocation cards should be sent to Telegram.
  • Tool calls should remain internal implementation details.
  • The user should only receive the assistant’s final human-readable response, unless an explicit user-facing progress update is intentionally sent.
  • Direct Telegram chat should not receive raw internal progress/status messages.

Actual behavior

Telegram direct chat received internal OpenClaw tool/status messages.

Examples of leaked message types:

  • Exec: check git status
  • Write
  • chmod +x
  • stage git changes
  • create git commit
  • push git changes

These appeared as normal chat bubbles, making the conversation noisy and exposing internal workflow details.

The leak persisted despite:

  • channels.telegram.streaming.mode = "off"
  • streaming.preview.toolProgress = false
  • streaming.progress.toolProgress = false

OpenClaw version

2026.5.7

Operating system

macOS 26.4.1

Install method

npm global

Model

openai-codex/gpt-5.5

Provider / routing chain

openclaw->openai-codex/gpt-5.5

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

Severity: High for Telegram direct chat UX and privacy hygiene.

Impact:

  • User receives internal implementation details as normal messages.
  • Chat becomes noisy and confusing.
  • Internal workflow steps leak into the user-facing channel.
  • Users may think the assistant is spamming or malfunctioning.
  • Internal tool/status details should not be exposed unless explicitly enabled.

This is especially problematic for direct messaging channels like Telegram, where users expect only deliberate assistant replies or intentional progress updates.

Requested fix

Please ensure that Telegram’s tool-progress suppression applies consistently across all progress/status delivery paths.

Specifically:

  • If channels.telegram.streaming.mode = "off", default tool progress cards should not be delivered.
  • If streaming.preview.toolProgress = false and streaming.progress.toolProgress = false, internal tool/status cards should not be delivered.
  • suppressDefaultToolProgressMessages should be honored by shared dispatch/progress rendering paths.
  • Direct chat channels should default to hiding internal tool invocation cards unless explicitly enabled.

Possible implementation areas to inspect:

  • Telegram bot dispatch progress callback wiring
  • shared dispatch default tool-progress rendering
  • verbose/session progress handling
  • suppressDefaultToolProgressMessages propagation
  • tool display card rendering path

Additional information

Environment

  • OpenClaw version observed locally: 2026.5.7 (eeef486)
  • Channel: Telegram direct chat
  • Chat type: direct Telegram conversation
  • Runtime: main interactive agent
  • OS: macOS / Darwin arm64 26.4.1

Relevant local runtime/dist files investigated:

  • dist/dispatch-8E8vi2HV.js
  • dist/bot-Ce301bOE.js
  • tool display/progress rendering paths related to visible tool cards

Logs, screenshots, and evidence

Observed user-facing Telegram chat bubbles included internal tool/status cards such as:

  • Exec
  • Write
  • chmod +x
  • git commit
  • git push

The leaked cards were not normal assistant text and were not the final response. They were internal progress/tool invocation messages.

Prior investigation found:

  • The leaked messages were not merely streaming preview text.
  • They matched tool/status card rendering behavior.
  • Disabling preview/progress toolProgress was insufficient.
  • Telegram appeared to set a suppression flag, but another dispatch/progress path could still send the default tool progress messages.

A local mitigation patch targeted the runtime paths responsible for respecting suppression across:

  • dist/dispatch-8E8vi2HV.js
  • dist/bot-Ce301bOE.js
--- a/dist/dispatch-8E8vi2HV.js
+++ b/dist/dispatch-8E8vi2HV.js
@@ -797,7 +797,8 @@
                        systemEvent: shouldRouteToOriginating
                });
                const suppressDefaultToolProgressMessages = params.replyOptions?.suppressDefaultToolProgressMessages === true;
-               const shouldSuppressDefaultToolProgressMessages = () => suppressDefaultToolProgressMessages && !shouldEmitVerboseProgress();
+               const forceSuppressDefaultToolProgressMessages = params.replyOptions?.forceSuppressDefaultToolProgressMessages === true;
+               const shouldSuppressDefaultToolProgressMessages = () => forceSuppressDefaultToolProgressMessages || suppressDefaultToolProgressMessages && !shouldEmitVerboseProgress();
                const onToolResultFromReplyOptions = params.replyOptions?.onToolResult;
                const onPlanUpdateFromReplyOptions = params.replyOptions?.onPlanUpdate;
                const onApprovalEventFromReplyOptions = params.replyOptions?.onApprovalEvent;

--- a/dist/bot-Ce301bOE.js
+++ b/dist/bot-Ce301bOE.js
@@ -4662,7 +4662,8 @@
        };
        const answerLane = lanes.answer;
        const reasoningLane = lanes.reasoning;
-       const previewToolProgressEnabled = Boolean(answerLane.stream) && resolveChannelStreamingPreviewToolProgress(telegramCfg);
+       const configuredToolProgressEnabled = resolveChannelStreamingPreviewToolProgress(telegramCfg);
+       const previewToolProgressEnabled = Boolean(answerLane.stream) && configuredToolProgressEnabled;
        let previewToolProgressSuppressed = false;
        let previewToolProgressLines = [];
        let answerLaneHasAssistantContent = false;
@@ -5190,6 +5191,7 @@
                                                                        previewToolProgressLines = [];
                                                                }) : void 0,
                                                                suppressDefaultToolProgressMessages: !previewStreamingEnabled || Boolean(answerLane.stream),
+                                                               forceSuppressDefaultToolProgressMessages: !previewStreamingEnabled || configuredToolProgressEnabled === false,
                                                                allowProgressCallbacksWhenSourceDeliverySuppressed: Boolean(answerLane.stream),
                                                                onToolStart: async (payload) => {
                                                                        const toolName = payload.name?.trim();

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.bugSomething isn't workingbug:behaviorIncorrect behavior without a crashclawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions