Qwen 3.5 Tool Calling Fixes for Agentic Use: Server Status and Client-Side Workarounds

Tool Calling Bugs in Qwen 3.5 Agentic Setups
When running Qwen 3.5 models in agentic environments like coding agents or function calling loops, four specific bugs can cause tool calling to fail completely.
The Four Core Bugs
- XML tool calls leak as plain text: Qwen 3.5 emits tool calls as XML format (e.g., <function=bash><parameter=command>ls</parameter></function>). When servers fail to parse this—especially when text precedes the XML or thinking is enabled—the tool call arrives as raw text with finish_reason: stop, so your agent never executes it.
- <think> tags leak into text and poison context: llama.cpp forces thinking=1 internally regardless of enable_thinking: false, causing tags to accumulate across turns and destroy multi-turn sessions.
- Wrong finish_reason: Servers send "stop" when tool calls are present, causing agents to treat it as a final answer.
- Non-standard finish_reason: Some servers return "eos_token", "", or null, causing most frameworks to crash on the unknown value before checking if tool calls exist.
Server Status (April 2026)
The source provides a detailed status table for major inference servers:
- LM Studio 0.4.9: Best local option for XML parsing (fixed in v0.4.7), improved think leak handling, usually correct finish_reason.
- vLLM 0.19.0: Works with --tool-call-parser qwen3_coder flag, streaming bugs exist, think leak fixed, usually correct finish_reason.
- Ollama 0.20.2: Improved since fix for unclosed </think> bug, still flaky on XML parsing, sometimes wrong finish_reason.
- llama.cpp b8664: Parser exists but fails with thinking enabled, think leak broken, wrong finish_reason when parser fails.
Recommended Solutions
Use Unsloth GGUFs instead of stock Qwen 3.5 Jinja templates, which have known issues with |items filter failing on tool arguments. Unsloth ships with 21 template fixes.
Add a client-side safety net with three small functions that catch what servers miss. The source provides the first function:
import re, json, uuid
1. Parse Qwen XML tool calls from text content
def parse_qwen_xml_tools(text):
results = []
for m in re.finditer(r'<function=([\w.-]+)>([\s\S]?)</function>', text):
args = {}
for p in re.finditer(r'<parameter=([\w.-]+)>([\s\S]?)</parameter>', m.group(2)):
k, v = p.group(1).strip(), p.group(2).strip()
try:
v = json.loads(v)
except:
pass
args[k] = v
This function extracts tool calls from text content when servers fail to parse the XML properly, providing a fallback mechanism for agentic workflows.
📖 Read the full source: r/LocalLLaMA
👀 See Also

Fix OpenClaw Slowdown in Long Sessions: contextInjection continuation-skip for llama.cpp Cache
A real-world fix for OpenClaw sessions that get slower over time: set contextInjection to continuation-skip to preserve llama.cpp prompt cache, cutting prompt eval from 130s to 1.3s.

Fixing Claude Cowork 'Failed to start workspace' errors on Windows 11 Home
A user solved Claude Cowork startup errors on Windows 11 Home by installing Windows Subsystem for Linux (WSL2) from the Microsoft Store, which is required for the underlying VM technology.

Running Qwen3.6 27B and 35B on 6GB VRAM with ik_llama: Practical Configs and Benchmarks
A user shares detailed ik_llama configs and performance numbers for running Qwen3.6 27B and 35B A3B models on an RTX2060 mobile (6GB VRAM, 32GB RAM), with prefill speeds of 40-100 t/s and generation up to 11 t/s.

Running OmniCoder-9B locally with llama.cpp configuration details
A developer achieved 96.7% average HumanEval score with OmniCoder-9B on mid-range hardware using specific llama.cpp flags including --reasoning-budget 0 to disable chain-of-thought output. The setup used a Q6_K quantized model running on an RTX 3080 with 10GB VRAM.