Skip to main content
Qwen in QitOS is no longer just “JSON-first by default”. For OpenAI-compatible Qwen endpoints, QitOS now prefers this order:
native tool calls -> Decision.act(...) -> tool execution
fallback: json_decision_v1 -> xml_decision_v1 -> react_text_v1
That matches the spirit of Qwen-Agent: function calling is the preferred lane when the backend exposes it cleanly.

What changed in v0.4

The qwen family preset now keeps three ideas together:
  • tool schemas are delivered through api_parameter
  • native tool calls are preferred when the endpoint returns tool_calls
  • text protocols remain available as a stable fallback chain
So the default protocol is still json_decision_v1, but for Qwen it is now the text fallback, not the ideal path itself.

When the native lane is used

QitOS will prefer the native lane when all of these are true:
  • the model resolves to the qwen family preset
  • the harness metadata says native_tool_call_preferred = true
  • the OpenAI-compatible response actually contains tool_calls
If any of those conditions fail, QitOS falls back to the normal parser chain.

Why QitOS does not copy the Qwen-Agent sentinel prompt

The official Qwen-Agent project includes a Qwen-specific function-calling prompt format for chat interfaces that do not provide a native tool channel. QitOS does not copy that prompt format directly for the OpenAI-compatible Qwen path because:
  • OpenAI-compatible serving already gives us a structured tool_calls channel
  • preserving that structure is cleaner than serializing it back into text
  • it keeps the runtime generic enough for other families that also expose native tool calls
In other words:
  • Qwen-Agent solves the more general “Qwen chat interface” problem
  • QitOS solves the “OpenAI-compatible served Qwen inside one reusable harness layer” problem
Use the flagship example with an OpenAI-compatible Qwen endpoint:
export OPENAI_API_KEY="your_api_key"
export OPENAI_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"

python examples/real/claude_code_agent.py \
  --model-family qwen \
  --model-name qwen-plus \
  --print-harness
You should expect the harness summary to show:
  • family_preset: qwen
  • tool_delivery: api_parameter
  • native_tool_call_preferred: True
  • decision_lane_preference: native_tool_calls

How to confirm it in qita

Inspect the run in qita and check:
  • family preset
  • prompt protocol
  • tool delivery
  • decision_source
  • native_tool_call_used
  • native_tool_call_fallback_reason
If the endpoint did not return native tool calls, QitOS will still run, but you should see the fallback reason and the parser lane in the trace.