Repository navigation
Description
In v2.0.16 the agent-level variant config key has no effect on outgoing requests, although the config schema documents it and opencode debug agents resolves it correctly.
Schema (https://opencode.ai/config.json, $defs/AgentConfig/properties/variant):
Default model variant for this agent (applies only when using the agent's configured model).
Config used
{
"model": "opencode-go/deepseek-v4.1-flash",
"agent": {
"build": { "model": "opencode-go/deepseek-v4.1-flash", "variant": "max" },
"plan": { "model": "opencode-go/deepseek-v4.1-flash", "variant": "max" },
"general": { "model": "opencode-go/deepseek-v4.1-flash", "variant": "max" }
}
}opencode debug agents resolves it fine:
build -> {"id": "deepseek-v4.1-flash", "providerID": "opencode-go", "variant": "max"}
Reproduction### Reproduction
I pointed provider.opencode-go.options.baseURL at a local recording proxy (project-level opencode.json) and captured the raw POST /chat/completions bodies.
Agent config in place for these runs:
"agent": { "build": { "model": "opencode-go/deepseek-v4.1-flash", "variant": "max" } }opencode debug agents resolves that to {"id":"deepseek-v4.1-flash","providerID":"opencode-go","variant":"max"}.
| invocation | effort on the wire |
|---|---|
opencode run --auto "..." — agent build used implicitly, nothing model-related passed on the CLI |
none |
opencode run --auto --agent build "..." — same config, agent named explicitly |
none |
opencode run --auto -m 'opencode-go/deepseek-v4.1-flash#max' "..." |
"reasoning_effort": "max" |
opencode run --auto -m 'opencode-go/deepseek-v4.1-flash' "..." |
none |
A field-by-field diff of the two bodies (agent config vs explicit #max, same model, same prompt shape) shows reasoning_effort is the only top-level field present in the explicit case and absent in the agent-config case. Scanning the entire agent-config body for max outside messages finds only unrelated tool-parameter descriptions ("Very short label (max 30 chars)" etc.), so the value is not being sent under some other key.
Two extra probes, to rule out "invalid value is simply dropped":
- The same capture was also run while the agent
variantwas an invalid value ("bogus") — identical result: no error, no effort field. - With a valid value (
"max") — again no error and no effort field, while the explicit-m ...#maxpath in the same session does sendreasoning_effort: "max".
So config-provided variants are neither validated nor applied, for valid and invalid values alike.
Expected
A session started with an agent that configures both model and variant should send the corresponding effort (e.g. reasoning_effort: "max"), as the schema description states.
Related
- core: legacy Markdown agent silently drops "model: provider/model#variant" — subagent inherits parent model #50849 / fix(core): keep embedded variant in legacy markdown agent model #51311 cover the legacy Markdown agent surface, where an embedded
model: provider/model#variantis dropped. This report is the JSON-config surface (agent.<id>.variant), where the variant is resolved bydebug agentsbut still never reaches the request. - Putting
#variantinside the model string in config ("model": "opencode-go/deepseek-v4.1-flash#max", in both the agent blocks and the top-levelmodel) makesdebug agentsreportmodel: nullfor every agent — the embedded form appears to be CLI-only (related: fix(core): parse embedded "#variant" in model selections #50853). - Qwen3.8 Flash: variant=xhigh silently disables reasoning by sending output_config.effort without thinking #49079 looks like a sibling report for a different model (variant accepted but not reflected in the request).
Environment
opencode v2.0.16, Windows x64, installed vianpm i -g @opencode/cli- Provider/model:
opencode-go/deepseek-v4.1-flash(the registry accepts#maxand rejects#xhighwithVariant unavailable, so variants are declared for this model — it is not a "model has no variants" case)
Activity
github-actions commentedon Sep 25, 2026
This issue might be a duplicate of existing issues. Please check:
1575514641-ship-it commentedon Sep 25, 2026
Re-verified after self-checking my own capture setup: the two "agent config" rows were first captured while the agent's
varianthappened to hold an invalid placeholder value, so I re-ran the full capture withvariant: "max"— the valueopencode debug agentsresolves for this agent — and got the identical result (noreasoning_efforton the wire, while-m 'opencode-go/deepseek-v4.1-flash#max'in the same session does send it). The body above now reflects the verified runs. I can re-run and share the raw capture on request.SachinD6 commentedon Sep 25, 2026
The variant was already on the agent record, but SessionRunnerModel only read session.model.variant so a matching session model never picked it up. This PR carries the agent variant through when the models match unless the session sets its own: #51385
opencodejr commentedon Oct 28, 2026
Thanks for the detailed report. I can confirm this on v2.0.16.
What I ran:
opencode-gopointed at a local mock server that records request bodies.agent.buildset to{ "model": "opencode-go/deepseek-v4.1-flash", "variant": "max" }.opencode run --auto "hi".The captured
POST /v1/chat/completionsbody fordeepseek-v4.1-flashhad noreasoning_effortfield, just as you describe.In v2.0.16, when
opencode runstarts a session without-m, the runner falls back to the default model and never reads the agent's configuredvariant. A recent change ondev(#58355) makes the runner use the agent's model and variant when no model is given. It looks like it should cover this, but it isn't in a release yet and I haven't checked it againstdev. Until then, passing-m opencode-go/deepseek-v4.1-flash#maxexplicitly works, as you found.Related:
runand the SDK.debug agentsdid not show the resolved variant.model#variantcase.