Skip to content

tool_choice: 'required' incompatible with thinking-enabled models when using structured output #15226

@bralca

Description

@bralca

Description

When using format: { type: "json_schema" } with the prompt_async API, OpenCode unconditionally sets toolChoice: "required" for the internal StructuredOutput tool. For reasoning models like Kimi K2.5
that have thinking automatically enabled, the downstream provider rejects this with:

tool_choice 'required' is incompatible with thinking enabled

This affects OpenCode Go (opencode-go). The same model + structured output works via OpenCode Zen (opencode), suggesting Zen reconciles the conflict server-side.

OpenCode Version

1.2.14

Plugins

No response

OpenCode version

No response

Steps to reproduce

  1. Start an OpenCode server with an opencode-go API key
  2. Create a session
  3. Send prompt_async with json_schema format targeting a reasoning model:

curl -X POST http://127.0.0.1:/session/<session_id>/prompt_async
-H "Authorization: Bearer "
-H "Content-Type: application/json"
-d '{
"parts": [{"type":"text","text":"Describe the directory. Return JSON."}],
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"description": {"type":"string"},
"files": {"type":"array","items":{"type":"string"}}
},
"required": ["description","files"]
},
"retryCount": 2
},
"model": {"providerID":"opencode-go","modelID":"kimi-k2.5"}
}'

  1. SSE /event endpoint fires session.error immediately:

{
"error": {
"message": "Provider returned error",
"code": 400,
"metadata": {
"raw": "{"error":{"message":"tool_choice 'required' is incompatible with thinking enabled"}}",
"provider_name": "Moonshot AI"
}
}
}

Expected Behavior

Structured output should work with all models including reasoning/thinking models.

Root Cause

Tracing through the v1.2.14 source:

  1. SessionPrompt.loop() creates a StructuredOutput tool when format.type === "json_schema"
  2. Unconditionally sets toolChoice: "required":
    toolChoice: format4.type === "json_schema" ? "required" : undefined
  3. Separately, ProviderTransform.options() enables thinking for reasoning models:
    result["thinking"] = { type: "enabled", budgetTokens: ... }
  4. Both tool_choice: "required" and thinking params are sent together to the downstream provider, which rejects the combination.
    Affected Models

Any model with reasoning: true accessed via providers that enforce thinking + tool_choice incompatibility. Confirmed: kimi-k2.5 (Moonshot AI) via opencode-go.

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcoreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions