Skip to content

Fall back to JSON object mode when model rejects json_schema#58

Open
DavertMik wants to merge 1 commit into
mainfrom
fix/json-object-fallback-reasoning
Open

Fall back to JSON object mode when model rejects json_schema#58
DavertMik wants to merge 1 commit into
mainfrom
fix/json-object-fallback-reasoning

Conversation

@DavertMik

Copy link
Copy Markdown
Contributor

Problem

Models that don't support strict JSON Schema structured outputs failed every structured-output call (test planning, supervisor verdicts, etc.) with:

This model does not support response format `json_schema`.

The AI SDK's default generateObject strategy always asks the provider for response_format: json_schema; providers like Groq (and many OpenRouter models, especially reasoning models) reject it for unsupported models, so the whole step failed and retried identically.

Fix

Provider.generateObject now degrades gracefully:

  1. Detect the capability error (isJsonSchemaUnsupportedError) and remember the model for the session (so later calls skip the failed first attempt).
  2. Retry in JSON object mode — AI SDK output: 'no-schema' (which makes the provider send response_format: { type: "json_object" }), the JSON Schema injected into the prompt, and the reply validated against the original Zod schema. This matches the provider's documented "JSON Object Mode".
  3. The object-mode attempt treats the deterministic json_schema error as non-retryable, so it falls back immediately instead of burning retries.

Also in this PR

  • [Planner] forwards agentName: 'planner' to generateObject. Previously the planner passed no options, so mergeProviderOptions dropped its per-agent config — meaning ai.agents.planner.providerOptions (e.g. reasoningEffort) was silently ignored. This matters because a reasoning model with full reasoning can spend its entire output budget thinking and never emit the plan JSON; the fix lets users disable/tune reasoning for the planner.
  • Suppress the AI SDK allowSystemInMessages warning on provider calls (the codebase intentionally carries the system prompt as the first message).

Which models this helps

The fallback is provider-agnostic — it triggers on the error string and works for any provider whose unsupported models still accept json_object. From the live OpenRouter model list (340 models): 264 already support json_schema (never needed this), and 23 support json_object but not json_schema — those now work. Examples: qwen/qwen3-235b-a22b, nousresearch/hermes-4-405b/70b, z-ai/glm-4.5, google/gemma-4-31b-it, ai21/jamba-large-1.7, microsoft/wizardlm-2-8x22b, nvidia/llama-3.3-nemotron-super-49b-v1.5. (53 models support neither and remain unsupported.)

Reasoning models in this set also need their reasoning budgeted (via provider options like Groq reasoningEffort / OpenRouter reasoning) so they leave output room for the JSON — that's config, enabled here by the planner agentName fix.

Verification

  • Reproduced against Groq qwen/qwen3.6-27b through the real Provider: without the fix → Failed to validate JSON; with it → 4 scenarios returned.
  • bun test tests/integration/ → 62/62 pass
  • bun run format / bun run lint:fix clean

🤖 Generated with Claude Code

Models that don't support strict JSON Schema structured outputs (e.g.
many Groq/OpenRouter models, especially reasoning models) failed every
structured-output call with "This model does not support response
format `json_schema`".

Provider.generateObject now detects that error, marks the model, and
retries in JSON object mode: output:'no-schema' (which sends
response_format json_object), the schema injected into the prompt, and
the reply validated against the original Zod schema. The model is
remembered for the session so later calls skip the failed first attempt.

Also forward agentName:'planner' from the planner so its per-agent
providerOptions (e.g. reasoningEffort) actually apply — previously they
were dropped, so a reasoning model could spend its whole output budget
thinking and never emit the plan JSON.

Suppress the AI SDK system-message-in-messages warning on provider calls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant