Description
OpenCode v1 (opencode-ai ≤ 1.18.x, AI-SDK based) forwarded unknown model/provider options verbatim into the outgoing request body for @ai-sdk/openai-compatible providers. OpenCode v2 (the packages/llm protocol layer) builds the request body from an explicit field list and only lowers a fixed set of known options, so provider-specific body parameters can no longer be expressed from configuration.
This breaks the LiteLLM dynamic allowlist pattern: gateways routing to deployments whose LiteLLM provider mapping doesn't list reasoning_effort require the client to send allowed_openai_params: ["reasoning_effort"] in the request body, otherwise the proxy rejects the call:
litellm.UnsupportedParamsError: tencent does not support parameters: ['reasoning_effort'], for model=glm-5.3-flashx.
If you want to use these params dynamically send allowed_openai_params=['reasoning_effort'] in your request.
The same config worked under v1 (option forwarded verbatim). Under v2 the option never reaches the wire, so any model behind such a route fails with the above HTTP 400 — and there is no config-only workaround left in v2.
Source pointers (v2)
packages/llm/src/protocols/openai-chat.ts — fromRequest() builds the body from explicit fields; lowerOptions() emits only store and reasoning_effort.
packages/llm/src/protocols/utils/openai-options.ts — options are read from the typed request.providerOptions?.openai bag; only the known keys (store, reasoningEffort, reasoningSummary, include, promptCacheKey, textVerbosity) are ever consulted.
Config like:
sends reasoning_effort on the wire but silently drops allowed_openai_params.
Suggested fix
Either restore verbatim forwarding of unknown option keys for openai-compatible protocols (v1 behavior), or add an explicit opt-in escape hatch (e.g. an options.extra / body bag merged into the provider body), or a documented plugin hook that can mutate the outgoing provider body. Any of the three unblocks enterprise LiteLLM gateways that rely on proxy-only body params.
Plugins
OpenCode version
2.0.1 (@opencode/cli)
Steps to reproduce
- Point an
@ai-sdk/openai-compatible provider at a LiteLLM proxy that routes the model to a deployment whose provider mapping doesn't support reasoning_effort (e.g. tencent), with model options: { "reasoningEffort": "high", "allowed_openai_params": ["reasoning_effort"] }.
- Send any prompt with that model → v2 fails with
litellm.UnsupportedParamsError: tencent does not support parameters: ['reasoning_effort'] (HTTP 400).
- The identical config under v1 sends both keys (
reasoning_effort and allowed_openai_params, verified by capturing the outgoing request body against a local echo server) and the gateway returns HTTP 200.
- Direct curl against the same gateway with both keys in the body also returns 200 — the proxy honors the dynamic allowlist when the client actually sends it, so the failure is purely the dropped option.
Note the passthrough is functionally meaningful, not cosmetic: with allowed_openai_params accepted, reasoning_effort: low vs max measured ~2 vs ~74 reasoning tokens on the same prompt from the upstream.
Operating System
macOS 27.0.1 (arm64)
Terminal
zsh
Description
OpenCode v1 (
opencode-ai≤ 1.18.x, AI-SDK based) forwarded unknown model/provideroptionsverbatim into the outgoing request body for@ai-sdk/openai-compatibleproviders. OpenCode v2 (thepackages/llmprotocol layer) builds the request body from an explicit field list and only lowers a fixed set of known options, so provider-specific body parameters can no longer be expressed from configuration.This breaks the LiteLLM dynamic allowlist pattern: gateways routing to deployments whose LiteLLM provider mapping doesn't list
reasoning_effortrequire the client to sendallowed_openai_params: ["reasoning_effort"]in the request body, otherwise the proxy rejects the call:The same config worked under v1 (option forwarded verbatim). Under v2 the option never reaches the wire, so any model behind such a route fails with the above HTTP 400 — and there is no config-only workaround left in v2.
Source pointers (v2)
packages/llm/src/protocols/openai-chat.ts—fromRequest()builds the body from explicit fields;lowerOptions()emits onlystoreandreasoning_effort.packages/llm/src/protocols/utils/openai-options.ts— options are read from the typedrequest.providerOptions?.openaibag; only the known keys (store,reasoningEffort,reasoningSummary,include,promptCacheKey,textVerbosity) are ever consulted.Config like:
sends
reasoning_efforton the wire but silently dropsallowed_openai_params.Suggested fix
Either restore verbatim forwarding of unknown option keys for openai-compatible protocols (v1 behavior), or add an explicit opt-in escape hatch (e.g. an
options.extra/bodybag merged into the provider body), or a documented plugin hook that can mutate the outgoing provider body. Any of the three unblocks enterprise LiteLLM gateways that rely on proxy-only body params.Plugins
OpenCode version
2.0.1 (
@opencode/cli)Steps to reproduce
@ai-sdk/openai-compatibleprovider at a LiteLLM proxy that routes the model to a deployment whose provider mapping doesn't supportreasoning_effort(e.g. tencent), with modeloptions: { "reasoningEffort": "high", "allowed_openai_params": ["reasoning_effort"] }.litellm.UnsupportedParamsError: tencent does not support parameters: ['reasoning_effort'](HTTP 400).reasoning_effortandallowed_openai_params, verified by capturing the outgoing request body against a local echo server) and the gateway returns HTTP 200.Note the passthrough is functionally meaningful, not cosmetic: with
allowed_openai_paramsaccepted,reasoning_effort: lowvsmaxmeasured ~2 vs ~74 reasoning tokens on the same prompt from the upstream.Operating System
macOS 27.0.1 (arm64)
Terminal
zsh