Tool-call markup occasionally emitted as plain text instead of executed (commands silently not run)
Summary
In longer agentic sessions, the assistant intermittently emits tool-call markup as plain text instead of producing an executable tool call. When this happens the command is silently not run — the malformed markup is rendered as literal text in the transcript, and the conversation continues as if a step happened when nothing executed.
Environment
- Claude Code CLI (terminal)
- OS: macOS (Darwin 25.5.0)
- Model: claude-opus-4-8
- Context: long session with prose and tool calls interleaved
Actual output (rendered as text, NOT executed)
count
<invoke name="Bash">
<parameter name="command">....
Expected output (parseable / executed form)
A tool call must use the namespaced wrapper: each invoke/parameter carries the antml: namespace prefix and is enclosed in an antml:function_calls block.
Difference from a correct call (any one of these breaks execution)
- Missing the
antml:namespace prefix oninvoke/parameter. - Missing the enclosing
function_callswrapper block. - A stray leading token (e.g.
count) — the opening tag appears to be generated corrupted.
Frequency / trigger
- Non-deterministic, intermittent.
- Empirically correlated with the boundary where a longer prose paragraph is immediately followed by a tool call in the same message; rarely happens for bare calls or short preambles.
- Can recur several times in one long session, alternating with correctly-formatted (and executed) calls.
Impact
- The step does not run; the user believes work is progressing when nothing happened.
- If the user does not notice the garbage text, they may trust an un-executed task as done.
- Recovery requires the assistant to notice and re-send the call — wasted round-trips and broken trust in "executed vs not executed".
Observed workaround
- Re-sending the same call with the full namespaced form executes normally — indicating the issue is in the serialization of the tool-call block, not the command, permissions, or sandbox.
Note (hypothesis, not confirmed)
The observable operative cause is the format deviation above. Why the namespace/wrapper is dropped at certain token boundaries, and why a stray token like count appears, can't be confirmed from the client side and likely needs server-side generation/parse logs. Suggested area to investigate: structured-output integrity at the prose to tool-call transition.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗