openclaw - ✅(Solved) Fix [tool calls omitted] placeholder leaks into outgoing Telegram messages [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#74573Fetched 2026-04-30 06:22:52
View on GitHub
Comments
1
Participants
2
Timeline
9
Reactions
2
Author
Timeline (top)
referenced ×3cross-referenced ×2closed ×1commented ×1

The string [tool calls omitted] leaks from OpenClaw's internal message-history sanitization into outgoing channel messages (observed on the Telegram channel), instead of being stripped before delivery to the user.

Root Cause

The string [tool calls omitted] leaks from OpenClaw's internal message-history sanitization into outgoing channel messages (observed on the Telegram channel), instead of being stripped before delivery to the user.

Fix Action

Fix / Workaround

The [tool calls omitted] placeholder should only exist inside the internal message array sent back to the model (for history integrity) and should never appear in content dispatched to a user-facing channel (Telegram, Discord, etc.).

Either:

  • The channel outbound pipeline should filter/strip [tool calls omitted] blocks before dispatching to the channel adapter, or
  • Replace the visible placeholder with an invisible/empty block that still preserves the role/content shape the provider needs.

PR fix notes

PR #74578: fix(pi-embedded): strip [tool calls omitted] from user-facing text

Description (problem / solution / changelog)

The internal replay placeholder '[tool calls omitted]' was leaking into channel output (e.g. Telegram) after aborted tool calls.

Fix: strip the placeholder early in sanitizeUserFacingText so all channels are protected by default. The replay transcript path in turns.ts is unaffected — it uses the placeholder internally.

Fixes #74573.

Summary

Describe the problem and fix in 2–5 bullets:

If this PR fixes a plugin beta-release blocker, title it fix(<plugin-id>): beta blocker - <summary> and link the matching Beta blocker: <plugin-name> - <summary> issue labeled beta-blocker. Contributors cannot label PRs, so the title is the PR-side signal for maintainers and automation.

  • Problem:
  • Why it matters:
  • What changed:
  • What did NOT change (scope boundary):

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write N/A. If the cause is unclear, write Unknown.

  • Root cause:
  • Missing detection / guardrail:
  • Contributing context (if known):

Regression Test Plan (if applicable)

For bug fixes or regressions, name the smallest reliable test coverage that should catch this. Otherwise write N/A.

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file:
  • Scenario the test should lock in:
  • Why this is the smallest reliable guardrail:
  • Existing test that already covers this (if any):
  • If no new test is added, why not:

User-visible / Behavior Changes

List user-visible changes (including defaults/config).
If none, write None.

Diagram (if applicable)

For UI changes or non-trivial logic flows, include a small ASCII diagram reviewers can scan quickly. Otherwise write N/A.

Before:
[user action] -> [old state]

After:
[user action] -> [new state] -> [result]

Security Impact (required)

  • New permissions/capabilities? (Yes/No)
  • Secrets/tokens handling changed? (Yes/No)
  • New/changed network calls? (Yes/No)
  • Command/tool execution surface changed? (Yes/No)
  • Data access scope changed? (Yes/No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS:
  • Runtime/container:
  • Model/provider:
  • Integration/channel (if any):
  • Relevant config (redacted):

Steps

Expected

Actual

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
  • Edge cases checked:
  • What you did not verify:

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No)
  • Config/env changes? (Yes/No)
  • Migration needed? (Yes/No)
  • If yes, exact upgrade steps:

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk:
    • Mitigation:

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts (modified, +15/-0)
  • src/agents/pi-embedded-helpers/sanitize-user-facing-text.ts (modified, +23/-7)

PR #74785: fix(pi-embedded): strip [assistant copied inbound metadata omitted] placeholder from delivery

Description (problem / solution / changelog)

Problem

The internal replay placeholder [assistant copied inbound metadata omitted] is leaking into outbound Telegram (and other channel) messages after the 2026.4.27 update, appearing as the entire message body instead of the actual assistant reply.

Fixes #74745.

Root cause

sanitize-user-facing-text.ts already strips [tool calls omitted] from user-facing output (landed in d30b8dccfd, fixing #74573). The same sentinel pattern OMITTED_INBOUND_METADATA_TEXT = "[assistant copied inbound metadata omitted]" synthesized by normalizeAssistantReplayContent in replay-history.ts was not covered by the stripping regex.

Solution

Extend TOOL_CALLS_OMITTED_PLACEHOLDER_LINE_RE to cover both placeholder variants using an alternation group:

-const TOOL_CALLS_OMITTED_PLACEHOLDER_LINE_RE = /^[ \t]*\[tool calls omitted\][ \t]*$/i;
+const TOOL_CALLS_OMITTED_PLACEHOLDER_LINE_RE =
+  /^[ \t]*\[(?:tool calls omitted|assistant copied inbound metadata omitted)\][ \t]*$/i;

Same standalone-line logic applies: only strip when the placeholder is the entire line content, so ordinary user discussion of the placeholder text is preserved.

Tests

Added 4 test assertions mirroring the existing [tool calls omitted] coverage — standalone strip, whitespace strip, mid-text strip, and inline-mention preservation. All 90/90 tests pass.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts (modified, +19/-0)
  • src/agents/pi-embedded-helpers/sanitize-user-facing-text.ts (modified, +4/-3)

Code Example

text: "[tool calls omitted]"
RAW_BUFFERClick to expand / collapse

Description

The string [tool calls omitted] leaks from OpenClaw's internal message-history sanitization into outgoing channel messages (observed on the Telegram channel), instead of being stripped before delivery to the user.

Source

dist/pi-embedded-helpers-C0R2W0ZW.js contains two occurrences where filtered/orphaned tool-call content is replaced with the placeholder [tool calls omitted]:

text: "[tool calls omitted]"

These placeholders appear to be intended for LLM conversation-history hygiene (handling aborted or orphaned tool calls that would otherwise break provider validation), but they are being emitted to the user-facing channel output as literal text.

Expected behavior

The [tool calls omitted] placeholder should only exist inside the internal message array sent back to the model (for history integrity) and should never appear in content dispatched to a user-facing channel (Telegram, Discord, etc.).

Actual behavior

When an assistant turn includes tool calls that are later filtered (e.g., timed-out tool, aborted turn, orphaned tool-use with no tool-result), subsequent turns emit [tool calls omitted] as visible text in the Telegram message body.

Steps to reproduce

  1. Install OpenClaw on Linux (WSL2 Ubuntu 24.04 / noble)
  2. Configure the Telegram channel
  3. Trigger an assistant turn that uses a long-running MCP tool that returns after the tool-call-side has already been considered aborted (timeout / cancellation)
  4. On the next assistant response, the text [tool calls omitted] appears in the Telegram message to the user

Environment

  • OpenClaw running on Linux 6.6.87.2-microsoft-standard-WSL2 (WSL2 under Windows)
  • Node v22.22.2
  • Channel: Telegram
  • Model: Claude Opus 4 via Bedrock

Suggested fix

Either:

  • The channel outbound pipeline should filter/strip [tool calls omitted] blocks before dispatching to the channel adapter, or
  • Replace the visible placeholder with an invisible/empty block that still preserves the role/content shape the provider needs.

Impact

Low-severity UX bug — confuses end users who see the literal string in their chat. Does not affect functionality.

extent analysis

TL;DR

Filter or replace the [tool calls omitted] placeholder in the channel outbound pipeline to prevent it from being dispatched to user-facing channels.

Guidance

  • Review the channel outbound pipeline to identify where the [tool calls omitted] placeholder is being passed through without filtering or replacement.
  • Consider implementing a filter or replacement mechanism for the placeholder before dispatching messages to the channel adapter.
  • Verify that the filter or replacement mechanism preserves the internal message array's integrity for conversation history purposes.
  • Test the fix by reproducing the steps to reproduce and checking that the [tool calls omitted] placeholder no longer appears in the Telegram message body.

Example

// Example filter function to remove [tool calls omitted] placeholder
function filterPlaceholder(text) {
  return text.replace("[tool calls omitted]", "");
}

Notes

The fix should ensure that the internal message array's integrity is preserved for conversation history purposes, while preventing the [tool calls omitted] placeholder from being visible to end users.

Recommendation

Apply a workaround by filtering or replacing the [tool calls omitted] placeholder in the channel outbound pipeline, as this is a low-severity UX bug that can be addressed without requiring a full version upgrade.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The [tool calls omitted] placeholder should only exist inside the internal message array sent back to the model (for history integrity) and should never appear in content dispatched to a user-facing channel (Telegram, Discord, etc.).

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [tool calls omitted] placeholder leaks into outgoing Telegram messages [2 pull requests, 1 comments, 2 participants]