From 0e8f7694ed22863a889c73060153affab62bafd7 Mon Sep 17 00:00:00 2001 From: Kyle Mistele Date: Mon, 12 Jan 2026 23:05:43 -0800 Subject: [PATCH] fix: force tool calls when outputFormat is json_schema When structured output is requested, the model must call the StructuredOutput tool instead of responding with plain text. Changes: - Add toolChoice parameter to LLM.StreamInput - Pass toolChoice: "required" to streamText when outputFormat is json_schema - This forces the model to call a tool, ensuring structured output is captured --- packages/opencode/src/session/llm.ts | 2 ++ packages/opencode/src/session/prompt.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/opencode/src/session/llm.ts b/packages/opencode/src/session/llm.ts index a81aa7db22..abd0c53380 100644 --- a/packages/opencode/src/session/llm.ts +++ b/packages/opencode/src/session/llm.ts @@ -28,6 +28,7 @@ export namespace LLM { small?: boolean tools: Record retries?: number + toolChoice?: "auto" | "required" | "none" } export type StreamOutput = StreamTextResult @@ -146,6 +147,7 @@ export namespace LLM { providerOptions: ProviderTransform.providerOptions(input.model, params.options), activeTools: Object.keys(tools).filter((x) => x !== "invalid"), tools, + toolChoice: input.toolChoice, maxOutputTokens, abortSignal: input.abort, headers: { diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index b94abd67bf..1614384e27 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -573,6 +573,7 @@ export namespace SessionPrompt { ], tools, model, + toolChoice: outputFormat.type === "json_schema" ? "required" : undefined, }) // Handle structured output logic