You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
core: SessionRunner sends forced tool_choice ("required"/"none"/named); providers that only support "auto" fail the whole session #45953
OpenCode's server-side SessionRunner sends tool_choice values other than "auto" ("none", "required", or named-function choices) on some steps. Providers backed by models/gateways that only implement tool_choice: "auto" (in my case a provider labeled "Console Go") reject these requests with [invalid_request_error], which kills the entire session with "Failed to drain Session" — the subagent/step never completes. OpenCode should either degrade gracefully (retry with "auto"), make forced tool_choice configurable per provider/agent, or at minimum fail a single step instead of the session.
Environment
opencode version: 0.0.0-beta-18314 (beta channel; from runtime diagnostics snapshot — --version unavailable in this session)
OS: Linux 6.8.0-138-generic (x64)
Terminal: Unavailable (no terminal env vars set in this context)
Configure a custom OpenAI-compatible provider whose backend only supports tool_choice: "auto" (observed with a provider labeled "Console Go").
Run an agent/subagent turn that causes OpenCode to force a tool choice (observed on subagent runs and structured steps).
The provider rejects the request and the session errors out.
Reproduces consistently: the same error appeared across multiple sessions on 2026-08-26 and 2026-08-27 (8+ occurrences in the server log).
Expected Behavior
The session/step should complete. If a provider doesn't support the requested tool_choice mode, OpenCode should fall back to "auto" (possibly with a warning), or the behavior should be configurable per provider/agent rather than hard-forced.
Actual Behavior
Session fails with:
Failed to drain Session
cause="AI.Error: RequestExecutor.execute: Error from provider (Console Go):
Upstream request failed: [invalid_request_error] only `"auto"` is supported for
`tool_choice`. `"none"`, `"required"`, and named function choices are not currently
supported"
at SessionRunner.callModel → SessionRunner.runSteps → SessionRunner.drain
Additional Context
The request emitter is OpenCode's server session runner; the rejection comes from the upstream model API behind the provider. Sending non-autotool_choice is valid OpenAI-style behavior, so this is a provider-compat gap — but the current failure mode (whole session dies) is harsh.
Adding a concrete, fully reproducible instance of this on the OpenCode Go gateway (opencode-go, https://opencode.ai/zen/go/v1), triggered by the steps agent cap.
Trigger confirmed: steps cap forces tool_choice: "none"
The SessionRunner.runStep path sets toolChoice: "none" as soon as step >= agent.info.steps, and that request is what gets rejected. Nothing else in the session needs to be special; any agent with a steps value will eventually fail on its final forced-text step if its model only supports "auto".
Run any task that needs ~5 tool iterations. Result: 5 assistant turns complete with finish: tool-calls, then the 6th (forced text-only) turn fails:
AI.Error.InvalidRequest: only `"auto"` is supported for `tool_choice`. `"none"`, `"required"`, and named function choices are not currently supported
Observed deterministically in 3 worker subagent sessions (ses_f0baf501fffeFxVmg09j2gy969, ses_f0baee3a9ffecMWv0Ix06lgazG, ses_f0c062aa4ffeEFiXb1ADz2Iqbb) on 0.0.0-beta-18866: each session has exactly 5 assistant messages ending tool-calls, followed by one assistant message with finish: "error", error.type: "provider.invalid-request", and the message above. The child session then shows idle_outcome: failed and the parent gets a failed subagent tool result instead of findings.
Minimal gateway repro (no OpenCode client involved)
POST https://opencode.ai/zen/go/v1/responses with header x-opencode-session: ses_<hex>:
Same probe with gpt-6-luna, gpt-5.6-luna, deepseek-v4-pro, deepseek-v4-flash, mimo-v2.6-flash, hy3 and longcat-2.5-preview-free returns 200, so this is specific to the Muse Spark contributor endpoints (muse-spark-1.2-contributor rejects it too). The worker model that hits this is @ai-sdk/openai-backed and routed over the Responses protocol.
Impact
This makes the documented final-step behavior ("remove tools, ask model to summarize") unusable on Muse Spark, which is otherwise a very cost-effective model. The failure discards a whole completed session's work rather than degrading, and since subagents commonly run with steps caps, it produces silent delegation failures.
Suggested direction (same as the issue summary)
Track supported tool_choice values per model/gateway and fall back to "auto" (or omit tools + tool_choice entirely, the way the Anthropic path already lowers "none") when a provider doesn't support forced choices.
Failing that, make the final-step downgrade survive a provider rejection (per-step retry/degrade) instead of killing the drain.
On the gateway side, accepting "none" for Muse Spark would also resolve it.
Note: #51906 reported the same Zen-gateway symptom and was auto-closed by the compliance bot despite matching this issue; it may be worth folding that repro in here.
Thanks for the report. I reproduced this on 2.2.0 (the latest release; 0.0.0-beta-18314 isn't published on npm) and it still happens on the latest dev (506ac20).
When it happens: in v2 the session runner sends a non-autotool_choice in one place. Once an agent reaches its steps: limit, the final step sends tool_choice: "none" so the model writes a text summary. Nothing in v2's session code sends "required" or a named choice. A provider that only accepts "auto" rejects that last request, so the run fails instead of summarizing.
Setup:
A mock OpenAI-compatible provider that, like your gateway, returns 400 invalid_request_error for any tool_choice other than "auto" and otherwise always answers with a tool call.
The build agent set to steps: 2.
opencode run "list files repeatedly".
What I saw: step 1 is sent without tool_choice and its tool call runs. The final step is sent with tool_choice: "none", the provider rejects it, and the run ends with:
Error: only `"auto"` is supported for `tool_choice`. `"none"`, `"required"`, and named function choices are not currently supported
The script below reproduces it.
Workaround: if your agents or subagents set steps: (or maxSteps:), removing or raising that limit should avoid the forced "none" request. The other option is a model whose provider accepts the full tool_choice range.
Related: #54772 and #51906 report the same error when a subagent or agent hits its steps limit.
Reproduction script (repro.sh)
#!/usr/bin/env bash# Reproduces #45953: once an agent reaches its `steps:` limit, the session runner sends tool_choice "none".# A provider that only accepts tool_choice "auto" rejects that request, so the run ends with an error# instead of the documented final text summary.# Needs: bun, and `opencode` on PATH (bun add -g @opencode/[email protected]). Override with OPENCODE="<cmd>".set -euo pipefail
OPENCODE=${OPENCODE:-opencode}
WORK=$(mktemp -d)
mkdir -p "$WORK/proj""$WORK/home"
cp "$(dirname "$0")/mock.ts""$WORK/mock.ts"
cat >"$WORK/proj/opencode.json"<<'JSON'{ "$schema": "https://opencode.ai/config.json", "provider": { "autoonly": { "npm": "@ai-sdk/openai-compatible", "name": "Auto Only Gateway", "options": { "baseURL": "http://127.0.0.1:4517/v1", "apiKey": "x" }, "models": { "auto-only": { "name": "Auto Only", "tool_call": true } } } }, "model": "autoonly/auto-only", "agent": { "build": { "steps": 2 } }}JSONecho hi >"$WORK/proj/README.md"
bun "$WORK/mock.ts">"$WORK/mock.log"2>&1&
MOCK=$!trap'kill $MOCK 2>/dev/null || true' EXIT
sleep 1
cd"$WORK/proj"
HOME="$WORK/home" XDG_DATA_HOME="$WORK/home/data" XDG_CONFIG_HOME="$WORK/home/cfg" \
timeout 180 $OPENCODE run "list files repeatedly"2>&1>"$WORK/run.log"||true; head -20 "$WORK/run.log"echo"--- requests seen by the auto-only mock provider ---"
cat "$WORK/mock.log"
Thanks for the report. I reproduced this on 2.2.0 (the latest release; 0.0.0-beta-18314 isn't published on npm) and it still happens on the latest dev (506ac20).
When it happens: in v2 the session runner sends a non-autotool_choice in one place. Once an agent reaches its steps: limit, the final step sends tool_choice: "none" so the model writes a text summary. Nothing in v2's session code sends "required" or a named choice. A provider that only accepts "auto" rejects that last request, so the run fails instead of summarizing.
Setup:
A mock OpenAI-compatible provider that, like your gateway, returns 400 invalid_request_error for any tool_choice other than "auto" and otherwise always answers with a tool call.
The build agent set to steps: 2.
opencode run "list files repeatedly".
What I saw: step 1 is sent without tool_choice and its tool call runs. The final step is sent with tool_choice: "none", the provider rejects it, and the run ends with:
Error: only `"auto"` is supported for `tool_choice`. `"none"`, `"required"`, and named function choices are not currently supported
The script below reproduces it.
Workaround: if your agents or subagents set steps: (or maxSteps:), removing or raising that limit should avoid the forced "none" request. The other option is a model whose provider accepts the full tool_choice range.
Related: #54772 and #51906 report the same error when a subagent or agent hits its steps limit.
Reproduction script (repro.sh)
Hello, could u advice exactly where do I rise/set the steps: or maxsteps: coz this one got very annoying recently after updating to 2.2 getting it ever 10-20 minutes or so.
Activity
awesomedog213 commentedon Sep 30, 2026
Adding a concrete, fully reproducible instance of this on the OpenCode Go gateway (
opencode-go,https://opencode.ai/zen/go/v1), triggered by thestepsagent cap.Trigger confirmed:
stepscap forcestool_choice: "none"The
SessionRunner.runSteppath setstoolChoice: "none"as soon asstep >= agent.info.steps, and that request is what gets rejected. Nothing else in the session needs to be special; any agent with astepsvalue will eventually fail on its final forced-text step if its model only supports"auto".Repro
Agent config:
Run any task that needs ~5 tool iterations. Result: 5 assistant turns complete with
finish: tool-calls, then the 6th (forced text-only) turn fails:Observed deterministically in 3 worker subagent sessions (
ses_f0baf501fffeFxVmg09j2gy969,ses_f0baee3a9ffecMWv0Ix06lgazG,ses_f0c062aa4ffeEFiXb1ADz2Iqbb) on0.0.0-beta-18866: each session has exactly 5 assistant messages endingtool-calls, followed by one assistant message withfinish: "error",error.type: "provider.invalid-request", and the message above. The child session then showsidle_outcome: failedand the parent gets a failed subagent tool result instead of findings.Minimal gateway repro (no OpenCode client involved)
POST https://opencode.ai/zen/go/v1/responseswith headerx-opencode-session: ses_<hex>:{ "model": "muse-spark-1.3-contributor", "input": [{"role": "user", "content": "hi"}], "tools": [{"type": "function", "name": "noop", "description": "no op", "parameters": {"type": "object", "properties": {}}}], "tool_choice": "none", "max_output_tokens": 16, "stream": false }tool_choice: "none"->400 {"error":{"message":"only"auto"is supported fortool_choice...","param":"tool_choice","type":"invalid_request_error"}}tool_choice: "required"-> same 400tool_choice: "auto"->200Same probe with
gpt-6-luna,gpt-5.6-luna,deepseek-v4-pro,deepseek-v4-flash,mimo-v2.6-flash,hy3andlongcat-2.5-preview-freereturns200, so this is specific to the Muse Spark contributor endpoints (muse-spark-1.2-contributorrejects it too). The worker model that hits this is@ai-sdk/openai-backed and routed over the Responses protocol.Impact
This makes the documented final-step behavior ("remove tools, ask model to summarize") unusable on Muse Spark, which is otherwise a very cost-effective model. The failure discards a whole completed session's work rather than degrading, and since subagents commonly run with
stepscaps, it produces silent delegation failures.Suggested direction (same as the issue summary)
tool_choicevalues per model/gateway and fall back to"auto"(or omit tools +tool_choiceentirely, the way the Anthropic path already lowers"none") when a provider doesn't support forced choices."none"for Muse Spark would also resolve it.Note: #51906 reported the same Zen-gateway symptom and was auto-closed by the compliance bot despite matching this issue; it may be worth folding that repro in here.
opencodejr commentedon Oct 28, 2026
Thanks for the report. I reproduced this on 2.2.0 (the latest release;
0.0.0-beta-18314isn't published on npm) and it still happens on the latestdev(506ac20).When it happens: in v2 the session runner sends a non-
autotool_choicein one place. Once an agent reaches itssteps:limit, the final step sendstool_choice: "none"so the model writes a text summary. Nothing in v2's session code sends"required"or a named choice. A provider that only accepts"auto"rejects that last request, so the run fails instead of summarizing.Setup:
invalid_request_errorfor anytool_choiceother than"auto"and otherwise always answers with a tool call.buildagent set tosteps: 2.opencode run "list files repeatedly".What I saw: step 1 is sent without
tool_choiceand its tool call runs. The final step is sent withtool_choice: "none", the provider rejects it, and the run ends with:The script below reproduces it.
Workaround: if your agents or subagents set
steps:(ormaxSteps:), removing or raising that limit should avoid the forced"none"request. The other option is a model whose provider accepts the fulltool_choicerange.Related: #54772 and #51906 report the same error when a subagent or agent hits its steps limit.
Reproduction script (repro.sh)
Run it:
bash repro.shhunlight5781-droid commentedon Oct 29, 2026
Hello, could u advice exactly where do I rise/set the steps: or maxsteps: coz this one got very annoying recently after updating to 2.2 getting it ever 10-20 minutes or so.