A model provider is a named record on an account: a type, a base URL, and references to encrypted secrets. Agents name a provider and a model; the runtime maps both onto the Pi SDK at execution time.
type ModelProviderConfig = {
type: string
modelDefaults?: Record<string, unknown>
secretRefs?: Record<string, string>
baseUrl?: string
authMode?: 'api-key' | 'subscription'
}The provider table
PROVIDER_SPECS (agents/src/api-service.ts:6689-6756) is the whole registry — adding a provider type is usually one entry here plus a matching entry in the desktop's provider-registry.ts.
Type | Pi API | Default base URL | Custom URL | Key required |
|---|---|---|---|---|
| openai-completions¹ |
| no | yes |
| anthropic-messages |
| no | yes |
| google-generative-ai |
| no | yes |
| openai-completions |
| no | yes |
| openai-completions |
| no | yes |
| openai-completions |
| no | yes |
| openai-completions |
| no | yes |
| openai-completions |
| yes | no |
| openai-completions | — | yes | no |
¹ openai reroutes to openai-responses when the resolved model is reasoning-flagged (:6923).
For pinned providers the spec's default base URL always wins even if a baseUrl was stored; only ollama and custom honor an override (resolveProviderBaseUrl, :6804-6809). Model lists come from live endpoints: GET /models with a bearer token for OpenAI-compatible, x-api-key plus anthropic-version: 2023-06-01 for Anthropic, and a supportedGenerationMethods filter for Google.
Secrets
API keys live in the secrets table, encrypted with AES-256-GCM. The key is 32 random bytes generated once and stored in server_config under secret_encryption_key_v1; each write gets a fresh 12-byte nonce, and the stored ciphertext is nonce || encrypted (encryptSecret, agents/src/api-service.ts:9915-9952).
Two honest caveats: the encryption key sits in the same SQLite database it protects — there is no OS keychain or KMS integration — and there is no general secret-deletion action, though deleting a provider removes its key. Both are tracked in Security.
Nothing plaintext ever leaves: RedactedModelProvider exposes hasSecrets: boolean, and RedactedSecret carries a literal hasValue: true rather than any bytes.
Subscription sign-in (OAuth)
Beyond API keys, a provider can use authMode: 'subscription' — today only OpenAI ("Sign in with ChatGPT"). The flow lives in agents/src/provider-oauth.ts and is deliberately headless: the server has no localhost of its own to catch a redirect, so loginOpenAICodexHeadless runs PKCE without a loopback listener and the user pastes the code back through SubmitProviderOAuthCode.
Execution then reroutes to the openai-codex Pi provider against https://chatgpt.com/backend-api, with its own model catalog (gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4). Refreshed tokens are persisted back through the encrypted secret store by PersistedOAuthBackend. When a token goes bad the secret is flagged needsReauth, surfacing as authStatus: 'needs-login' in the UI.
The whole feature is gated by the operator flag SEED_AGENTS_SUBSCRIPTION_AUTH; with it off, StartProviderOAuth returns 403.
Reasoning levels
ReasoningLevel is minimal | low | medium | high | xhigh. What each model accepts is genuinely inconsistent, and the file header (agents/protocol/src/reasoning.ts:1-8) explains why the table is hand-verified: providers gate levels per model generation — e.g. OpenAI's gpt-5 family accepts minimal but not none, while gpt-5.1+ accepts none but not minimal.
Family | Levels | When unset |
|---|---|---|
OpenAI gpt-5 / gpt-5-mini | minimal, low, medium, high | provider default (cannot disable) |
OpenAI gpt-5.1 | low, medium, high | off ( |
OpenAI gpt-5.2+ (5.4, 5.6) | low, medium, high, xhigh | off |
OpenAI o-series (o1/o3/o4) | low, medium, high | provider default |
Anthropic claude-3-7+ | minimal, low, medium, high | off |
Google gemini-2.5+ | minimal, low, medium, high | off, except |
gpt-5-chat* exposes no reasoning control at all.
One footgun to know about: provider.modelDefaults is shallow-merged over the Pi-generated payload, so a stray reasoning key there will clobber the level the agent asked for.
Related
Agents and Grants — who uses a provider
Security — secret handling and gaps
Protocol — the actions that manage providers
Operations — the flags that enable them
Do you like what you are reading? Subscribe to receive updates.
Unsubscribe anytime