fix(agent): also strip bare <invoke> tool-call blocks (no function_calls wrapper) - #1261
Merged
mrgoonie merged 1 commit intoJun 23, 2026
Merged
Conversation
Follow-up to nextlevelbuilder#1260. A model (notably the claude-cli proxy under a degraded session) sometimes emits a tool call as a bare <invoke name="...">...</invoke> block with no <function_calls> wrapper. fullToolCallBlockPattern only matched the wrapped form, so the bare block slipped through to the tag-only strip, leaking the inner <parameter> command text into the reply while the tool never ran. Match and remove complete bare <invoke> blocks too (after the wrapped form), add "<invoke name=" as a detection indicator, and log the dropped tool name(s). Partial/unterminated artifacts still fall through to the existing tag strip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mrgoonie
approved these changes
Jun 23, 2026
mrgoonie
left a comment
Contributor
There was a problem hiding this comment.
Summary: This is a focused follow-up to the wrapped function_calls sanitizer. It removes complete bare ... text blocks before the fallback tag stripping path, so command parameters do not leak into user-facing replies when a provider emits a tool call as text.
Risk level: Low
Mandatory gates:
- Duplicate/prior implementation: clear; search only found this PR for the bare-invoke no-wrapper case, while prior work handled the wrapped block form.
- Project standards: passed; the change stays in internal/agent sanitizer code and adds targeted regression coverage.
- Strategic necessity: clear value; this closes a real leakage/no-op failure mode in degraded tool-call output handling.
- CI/checks: green.
Findings:
- Critical: none.
- Important: none.
- Suggestion: none.
Verdict: APPROVE
Reviewed evidence: diff limited to internal/agent/sanitize.go and internal/agent/sanitize_toolcall_xml_test.go; CI release-versioning, go, and web checks are successful; added tests cover bare invoke removal and command-argument non-leakage.
Posted by /github-maintain at 2026-06-23T00:00:00Z
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Follow-up to #1260. That PR removes a complete
<function_calls>...</function_calls>block a model emitted as text. But in production the claude-cli proxy (under a degraded/bloated session) emits the tool call as a bare<invoke name="...">...</invoke>block with no<function_calls>wrapper:fullToolCallBlockPattern(wrapper-only) misses this, so it falls through to the tag-only strip — which deletes the tags but leaks the inner<parameter>command text into the reply, while the tool still never runs (silent no-op).Fix
bareInvokeBlockPatternand remove complete bare<invoke>...</invoke>blocks too, after the wrapped form (so wrapper-nested invokes aren't double-handled).<invoke name=togarbledToolXMLIndicatorsso even a bare invoke triggers the cleanup gate.dropped text-encoded tool callWARN with the attempted tool name(s).Unterminated/partial artifacts still fall through to the existing tag-level strip (DeepSeek/GLM/Minimax behavior unchanged). No effect on providers that emit proper structured tool calls.
Test
internal/agent/sanitize_toolcall_xml_test.goextended:<invoke>block removed, surrounding prose keptSanitizeAssistantContentdoes not leak the bare-invoke command argument (regression)No migration / schema / i18n change.