Repository navigation
Description
Description
On opencode-go/qwen3.8-flash, selecting the reasoning variant xhigh makes OpenCode send a bare output_config.effort to POST /zen/go/v1/messages with no thinking block. The request succeeds (HTTP 200) and no error is shown, but reasoning is never enabled: tokens.reasoning is always 0 for these sessions.
So variant=xhigh looks active but does nothing. This is deterministic, not intermittent.
Wire symptom:
variant=xhigh
-> POST /messages
-> output_config: {"effort":"xhigh"}
-> no "thinking" field
-> HTTP 200, no thinking block
-> tokens.reasoning = 0
OpenCode version
1.18.31 (Linux). Relevant UA: opencode/1.18.31 ai-sdk/provider-utils/4.0.46 runtime/bun/1.3.14. Bundled @ai-sdk/anthropic is 3.0.111.
Steps to reproduce
opencode run --model opencode-go/qwen3.8-flash --variant xhigh "Reply with exactly: OK"
Check the session usage:
DB="$HOME/.local/share/opencode/opencode.db"
sqlite3 "$DB" "
SELECT json_extract(model,'\$.variant'), tokens_reasoning, tokens_output
FROM session
WHERE model LIKE '%qwen3.8-flash%' AND model LIKE '%xhigh%'
ORDER BY time_created DESC LIMIT 5;"
Result: tokens_reasoning = 0 on every row.
To see the body OpenCode actually sends, point the provider at a local recording endpoint (provider.opencode-go.options.baseURL) and run the same command. Captured body for the xhigh request (message/system content redacted):
{
"model": "qwen3.8-flash",
"stream": true,
"max_tokens": 32000,
"output_config": { "effort": "xhigh" },
"tool_choice": { "type": "auto" },
"tools": ["<14 tools>"]
}There is no thinking key. (For comparison, the auxiliary/title request is sent the same way with effort: "low".)
Expected behavior
variant=xhigh should enable the model's reasoning mode and produce reasoning tokens. If the requested mode cannot be honoured, OpenCode should warn instead of silently sending a no-op parameter.
Root cause (source)
packages/opencode/src/provider/transform.ts:
reasoningVariants() -> model has { type:"effort", values:["low","medium","xhigh"] }
-> effortVariants() -> reasoningEffort(model, "xhigh")
case "@ai-sdk/anthropic":
return anthropicEffort(model, effort) ?? { effort } // fallback taken
anthropicEffort(): anthropicAdaptiveEfforts("qwen3.8-flash") -> null // needs claude-/kimi
-> returns undefined
=> { effort: "xhigh" }
@ai-sdk/anthropic 3.0.111 then faithfully serialises effort into output_config.effort; since no thinking was provided, none is sent. The catalog defines qwen3.8-flash with a model-level provider.npm: "@ai-sdk/anthropic" (provider default is @ai-sdk/openai-compatible).
Evidence
Local opencode.db, qwen3.8-flash on opencode-go:
| variant | sessions | reasoning tokens |
|---|---|---|
| xhigh | 42 | 0 |
| default | 16 | 0 |
| high | 3 | 0 |
| max | 2 | 0 |
42/42 xhigh sessions (100%) have reasoning = 0; message-level cross-check: 1,656 messages, 0 with reasoning.
Controls on the same provider:
| model | reasoning tokens |
|---|---|
qwen3.7-plus |
29,577 |
deepseek-v4.1-flash |
242,466 |
qwen3.8-flash |
0 |
So the provider/adapter path does produce reasoning for other models; only the qwen3.8-flash effort-variant path yields zero.
Related (separate) compatibility note
On the same endpoint for this model, thinking: {"type":"adaptive"} returns HTTP 200 with a thinking block, while thinking: {"type":"enabled","budget_tokens":N} is rejected (HTTP 500 before ~2026-09-14 23:13 UTC, later HTTP 400 {"model":"qwen3.8-flash"}). The enabled form is accepted for qwen3.7-plus and minimax-m3. This looks like a provider/model compatibility limitation, and it means replacing the bare effort with enabled + budget_tokens is not safe — adaptive is what this model accepts.
Proposed fix
Guard the Anthropic effort mapping for Qwen models so the variant produces a real thinking config, e.g. in anthropicEffort():
if (isQwenAnthropicFamily(model)) // family === "qwen" on @ai-sdk/anthropic
return { thinking: { type: "adaptive", display: "summarized" }, effort }adaptive is confirmed accepted by this endpoint. If mapping xhigh -> adaptive changes the intended semantics of xhigh, the alternative is to not expose effort variants for this model on this adapter and surface that the capability is unavailable — rather than emitting a parameter that does nothing.
Regression test
Given opencode-go/qwen3.8-flash + variant=xhigh, assert the generated body contains a thinking block and does not rely on bare output_config.effort alone; then assert the response contains a thinking block and tokens.reasoning > 0. Keep default qwen3.8-flash, qwen3.7-plus, deepseek-v4.1-flash, and non-reasoning models covered as controls.
Related issues
--variantsilently ignored when the value is not in the model's reasoning_options #40182 —--variantsilently ignored when the value is not inreasoning_options. Different cause: here the value is valid and applied, but has no effect.- [Bug] Anthropic provider sends invalid API parameters (thinking.type: adaptive, output_config.effort) when variant is set #17876 (closed, not planned) — opposite symptom on native Anthropic (adaptive + effort sent, causes 400).
Note
Separately, opencode-go/qwen3.8-flash also has intermittent Internal server error / Type validation failed failures (26 of 63 local sessions). That is a different failure domain and is not related to this reasoning-variant bug.
Activity
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊