🛠️ Qwen Tool-Calling Template Fix

A focused chat-template fix for more reliable Qwen tool-call history rendering.

Start here: use chat_template.jinja as your chat-template override. If your runtime only accepts an inline value, use chat_template_oneline.txt instead.

✨ What's included

File Purpose
chat_template.jinja Readable Jinja template for direct use and inspection.
chat_template_oneline.txt Inline, single-line form for runtimes that require it.

🚀 Usage

Use either file as your runtime's chat-template override. For vLLM, pair it with a Qwen-compatible tool parser such as qwen3_xml.

This repository targets template-level tool-history rendering. It is not a universal claim that every repeated tool call is caused by the template or the model.

🔬 What the investigation found

The visible symptom—an agent calling the same tool again and again—does not identify the cause by itself. The failure can occur in the template, at the API boundary, in a runtime parser, in the model's tool grammar, or in the agent's control flow.

✅ This template helps with ⚠️ This template alone cannot guarantee
Preserving tool-call history when arguments is a mapping, JSON string, or array-like value. That a model will never choose a repeated action.
Avoiding history corruption during compatible template rendering. That every parser or agent harness handles the model output correctly.
Retaining the native Qwen-style tool grammar where appropriate. That a terminal tool stops the agent if the harness keeps sending new turns.

🧩 Example 1 — a JSON-string argument mismatch

An OpenAI-compatible client may preserve a previous tool call as:

{
  "name": "read_file",
  "arguments": "{\"path\": \"README.md\"}"
}

But a mapping-only template may use logic equivalent to:

tool_call.arguments | items

That expression expects an object, whereas the client supplied a string. If the history is rendered incorrectly, the model may no longer see a faithful record of the completed call—and may attempt it again.

Normalize incompatible JSON-string histories at the runtime boundary when possible, then preserve the model's native tool grammar when rendering the conversation.

🛑 Example 2 — terminal tools need the harness to stop

For a terminal tool such as submit_implementation, the intended flow is:

model → submit_implementation → success → stop

If the harness instead appends the successful result to the conversation and invokes the model again, another submit_implementation call can follow. That resembles a model loop, but it is an agent-control-flow problem.

A chat template cannot make a terminal action terminal. The harness must end the run immediately after a successful terminal tool.

🧠 Practical checklist

  • 🔄 Normalize incompatible JSON-string histories at the runtime boundary when needed.
  • 🧬 Preserve the tool-call grammar the model learned during training.
  • 🧪 Test Hugging Face Jinja and llama.cpp/minja independently when supporting both.
  • 📋 Keep the exact rendered conversation in debug logs.
  • 🧯 Add a maximum tool-turn limit and detect unchanged repeated tool signatures.

📚 Background research

The accompanying write-up documents the targeted regression and behavior investigations behind this template. It is not a general benchmark or a replacement claim for every stock Qwen template.

👉 Why Some Qwen Tool-Calling Loops Are Not Model Loops

📄 License

Apache-2.0

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support