{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://pi.dev/schemas/models.schema.json", "$comment": "This file is generated from TypeScript source. Do not edit it manually; run npm run generate:schemas.", "type": "object", "required": [ "providers" ], "properties": { "$schema": { "type": "string" }, "providers": { "type": "object", "patternProperties": { "^.*$": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "baseUrl": { "type": "string", "minLength": 1 }, "apiKey": { "type": "string", "minLength": 1 }, "api": { "type": "string", "minLength": 1 }, "oauth": { "type": "string", "const": "radius" }, "headers": { "type": "object", "patternProperties": { "^.*$": { "type": "string" } } }, "compat": { "$ref": "#/$defs/ProviderCompat", "description": "Provider and model compatibility overrides." }, "authHeader": { "type": "boolean" }, "models": { "type": "array", "items": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1 }, "api": { "type": "string", "minLength": 1 }, "baseUrl": { "type": "string", "minLength": 1 }, "reasoning": { "type": "boolean" }, "thinkingLevelMap": { "$ref": "#/$defs/ThinkingLevelMap" }, "input": { "type": "array", "items": { "enum": [ "text", "image" ] } }, "inputLimits": { "$ref": "#/$defs/ModelInputLimits" }, "cost": { "$ref": "#/$defs/ModelCost" }, "promptCache": { "$ref": "#/$defs/ModelPromptCache", "description": "Best-effort prompt cache lifetime in seconds for each retention tier. A missing tier means the lifetime is unknown, so Pi does not warm it." }, "contextWindow": { "type": "number", "exclusiveMinimum": 0 }, "maxTokens": { "type": "number", "exclusiveMinimum": 0 }, "samplingParams": { "type": "object", "patternProperties": { "^.*$": {} } }, "samplingParamsByThinkingLevel": { "type": "object", "properties": { "off": { "type": "object", "patternProperties": { "^.*$": {} } }, "minimal": { "type": "object", "patternProperties": { "^.*$": {} } }, "low": { "type": "object", "patternProperties": { "^.*$": {} } }, "medium": { "type": "object", "patternProperties": { "^.*$": {} } }, "high": { "type": "object", "patternProperties": { "^.*$": {} } }, "xhigh": { "type": "object", "patternProperties": { "^.*$": {} } }, "max": { "type": "object", "patternProperties": { "^.*$": {} } } } }, "headers": { "type": "object", "patternProperties": { "^.*$": { "type": "string" } } }, "compat": { "$ref": "#/$defs/ProviderCompat", "description": "Provider and model compatibility overrides." } } } }, "modelOverrides": { "type": "object", "patternProperties": { "^.*$": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "reasoning": { "type": "boolean" }, "thinkingLevelMap": { "$ref": "#/$defs/ThinkingLevelMap" }, "input": { "type": "array", "items": { "enum": [ "text", "image" ] } }, "inputLimits": { "$ref": "#/$defs/ModelInputLimits" }, "cost": { "type": "object", "properties": { "input": { "type": "number", "description": "Input cost in USD per million tokens." }, "output": { "type": "number", "description": "Output cost in USD per million tokens." }, "cacheRead": { "type": "number", "description": "Cache-read cost in USD per million tokens." }, "cacheWrite": { "type": "number", "description": "Cache-write cost in USD per million tokens." }, "tiers": { "type": "array", "items": { "type": "object", "required": [ "inputTokensAbove", "input", "output", "cacheRead", "cacheWrite" ], "properties": { "inputTokensAbove": { "type": "number", "description": "Use this tier when total request input exceeds this token count." }, "input": { "type": "number", "description": "Input cost in USD per million tokens." }, "output": { "type": "number", "description": "Output cost in USD per million tokens." }, "cacheRead": { "type": "number", "description": "Cache-read cost in USD per million tokens." }, "cacheWrite": { "type": "number", "description": "Cache-write cost in USD per million tokens." } } }, "description": "Request-wide pricing tiers. The highest matching input threshold applies to the full request." } } }, "promptCache": { "$ref": "#/$defs/ModelPromptCache", "description": "Best-effort prompt cache lifetime in seconds for each retention tier. A missing tier means the lifetime is unknown, so Pi does not warm it." }, "contextWindow": { "type": "number", "exclusiveMinimum": 0 }, "maxTokens": { "type": "number", "exclusiveMinimum": 0 }, "samplingParams": { "type": "object", "patternProperties": { "^.*$": {} } }, "samplingParamsByThinkingLevel": { "type": "object", "properties": { "off": { "type": "object", "patternProperties": { "^.*$": {} } }, "minimal": { "type": "object", "patternProperties": { "^.*$": {} } }, "low": { "type": "object", "patternProperties": { "^.*$": {} } }, "medium": { "type": "object", "patternProperties": { "^.*$": {} } }, "high": { "type": "object", "patternProperties": { "^.*$": {} } }, "xhigh": { "type": "object", "patternProperties": { "^.*$": {} } }, "max": { "type": "object", "patternProperties": { "^.*$": {} } } } }, "headers": { "type": "object", "patternProperties": { "^.*$": { "type": "string" } } }, "compat": { "$ref": "#/$defs/ProviderCompat", "description": "Provider and model compatibility overrides." } } } } } } } } } }, "$defs": { "ModelCost": { "type": "object", "required": [ "input", "output", "cacheRead", "cacheWrite" ], "properties": { "input": { "type": "number", "description": "Input cost in USD per million tokens." }, "output": { "type": "number", "description": "Output cost in USD per million tokens." }, "cacheRead": { "type": "number", "description": "Cache-read cost in USD per million tokens." }, "cacheWrite": { "type": "number", "description": "Cache-write cost in USD per million tokens." }, "tiers": { "type": "array", "items": { "type": "object", "required": [ "inputTokensAbove", "input", "output", "cacheRead", "cacheWrite" ], "properties": { "inputTokensAbove": { "type": "number", "description": "Use this tier when total request input exceeds this token count." }, "input": { "type": "number", "description": "Input cost in USD per million tokens." }, "output": { "type": "number", "description": "Output cost in USD per million tokens." }, "cacheRead": { "type": "number", "description": "Cache-read cost in USD per million tokens." }, "cacheWrite": { "type": "number", "description": "Cache-write cost in USD per million tokens." } } }, "description": "Request-wide pricing tiers. The highest matching input threshold applies to the full request." } } }, "ModelInputLimits": { "type": "object", "properties": { "maxRequestBytes": { "type": "integer", "minimum": 1, "description": "Maximum serialized provider request size in bytes." }, "images": { "type": "object", "properties": { "resize": { "type": "object", "properties": { "maxWidth": { "type": "integer", "minimum": 1 }, "maxHeight": { "type": "integer", "minimum": 1 }, "maxBytes": { "type": "integer", "minimum": 1, "description": "Maximum base64-encoded payload size in bytes." }, "jpegQuality": { "type": "integer", "minimum": 1, "maximum": 100 } }, "description": "Cache-safe resize profile applied before a new image enters conversation history." }, "maxPerMessage": { "type": "integer", "minimum": 1, "description": "Maximum images accepted in one provider message." }, "maxPerRequest": { "type": "integer", "minimum": 1, "description": "Maximum images accepted across one provider request." } } } } }, "ModelPromptCache": { "type": "object", "properties": { "short": { "type": "number", "exclusiveMinimum": 0 }, "long": { "type": "number", "exclusiveMinimum": 0 } } }, "ProviderCompat": { "type": "object", "properties": { "supportsStore": { "type": "boolean", "description": "Whether the provider supports the store field. Default: auto-detected from URL." }, "supportsDeveloperRole": { "type": "boolean", "description": "Whether the provider supports the developer role instead of system. Defaults are API-specific." }, "supportsReasoningEffort": { "type": "boolean", "description": "Whether the provider supports reasoning_effort. Default: auto-detected from URL." }, "supportsUsageInStreaming": { "type": "boolean", "description": "Whether the provider supports stream_options.include_usage for token usage in streaming responses.", "default": true }, "supportsFinishReason": { "type": "boolean", "description": "Whether streamed responses include finish_reason. When false, pi infers stop or toolUse when the stream ends.", "default": true }, "maxTokensField": { "anyOf": [ { "type": "string", "const": "max_completion_tokens" }, { "type": "string", "const": "max_tokens" } ], "description": "Which field to use for max tokens. Default: auto-detected from URL." }, "requiresToolResultName": { "type": "boolean", "description": "Whether tool results require the name field. Default: auto-detected from URL." }, "requiresAssistantAfterToolResult": { "type": "boolean", "description": "Whether a user message after tool results requires an assistant message in between. Default: auto-detected from URL." }, "requiresThinkingAsText": { "type": "boolean", "description": "Whether thinking blocks must be converted to text blocks with delimiters. Default: auto-detected from URL." }, "requiresReasoningContentOnAssistantMessages": { "type": "boolean", "description": "Whether all replayed assistant messages must include an empty reasoning_content field when reasoning is enabled. Default: auto-detected from URL." }, "thinkingFormat": { "anyOf": [ { "type": "string", "const": "openai" }, { "type": "string", "const": "openrouter" }, { "type": "string", "const": "deepseek" }, { "type": "string", "const": "together" }, { "type": "string", "const": "baseten" }, { "type": "string", "const": "zai" }, { "type": "string", "const": "qwen" }, { "type": "string", "const": "chat-template" }, { "type": "string", "const": "qwen-chat-template" }, { "type": "string", "const": "string-thinking" }, { "type": "string", "const": "ant-ling" } ], "description": "Format for reasoning or thinking parameters. When omitted, Pi auto-detects the format from the provider URL. \"openai\" uses reasoning_effort, \"openrouter\" uses reasoning.effort, \"deepseek\" uses thinking.type plus reasoning_effort when supported, \"together\" uses reasoning.enabled plus reasoning_effort when supported, \"baseten\" uses configurable chat_template_args plus reasoning_effort when supported, \"zai\" uses thinking.type, \"qwen\" uses top-level enable_thinking, \"qwen-chat-template\" uses chat_template_kwargs.enable_thinking and preserve_thinking, \"chat-template\" uses configurable chat_template_kwargs, \"string-thinking\" uses top-level thinking, and \"ant-ling\" uses reasoning.effort only when the mapped effort is non-null." }, "chatTemplateKwargs": { "type": "object", "patternProperties": { "^.*$": { "anyOf": [ { "type": "string" }, { "type": "number" }, { "type": "boolean" }, { "type": "null" }, { "type": "object", "required": [ "$var" ], "properties": { "$var": { "anyOf": [ { "type": "string", "const": "thinking.enabled" }, { "type": "string", "const": "thinking.effort" }, { "type": "string", "const": "thinking.budget" } ] }, "omitWhenOff": { "type": "boolean" } } } ] } }, "description": "Kwargs sent as chat_template_kwargs when thinkingFormat is \"chat-template\". Use $var with \"thinking.enabled\", \"thinking.effort\", or \"thinking.budget\" for pi-controlled values." }, "chatTemplateArgs": { "type": "object", "patternProperties": { "^.*$": { "anyOf": [ { "type": "string" }, { "type": "number" }, { "type": "boolean" }, { "type": "null" }, { "type": "object", "required": [ "$var" ], "properties": { "$var": { "anyOf": [ { "type": "string", "const": "thinking.enabled" }, { "type": "string", "const": "thinking.effort" }, { "type": "string", "const": "thinking.budget" } ] }, "omitWhenOff": { "type": "boolean" } } } ] } }, "description": "Arguments sent as chat_template_args when thinkingFormat is \"baseten\". Use $var with \"thinking.enabled\", \"thinking.effort\", or \"thinking.budget\" for pi-controlled values." }, "openRouterRouting": { "type": "object", "properties": { "allow_fallbacks": { "type": "boolean", "description": "Whether to allow backup providers to serve requests.", "default": true }, "require_parameters": { "type": "boolean", "description": "Whether to filter providers to only those that support all parameters in the request.", "default": false }, "data_collection": { "anyOf": [ { "type": "string", "const": "deny" }, { "type": "string", "const": "allow" } ], "description": "Data collection setting. \"allow\": allow providers that may store or train on data. \"deny\": only use providers that do not collect user data.", "default": "allow" }, "zdr": { "type": "boolean", "description": "Whether to restrict routing to only ZDR (Zero Data Retention) endpoints." }, "enforce_distillable_text": { "type": "boolean", "description": "Whether to restrict routing to only models that allow text distillation." }, "order": { "type": "array", "items": { "type": "string" }, "description": "An ordered list of provider names or slugs to try in sequence, falling back to the next if unavailable." }, "only": { "type": "array", "items": { "type": "string" }, "description": "List of provider names or slugs to exclusively allow for this request." }, "ignore": { "type": "array", "items": { "type": "string" }, "description": "List of provider names or slugs to skip for this request." }, "quantizations": { "type": "array", "items": { "type": "string" }, "description": "A list of quantization levels to filter providers by, for example [\"fp16\", \"bf16\", \"fp8\", \"fp6\", \"int8\", \"int4\", \"fp4\", \"fp32\"]." }, "sort": { "anyOf": [ { "type": "string" }, { "type": "object", "properties": { "by": { "type": "string", "description": "The sorting metric, such as \"price\", \"throughput\", or \"latency\"." }, "partition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Partitioning strategy: \"model\" or \"none\".", "default": "model" } } } ], "description": "Sorting strategy. Can be a string such as \"price\", \"throughput\", or \"latency\", or an object." }, "max_price": { "type": "object", "properties": { "prompt": { "anyOf": [ { "type": "number" }, { "type": "string" } ], "description": "Price per million prompt tokens." }, "completion": { "anyOf": [ { "type": "number" }, { "type": "string" } ], "description": "Price per million completion tokens." }, "image": { "anyOf": [ { "type": "number" }, { "type": "string" } ], "description": "Price per image." }, "audio": { "anyOf": [ { "type": "number" }, { "type": "string" } ], "description": "Price per audio unit." }, "request": { "anyOf": [ { "type": "number" }, { "type": "string" } ], "description": "Price per request." } }, "description": "Maximum price per million tokens in USD." }, "preferred_min_throughput": { "anyOf": [ { "type": "number" }, { "type": "object", "properties": { "p50": { "type": "number", "description": "Minimum tokens per second at the 50th percentile." }, "p75": { "type": "number", "description": "Minimum tokens per second at the 75th percentile." }, "p90": { "type": "number", "description": "Minimum tokens per second at the 90th percentile." }, "p99": { "type": "number", "description": "Minimum tokens per second at the 99th percentile." } } } ], "description": "Preferred minimum throughput in tokens per second. A number applies to p50." }, "preferred_max_latency": { "anyOf": [ { "type": "number" }, { "type": "object", "properties": { "p50": { "type": "number", "description": "Maximum latency in seconds at the 50th percentile." }, "p75": { "type": "number", "description": "Maximum latency in seconds at the 75th percentile." }, "p90": { "type": "number", "description": "Maximum latency in seconds at the 90th percentile." }, "p99": { "type": "number", "description": "Maximum latency in seconds at the 99th percentile." } } } ], "description": "Preferred maximum latency in seconds. A number applies to p50." } }, "description": "OpenRouter provider routing preferences. Controls which upstream providers OpenRouter routes requests to. Sent as the provider field in the OpenRouter API request body. See https://openrouter.ai/docs/guides/routing/provider-selection." }, "vercelGatewayRouting": { "type": "object", "properties": { "only": { "type": "array", "items": { "type": "string" }, "description": "List of provider slugs to exclusively use for this request, for example [\"bedrock\", \"anthropic\"]." }, "order": { "type": "array", "items": { "type": "string" }, "description": "List of provider slugs to try in order, for example [\"anthropic\", \"openai\"]." } }, "description": "Vercel AI Gateway routing preferences. Controls which upstream providers the gateway routes requests to. See https://vercel.com/docs/ai-gateway/models-and-providers/provider-options." }, "zaiToolStream": { "type": "boolean", "description": "Whether z.ai supports top-level tool_stream for streaming tool call deltas.", "default": false }, "thinkingTokenBudgetField": { "anyOf": [ { "type": "string", "const": "thinking_token_budget" }, { "type": "string", "const": "thinking_budget" }, { "type": "string", "const": "thinking_budget_tokens" } ], "description": "Top-level request field used to cap reasoning tokens from thinkingBudgets. Reasoning and the answer share max_tokens on these endpoints. \"thinking_token_budget\" is vLLM, \"thinking_budget\" is Qwen, DashScope, or SGLang, and \"thinking_budget_tokens\" is llama.cpp. Off by default and not set on the generated catalog." }, "supportsThinkingTokenBudget": { "type": "boolean", "description": "Alias for thinkingTokenBudgetField: \"thinking_token_budget\" (vLLM). Prefer thinkingTokenBudgetField.", "default": false }, "supportsOpenAIGrammarTools": { "type": "boolean", "description": "Whether the provider supports OpenAI custom tools with Lark or regex grammar formats. When false, grammar-constrained tools fall back to normal function tools.", "default": false }, "supportsMidConvoSystemMessages": { "type": "boolean", "description": "Whether the exact model accepts system or developer messages after the conversation has started. When false, later system messages are folded into the leading system message.", "default": false }, "supportsMidConvoToolAdditions": { "type": "boolean", "description": "Whether system messages can introduce additional tools mid-conversation. Requires supportsMidConvoSystemMessages. The generated catalog enables this for capable models.", "default": false }, "supportsStrictMode": { "type": "boolean", "description": "Whether the provider supports strict tool schemas. Defaults are API-specific." }, "cacheControlFormat": { "type": "string", "const": "anthropic", "description": "Cache control convention for prompt caching. Anthropic applies cache_control markers to the system prompt, last tool definition, and last user, assistant, or tool-result text content." }, "sendSessionAffinityHeaders": { "type": "boolean", "description": "Whether to send session-affinity data from options.sessionId. Defaults are API-specific." }, "sessionAffinityFormat": { "anyOf": [ { "type": "string", "const": "openai" }, { "type": "string", "const": "openai-nosession" }, { "type": "string", "const": "openrouter" } ], "description": "Session-affinity header format. Defaults are API-specific or auto-detected." }, "supportsLongCacheRetention": { "type": "boolean", "description": "Whether the provider supports long prompt cache retention. Defaults are API-specific or auto-detected." }, "vllmPriority": { "type": "number", "description": "vLLM scheduler priority sent as the top-level priority request field. Lower values are handled earlier and the server default is 0. Only meaningful with --scheduling-policy priority. Off by default and not set on the generated catalog." }, "supportsAdditionalTools": { "type": "boolean", "description": "Whether the model supports message-anchored additional_tools input items.", "default": false }, "supportsToolSearch": { "type": "boolean", "description": "Whether the model supports client-executed tool search for transcript-anchored additions.", "default": false }, "supportsExplicitPromptCacheMode": { "type": "boolean", "description": "Whether the model accepts prompt_cache_options. Older OpenAI models reject the parameter.", "default": false }, "supportsMidConvoEffort": { "type": "boolean", "description": "Whether thinking level changes are sent inside the conversation instead of changing the request's effort, so a change keeps the prompt cache. Used by the anthropic-messages and openai-responses APIs.", "default": false }, "supportsMaxOutputTokens": { "type": "boolean", "description": "Whether the provider accepts max_output_tokens. Some Codex-protocol gateways reject it.", "default": true }, "supportsEagerToolInputStreaming": { "type": "boolean", "description": "Whether the provider accepts per-tool eager_input_streaming. When false, the Anthropic provider omits tools[].eager_input_streaming and sends the legacy fine-grained-tool-streaming-2025-05-14 beta header for tool-enabled requests.", "default": true }, "supportsCacheControlOnTools": { "type": "boolean", "description": "Whether the provider supports Anthropic-style cache_control markers on tool definitions. When false, cache_control is omitted from tool parameters. Some Anthropic-compatible providers, such as Fireworks, do not support this field on tools and may reject or ignore it.", "default": true }, "supportsTemperature": { "type": "boolean", "description": "Whether the model accepts the Anthropic temperature request field. Claude Opus 4.7+ rejects non-default values.", "default": true }, "forceAdaptiveThinking": { "type": "boolean", "description": "Whether to force adaptive thinking (thinking.type: adaptive plus output_config.effort) regardless of model ID. Built-in models that require adaptive thinking set this in generated metadata. Custom Anthropic-compatible providers can set this to true for any model whose upstream requires the adaptive format. Set false to opt out on overridden built-in models.", "default": false }, "allowEmptySignature": { "type": "boolean", "description": "Whether to replay empty thinking signatures instead of converting thinking to text.", "default": false }, "supportsStrictTools": { "type": "boolean", "description": "Whether the provider supports Anthropic strict tool schemas. Generated Anthropic models enable it explicitly.", "default": false }, "supportsMidConvoToolChanges": { "type": "boolean", "description": "Whether the exact model accepts mid-conversation tool_addition and tool_removal blocks. Requires supportsMidConvoSystemMessages.", "default": false }, "allowedFallbackModels": { "type": "array", "items": { "type": "object", "required": [ "provider", "model", "cost" ], "properties": { "provider": { "type": "string", "minLength": 1 }, "model": { "type": "string", "minLength": 1 }, "cost": { "$ref": "#/$defs/ModelCost" } }, "description": "An Anthropic server-side refusal fallback model with local pricing metadata." }, "maxItems": 3, "description": "Models Anthropic accepts for server-side refusal fallback, with local pricing metadata for returned fallback responses. When absent or empty, callers must omit fallbacks; Anthropic rejects the field for models with no permitted fallback targets." } }, "additionalProperties": true }, "ThinkingLevelMap": { "type": "object", "properties": { "off": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "minimal": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "low": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "medium": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "high": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "xhigh": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "max": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } } } } }