openclaw - ✅(Solved) Fix [Bug]: Tool call XML leaking into Discord messages [3 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#57868Fetched 2026-04-08 01:56:38
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Timeline (top)
cross-referenced ×3commented ×1labeled ×1referenced ×1

Version: OpenClaw 2026.3.28 (f9b1079) Channel: Discord Config: streaming: off, streamMode: block

Issue: When the agent uses internal tools (read, exec, apply_patch, etc.), the raw XML tool_call tags are included in the Discord message sent to the user. Example: The user sees: "Here's my response <tool_call>{"name": "exec", "arguments": {"command": "echo test"}}</tool_call>"

ool calls should be stripped from the message before rendering to Discord. Only the human-readable text should be displayed.

Reproduction: Any agent response that includes a tool call alongside text will leak the raw XML to Discord.

Root Cause

Version: OpenClaw 2026.3.28 (f9b1079) Channel: Discord Config: streaming: off, streamMode: block

Issue: When the agent uses internal tools (read, exec, apply_patch, etc.), the raw XML tool_call tags are included in the Discord message sent to the user. Example: The user sees: "Here's my response <tool_call>{"name": "exec", "arguments": {"command": "echo test"}}</tool_call>"

ool calls should be stripped from the message before rendering to Discord. Only the human-readable text should be displayed.

Reproduction: Any agent response that includes a tool call alongside text will leak the raw XML to Discord.

Fix Action

Fix / Workaround

Issue: When the agent uses internal tools (read, exec, apply_patch, etc.), the raw XML tool_call tags are included in the Discord message sent to the user. Example: The user sees: "Here's my response <tool_call>{"name": "exec", "arguments": {"command": "echo test"}}</tool_call>"

PR fix notes

PR #57878: fix(sanitize): strip tool_call XML tags from user-facing messages

Description (problem / solution / changelog)

Summary

  • Add regex-based stripping of <tool_call>...</tool_call> and <tool_result>...</tool_result> XML tags in sanitizeUserFacingText()
  • When streaming is disabled (streamMode: block), raw tool call XML leaks into channel messages (Discord, Telegram, etc.), exposing internal tool invocations to end users
  • The fix is in the shared sanitizeUserFacingText() function used by normalizeReplyPayload(), so all channel delivery paths benefit
  • Includes 4 new test cases covering single tags, multiple tags, multiline tags, and tool_result tags

Fixes #57868

Test plan

  • Run pnpm test src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts — 4 new test cases should pass
  • Send a message that triggers tool use with streaming: off / streamMode: block on Discord
  • Verify the response text no longer contains <tool_call> XML tags
  • Verify normal message text (without tool calls) is unaffected

🤖 Generated with Claude Code

Changed files

  • src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts (modified, +22/-0)
  • src/agents/pi-embedded-helpers/errors.ts (modified, +14/-1)

PR #57886: fix(replies): strip leaked tool_call XML

Description (problem / solution / changelog)

Summary

  • Problem: final user-facing replies could leak raw <tool_call>...</tool_call> XML.
  • Why it matters: Discord users saw internal tool scaffolding instead of clean reply text.
  • What changed: strip leaked <tool_call> scaffolding in the shared assistant-visible text helper and use that helper in final reply sanitization.
  • What did NOT change (scope boundary): tool execution behavior is unchanged; fenced code examples with literal <tool_call> text are preserved.

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 #57868
  • Related #
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

  • Root cause: final text sanitization stripped some internal tags (<final>, reasoning/memory scaffolding) but not raw <tool_call>...</tool_call> blocks.
  • Missing detection / guardrail: no focused regression covered leaked tool_call XML in final reply normalization.
  • Prior context (git blame, prior PR, issue, or refactor if known): adjacent internal-scaffolding stripping already existed; this XML shape was missing.
  • Why this regressed now: unknown.
  • If unknown, what was ruled out: no active upstream PR overlaps this exact issue.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file:
    • src/shared/text/assistant-visible-text.test.ts
    • src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts
    • src/auto-reply/reply/reply-utils.test.ts
  • Scenario the test should lock in: leaked <tool_call>...</tool_call> blocks are removed from final user-facing replies, but fenced code literals remain visible.
  • Why this is the smallest reliable guardrail: the bug lives in shared text sanitization and final reply normalization.
  • Existing test that already covers this (if any): adjacent tests already covered other internal scaffolding.
  • If no new test is added, why not: N/A.

User-visible / Behavior Changes

User-facing replies no longer include leaked raw <tool_call>...</tool_call> scaffolding.

Diagram (if applicable)

N/A.

Security Impact (required)

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

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local Node/pnpm checkout
  • Model/provider: N/A
  • Integration/channel (if any): Discord final reply delivery path
  • Relevant config (redacted): N/A

Steps

  1. Produce a reply containing leaked <tool_call>...</tool_call> XML.
  2. Run final reply normalization.
  3. Inspect the user-facing text payload.

Expected

  • Human-readable reply remains.
  • Raw <tool_call> block is removed.
  • Fenced code containing literal <tool_call> text remains intact.

Actual

  • Matches expected with this patch.

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:
    • pnpm test -- src/shared/text/assistant-visible-text.test.ts
    • pnpm test -- src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts
    • pnpm test -- src/auto-reply/reply/reply-utils.test.ts
    • pnpm exec oxfmt --check src/shared/text/assistant-visible-text.ts src/shared/text/assistant-visible-text.test.ts src/agents/pi-embedded-helpers/errors.ts src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts src/auto-reply/reply/reply-utils.test.ts
  • Edge cases checked: fenced code literals are preserved.
  • What you did not verify: full pnpm check. Current origin/main already has unrelated TypeScript failures in the skills area.

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)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: over-stripping literal <tool_call> prose outside code blocks.
    • Mitigation: keep the stripping scoped to assistant-internal scaffolding and preserve fenced-code literals with regression coverage.

Changed files

  • src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts (modified, +26/-0)
  • src/agents/pi-embedded-helpers/errors.ts (modified, +7/-1)
  • src/auto-reply/reply/reply-utils.test.ts (modified, +16/-0)
  • src/shared/text/assistant-visible-text.test.ts (modified, +29/-0)
  • src/shared/text/assistant-visible-text.ts (modified, +51/-3)

PR #58043: fix(discord): strip tool_call XML blocks from text before sending

Description (problem / solution / changelog)

Summary

Fixes issue where raw <tool_call>...</tool_call> XML tags from MCP providers were being included in Discord messages sent to users.

Root Cause

When MCP providers or certain models output tool calls, they may include raw XML-formatted tool call blocks in the text content. This was not being filtered out before sending messages to Discord.

Fix

Added regex to strip <tool_call>...</tool_call> XML blocks from assistant text in the stripDowngradedToolCallText function, which is used when processing messages for delivery to channels like Discord.

Testing

  • All existing tests pass (34 tests)
  • The fix follows the existing pattern for stripping [Tool Call: ...] and [Tool Result for ID ...] blocks

Impact

  • Users will no longer see raw <tool_call> XML in Discord messages
  • Fixes the broken user experience when agents use tools in Discord

Fixes #57868

Changed files

  • extensions/telegram/src/bot-access.ts (modified, +3/-2)
  • src/infra/matrix-legacy-crypto.ts (modified, +3/-15)
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

Version: OpenClaw 2026.3.28 (f9b1079) Channel: Discord Config: streaming: off, streamMode: block

Issue: When the agent uses internal tools (read, exec, apply_patch, etc.), the raw XML tool_call tags are included in the Discord message sent to the user. Example: The user sees: "Here's my response <tool_call>{"name": "exec", "arguments": {"command": "echo test"}}</tool_call>"

ool calls should be stripped from the message before rendering to Discord. Only the human-readable text should be displayed.

Reproduction: Any agent response that includes a tool call alongside text will leak the raw XML to Discord.

Steps to reproduce

Anytime tool is used in Discord

Expected behavior

Tool calls should be stripped from the message before rendering to Discord. Only the human-readable text should be displayed.

Actual behavior

Any agent response that includes a tool call alongside text will leak the raw XML to Discord.

OpenClaw version

OpenClaw 2026.3.28 (f9b1079)

Operating system

MacOS

Install method

No response

Model

Anthropic Claude 4.6

Provider / routing chain

Anthropic API (direct) → OpenClaw Gateway (local loopback 127.0.0.1:18789) → Discord channel plugin Model: claude-opus-4-6

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

extent analysis

Fix Plan

To fix the issue of raw XML tool_call tags being included in Discord messages, we need to modify the code that renders the agent's response to Discord.

  • Update the Discord channel plugin to parse the agent's response and remove any XML tool_call tags before sending the message to Discord.
  • Use an XML parsing library to identify and strip the tool_call tags.

Example code snippet in Python:

import xml.etree.ElementTree as ET
import re

def strip_tool_calls(response):
    # Parse the response as XML
    root = ET.fromstring(response)
    
    # Find and remove all tool_call tags
    for tool_call in root.findall('.//tool_call'):
        tool_call.tag = 'removed'
        tool_call.attrib = {}
        tool_call.text = ''
    
    # Remove any remaining XML tags from the response
    response = ET.tostring(root, encoding='unicode')
    response = re.sub(r'<.*?>', '', response)
    
    return response

# Example usage:
response = "Here's my response <tool_call>{\"name\": \"exec\", \"arguments\": {\"command\": \"echo test\"}}</tool_call>"
cleaned_response = strip_tool_calls(response)
print(cleaned_response)  # Output: "Here's my response "

Note that this is a simplified example and may need to be adapted to your specific use case.

Verification

To verify that the fix worked, test the agent's response with a tool call and check that the raw XML is no longer included in the Discord message.

Extra Tips

  • Make sure to handle any potential errors that may occur during XML parsing.
  • Consider adding logging to track any issues that may arise during the stripping process.
  • If you're using a different programming language, you'll need to use an equivalent XML parsing library.

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

Tool calls should be stripped from the message before rendering to Discord. Only the human-readable text should be displayed.

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 [Bug]: Tool call XML leaking into Discord messages [3 pull requests, 1 comments, 2 participants]