Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
Summary
When using openrouter/qwen/qwen3-235b-a22b (or any Qwen3 model via OpenRouter),
every response fails with:
incomplete turn detected: runId=... stopReason=stop payloads=0 — surfacing error to user
The agent shows "⚠️ Agent couldn't generate a response. Please try again."
Root Cause (community-diagnosed in Discord)
src/agents/openai-transport-stream.ts handles these reasoning fields on streamed choice.delta:
reasoning_content
reasoning
reasoning_text
But not reasoning_details — which Qwen3 returns via OpenRouter.
The OpenRouter hook path (createOpenRouterWrapper) is request-side wrapping only — no response normalisation. So reasoning_details passes through unhandled, leaving OpenClaw with no assistant payload blocks, which hits the payloads=0 incomplete-turn path in src/agents/pi-embedded-runner/run.ts.
What was tried (none worked)
thinkingDefault: "off" — only stops injecting reasoning effort, does not send OpenRouter exclude: true
tools.allow: [] — no tools
providerOptions.openrouter.extra_body.enable_thinking: false
providerOptions.openrouter.extra_body.thinking: { type: "disabled" }
- Model variants:
qwen3-235b-a22b, qwen3-235b-a22b-2507, qwen3-32b
Direct OpenRouter API call with the same model works correctly — returns content + reasoning_details.
Verification
Raw OpenRouter response includes:
"reasoning_details": [
{
"type": "reasoning.text",
"text": "...",
"format": "unknown",
"index": 0
}
]
This field is not handled in the stream parser, causing zero content blocks to be assembled.
Expected Fix
Handle choice.delta.reasoning_details in openai-transport-stream.ts the same way reasoning_content is handled — extract text content and treat as reasoning tokens, not as a blocking field.
Alternatively, on the OpenRouter response path, strip or ignore unknown reasoning fields so payloads=0 is not triggered when the model returns only reasoning with no text delta.
Workaround
None available in 2026.4.14 without a litellm proxy to strip reasoning_details before OpenClaw parses the stream.
### Steps to reproduce
## Steps to Reproduce
1. Create an agent with `model: "openrouter/qwen/qwen3-235b-a22b"`
2. Send any message to the agent
3. Observe `incomplete turn detected: payloads=0` in gateway logs
4. User receives "⚠️ Agent couldn't generate a response"
### Expected behavior
When a model returns `reasoning_details` in the stream, OpenClaw should treat it the same as other recognised reasoning fields (`reasoning_content`, `reasoning`, `reasoning_text`) — extract the text content and continue assembling the response. The assistant turn should complete successfully with the model's reply visible to the user.
### Actual behavior
When a Qwen3 model responds via OpenRouter, the stream includes a `reasoning_details` field that OpenClaw does not recognise. Because no content blocks are assembled from the unhandled field, the turn completes with `payloads=0`. The agent fails silently and the user sees "⚠️ Agent couldn't generate a response. Please try again."
### OpenClaw version
OpenClaw: 2026.4.14 (323493f)
### Operating system
OS: macOS arm64 (Darwin 25.3.0)
### Install method
npm (stable)
### Model
Model: openrouter/qwen/qwen3-235b-a22b
### Provider / routing chain
Provider: OpenRouter
### Additional provider/model setup details
_No response_
### Logs, screenshots, and evidence
```shell
Impact and severity
No response
Additional information
No response
Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
Summary
When using
openrouter/qwen/qwen3-235b-a22b(or any Qwen3 model via OpenRouter),every response fails with:
incomplete turn detected: runId=... stopReason=stop payloads=0 — surfacing error to user
The agent shows "⚠️ Agent couldn't generate a response. Please try again."
Root Cause (community-diagnosed in Discord)
src/agents/openai-transport-stream.tshandles these reasoning fields on streamedchoice.delta:reasoning_contentreasoningreasoning_textBut not
reasoning_details— which Qwen3 returns via OpenRouter.The OpenRouter hook path (
createOpenRouterWrapper) is request-side wrapping only — no response normalisation. Soreasoning_detailspasses through unhandled, leaving OpenClaw with no assistant payload blocks, which hits thepayloads=0incomplete-turn path insrc/agents/pi-embedded-runner/run.ts.What was tried (none worked)
thinkingDefault: "off"— only stops injecting reasoning effort, does not send OpenRouterexclude: truetools.allow: []— no toolsproviderOptions.openrouter.extra_body.enable_thinking: falseproviderOptions.openrouter.extra_body.thinking: { type: "disabled" }qwen3-235b-a22b,qwen3-235b-a22b-2507,qwen3-32bDirect OpenRouter API call with the same model works correctly — returns
content+reasoning_details.Verification
Raw OpenRouter response includes:
Impact and severity
No response
Additional information
No response