JSON Schema Support

JSON Schemas are used in two places in primfunctions.completions:

Each provider supports a different subset of JSON Schema, and the proxy automatically sanitizes schemas for Google compatibility where possible.

Schema families#

All twelve providers accept response_schema, but they fall into three schema families — OpenAI-shaped, Anthropic-shaped, and Google-shaped — and the differences below are properties of the family, not of the individual provider. The OpenAI-shaped family has two wire envelopes, so it takes two rows:

FamilyProvidersWire shape
OpenAI-shapedopenai, openai_bedrock, alibaba, deepseek, groq, voicerunresponse_format → json_schema with strict: true
OpenAI-shaped (Responses)openai_responsestext.format → type: "json_schema" with strict: true — same fields, different envelope
Anthropic-shapedanthropic, anthropic_vertex, anthropic_bedrockoutput_config with a json_schema format
Google-shapedgoogle, google_vertexresponse_mime_type: "application/json" + sanitized schema

Your response_schema is carried through unchanged in every family except the Google-shaped one, which sanitizes it first. So the same schema you write for openai goes on the wire unmodified for groq, deepseek, and voicerun too — what can still differ is what the model behind the endpoint does with it.

Cross-Provider Compatibility#

The following JSON Schema features work across every provider in every family:

FeatureExample
type"type": "string"
properties"properties": {"name": {"type": "string"}}
required"required": ["name"]
description"description": "The user's name"
enum (strings)"enum": ["celsius", "fahrenheit"]
items (arrays)"items": {"type": "string"}
anyOf"anyOf": [{"type": "string"}, {"type": "integer"}]
default"default": "celsius"

Google Schema Sanitization#

Google Gemini does not support several JSON Schema features that the OpenAI-shaped and Anthropic-shaped families accept. The proxy automatically handles these when the request lands on either Google-shaped provider (google or google_vertex — Vertex reuses the same sanitizer):

FeatureBehavior
additionalProperties: falseSilently stripped
additionalProperties: trueRaises InvalidToolError
constConverted to single-value enum
allOfRaises InvalidToolError
["string", "null"] union typesConverted to "type": "string", "nullable": true
Non-string enum valuesRaises InvalidToolError

For schemas that raise InvalidToolError, you'll need to restructure them for Google compatibility. For example, instead of additionalProperties: true, consider using an array of key-value objects:

# Instead of this (not supported on Google): "metadata": { "type": "object", "additionalProperties": True } # Use this: "metadata": { "type": "array", "items": { "type": "object", "properties": { "key": {"type": "string"}, "value": {"type": "string"} }, "required": ["key", "value"] } }

Provider-Specific Differences#

FeatureOpenAI-shapedAnthropic-shapedGoogle-shaped
additionalPropertiesRequired false in strict modeRequired false in strict modeNot supported
minimum / maximumNot supportedSDK moves to descriptionSupported
minLength / maxLengthNot supportedSDK moves to descriptionSupported
patternNot supportedSupportedSupported
formatNot supportedSupportedSupported
constSupportedSupportedAuto-converted to enum
allOfNot documentedSupportedNot supported
nullable: trueUse ["type", "null"]Use ["type", "null"]Supported (Google-specific)
Non-string enumSupportedSupportedNot supported
Recursive schemasSupportedNot supportedLimited

The OpenAI-shaped column describes OpenAI's own strict-mode behavior. The other endpoints in that family receive the same schema and the same strict: true flag, but how faithfully strict mode is enforced depends on the endpoint and the model behind it — see Alibaba/DashScope, DeepSeek, and Groq's structured outputs docs. voicerun serves fine-tuned small models through vLLM, so enforcement there follows whatever the serving stack supports rather than OpenAI's strict-mode contract.

Recommendations#

For maximum portability across providers, stick to:

  • Basic types: string, number, integer, boolean, object, array
  • properties, required, description, enum (strings only), items
  • Avoid additionalProperties, const, allOf, pattern, format, minimum/maximum
toolsschemasstructured-outputgoogle