Repository navigation
[BUG] Model options (reasoning/thinking) not forwarded to API for @ai-sdk/openai-compatible providers in headless mode #27361
Description
Description
When using a custom @ai-sdk/openai-compatible provider with model-specific options (e.g. reasoning.effort for OpenRouter), the options are silently ignored and never sent to the API. This affects all headless usage (opencode run --format json) and makes it impossible to enable extended thinking/reasoning for any custom provider model.
Environment
- OpenCode version:
1.14.48 - OS: Ubuntu 24.04 LTS
- Mode: headless (
opencode run --format json) - Provider: OpenRouter via
@ai-sdk/openai-compatible - Model:
qwen/qwen3.6-plus
Steps to Reproduce
1. Create config with reasoning options:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openrouter": {
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "https://openrouter.ai/api/v1",
"name": "Openrouter"
},
"models": {
"qwen/qwen3.6-plus": {
"options": {
"reasoning": { "effort": "high" }
}
}
}
}
}
}2. Run in headless mode:
OPENCODE_CONFIG=/tmp/test_thinking.json \
OPENROUTER_API_KEY=sk-or-v1-... \
opencode run \
--model openrouter/qwen/qwen3.6-plus \
--format json \
--dangerously-skip-permissions \
"explain recursion briefly"3. Observe output:
{"type":"step_start",...}
{"type":"text","part":{"text":"Recursion is..."}}Model responds instantly with no reasoning — reasoning.effort: high was not sent to the API.
Expected Behavior
OpenCode should forward model-level options to the API call, resulting in the model performing extended thinking before responding. OpenRouter confirms qwen/qwen3.6-plus supports reasoning parameter:
curl https://openrouter.ai/api/v1/models | jq '.data[] | select(.id=="qwen/qwen3.6-plus") | .supported_parameters'
# ["include_reasoning", "max_tokens", "presence_penalty", "reasoning", ...]When called directly with reasoning parameter, the model thinks before responding (verified via direct API call).
Actual Behavior
Model options are silently ignored. The reasoning parameter is never sent to OpenRouter. Model responds without any thinking regardless of config.
Additional Investigation
We also tested:
Attempt 1 — options at provider level via defaultQuery:
"options": {
"baseURL": "...",
"name": "Openrouter",
"defaultQuery": { "reasoning": {"effort": "high"} }
}→ Same result. Options ignored.
Attempt 2 — using built-in OpenRouter provider (no npm field):
{
"provider": {
"openrouter": {
"models": {
"qwen/qwen3.6-plus": {
"options": { "reasoning": {"effort": "high"} }
}
}
}
}
}→ Same result. Options ignored.
Root Cause (suspected)
Related to issue #971 — model options are not forwarded for openai-compatible providers. The options object appears to be parsed from config but never merged into the actual AI SDK provider call parameters.
The name field in provider options IS applied correctly (baseURL routing works), suggesting provider-level options are forwarded but model-level options are dropped somewhere between config parsing and the API call.
Use Case / Impact
This blocks implementing dynamic thinking/reasoning toggle for any custom or OpenRouter-hosted model in headless/programmatic OpenCode usage. Specifically, it prevents building OpenWebUI pipe integrations that toggle reasoning per-request via OPENCODE_CONFIG environment variable.
Workaround
None found. The only alternative is to use models with thinking built-in at the model level (e.g. qwen/qwen3-235b-a22b-thinking), but this removes the ability to toggle thinking on/off dynamically.
References
- Related issue: Model options are not forwarded for openai-compatible providers unless provider.name option is given #971 (Model options are not forwarded for openai-compatible providers unless provider.name option is given)
- OpenRouter reasoning docs: https://openrouter.ai/docs/use-cases/reasoning-tokens
Plugins
No response
OpenCode version
1.14.48
Steps to reproduce
No response
Screenshot and/or share link
No response
Operating System
No response
Terminal
No response
Activity
github-actions commentedon May 13, 2026
This issue might be a duplicate of existing issues. Please check:
optionsin the config are silently dropped and never forwarded to the API for@ai-sdk/openai-compatibleproviders.provider.nameoption is given — the root cause issue referenced in your report (now closed, but the problem appears to persist).If your issue is distinct (e.g., specific to model-level
optionslikereasoning.effortvs. provider-leveloptionslikebaseURL), please clarify the difference so it can be tracked separately.R8CEH commentedon May 13, 2026
Yes, this is distinct from #5674 and #971. To clarify:
Provider-level options (baseURL, name) — work correctly. Requests are routed to the right endpoint.
Model-level options (reasoning.effort, thinking) — silently dropped. Never appear in the actual API call.
Tested with three different configs (model options, provider defaultQuery, built-in openrouter provider without npm) — all produce identical results with no reasoning parameter sent to the API.
The distinction matters because provider-level fix (#971) did not resolve model-level forwarding.
cgaravitoq commentedon May 19, 2026
Hitting the same root cause from a slightly different angle — direct OpenAI provider (
@ai-sdk/openai), via the JS SDK (@opencode-ai/sdk1.15.5,createOpencode()).Two extra symptoms worth capturing:
Default injection, not just drop: For GPT-5 models with
reasoning: true, opencode 1.15.5 doesn't merely drop the user-suppliedoptions.reasoning.effort— it injects"max"from an internal default. The OpenAI Responses API rejects this:{ "error": { "message": "Invalid value: 'max'. Supported values are: 'none', 'minimal', 'low', 'medium', 'high', and 'xhigh'.", "param": "reasoning.effort", "code": "invalid_value" } }Result: 100% of GPT-5 reasoning model calls fail with HTTP 400.
Confirms the parse/forward split noted in this issue's root-cause analysis: changing
provider.openai.models["gpt-5.5"].nameviaConfigis reflected inclient.config.providers(), whileprovider.openai.models["gpt-5.5"].options.reasoning.effort = "xhigh"is silently discarded.Tried at provider level, model level, and with
reasoning: false— all ignored.dzuff-sfdc commentedon Jun 8, 2026
May also affect
@ai-sdk/amazon-bedrockprovidersI believe I'm hitting the same issue with a custom provider using
npm: "@ai-sdk/amazon-bedrock". Specifically triedus.anthropic.claude-opus-4-8withreasoningConfig, but model-leveloptionsappear to be dropped —additionalModelRequestFieldslooks absent in the outbound Converse request based on my testing.Haven't fully ruled out other causes, but the gateway and model seem fine when called directly, which suggests the drop may be happening in opencode's option-forwarding layer.
psemeniuk commentedon Jun 18, 2026
Hi,
probably related - i have the same issues with new bedrock mantle (openai-compatible) endpoint for closed GPT models.
Payload intercepted by mitmproxy:
{ "model": "openai.gpt-5.4", "input": [ { "role": "system", "content": "You are OpenCode,...IRRELEVANT" }, { "role": "user", "content": [ { "type": "input_text", "text": "hi" } ] } ], "max_output_tokens": 32000, "text": { "verbosity": "low" }, "store": false, "include": [ "reasoning.encrypted_content" ], "tools": [ ...IRRELEVANT ], "tool_choice": "auto", "stream": true }Effectively GPT 5.4 works with NO reasoning, GPT 5.5 medium effort (because of their at-provider-level defaults). Tried set via toggling effort and via opencode.json with
on model settings.
opencode-agent commentedon Aug 9, 2026
Thanks everyone for the reports. There are a few different cases collected in this issue, and they are covered by the current
devbranch:@ai-sdk/openai-compatibleprovider, do not retain the oldoptions.nameworkaround with different casing. In the original config,name: "Openrouter"makes the SDK readproviderOptions.Openrouterwhile OpenCode writesproviderOptions.openrouter, so the nestedreasoningoption is skipped. Removeoptions.name(allowing OpenCode to use the provider IDopenrouter) or keep its casing identical to the provider ID.@ai-sdk/openaiand Bedrock Mantle comments describe a separate OpenAI reasoning gate. That was fixed in fix(provider): force openai reasoning variants #34702 by forcing the reasoning request path when reasoning options or capabilities are present; the fix first shipped in v1.17.13.maxdefault and reasoning variant behavior have also since been corrected ondev.devroutes Amazon BedrockreasoningConfigunder thebedrockSDK namespace and has coverage for that mapping.Please upgrade to the latest release and use the provider-specific option shape (
reasoningfor the OpenRouter SDK,reasoningEffortfor OpenAI-family SDKs). Closing this as fixed.adamkes commentedon Aug 15, 2026
Still reproducible on the latest release (1.18.18), headless and interactive. Verified against
@ai-sdk/openai-compatiblewith an Ollama 0.32.9 backend. Captured request bodies via a stub atbaseURL:1. Model-level
options— silently dropped:2.
variants— forwarded, but nested underoptions, which OpenAI-compatible backends ignore:Ollama's
/v1handler unmarshals into a struct with nooptionsfield, so this is silently discarded: the model still thinks (60 reasoning tokens, empty content withmax_tokens:60). The same server honors a top-levelreasoning_effort:"none"(17 tokens, instant answer).3. v2 config keys
settings/body— not honored by 1.18.18 at all (nothing appears in the request body).Net result: there is no config-only way to inject a top-level provider field like
reasoning_effortfor@ai-sdk/openai-compatiblemodels, so users of Ollama thinking models (qwen3.5, gemma4, DeepSeek-R1 style) cannot disable reasoning without running a local proxy.Expected: model
optionsforwarded into the request,variants/optionsmerged at the top level, or the documented v2settings/bodykeys working in the openai-compatible adapter — any of these would fix it.Related: #41294, #5674, #971.