piagent_
← ~/guides

Providers and Models

Last updated: Aug 12, 2026

$ pi –providers

TL;DR. Pi ships with 40+ built-in providers ranging from subscription OAuth (Claude Pro, ChatGPT Plus, GitHub Copilot, OpenRouter, Kimi Code, Radius) to API-key gateways (Anthropic, OpenAI, Google Gemini, Bedrock, llama.cpp, Baseten, and dozens of regional ones). Pick one with /login (OAuth) or by setting the matching env var or auth.json entry; switch the active model at runtime with /model or Ctrl+P; customize the catalog with ~/.pi/agent/models.json. Two features worth knowing about: pricing tiers (v0.80.6) for accurate long-context billing and constrained sampling (v0.82.0) for guaranteed-shape tool output. Scripts can read the active model from PI_PROVIDER and PI_MODEL rather than inferring it from the system prompt.

The choice of provider is mostly about which model you want to use and which authentication you have on hand. Once a single provider is authenticated, switching models within it is /model or Ctrl+P; switching providers is /login again, or pi --provider <name> --model <pattern> at the CLI.

Built-in providers

The provider list combines subscription OAuth and API-key entry points. Pick whichever matches your auth setup.

Provider Auth Notes
Anthropic ANTHROPIC_API_KEY or /login (Claude Pro/Max subscription) First-party; uses x-api-key by default. v0.82.1 added ANTHROPIC_AUTH_TOKEN for Anthropic-compatible gateways that expect Authorization: Bearer.
OpenAI OPENAI_API_KEY or /login (ChatGPT Plus/Pro Codex subscription) Includes OpenAI Codex Responses API for the subscription path.
Google Gemini / Vertex AI GEMINI_API_KEY (or ADC for Vertex) Vertex uses gcloud auth application-default login plus GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION.
Amazon Bedrock AWS_BEARER_TOKEN_BEDROCK (or IAM profile / IRSA) Optional AWS_REGION (default us-east-1); proxy support via AWS_ENDPOINT_URL_BEDROCK_RUNTIME.
GitHub Copilot /login (github.com or GitHub Enterprise Server) Subscription path; works in any Forge-compatible pipeline.
OpenRouter /login openrouter (PKCE) or OPENROUTER_API_KEY v0.83.0 added headless SSH sign-in for OpenRouter specifically.
Kimi Code /login kimi-coding OAuth subscription added in v0.82.0.
xAI (Grok) /login xai (X subscription) or XAI_API_KEY v0.80.8 added device-code sign-in for xAI.
Radius /login radius OAuth tokens; gateway catalog cached in models-store.json.
Baseten BASETEN_API_KEY Built-in provider added in v0.84.0.
llama.cpp LLAMA_BASE_URL (+ optional LLAMA_API_KEY) Local router; added in v0.81.0. Manage with /llama.
Qwen Token Plan QWEN_TOKEN_PLAN_API_KEY (+ China variant) Individual subscription path added in v0.84.1.
Cloudflare AI Gateway / Workers AI CLOUDFLARE_API_KEY (+ CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_GATEWAY_ID) Four auth modes; unified billing or stored BYOK preferred.
ZAI Coding Plan (Global / China) ZAI_API_KEY / ZAI_CODING_CN_API_KEY
Xiaomi MiMo XIAOMI_API_KEY
Xiaomi MiMo Token Plan XIAOMI_TOKEN_PLAN_*_API_KEY (China / Amsterdam / Singapore) Token-plan subscription variants
Plus OpenCode Zen/Go, Hugging Face, Fireworks, Together, Groq, Cerebras, Mistral, NVIDIA NIM, DeepSeek, Moonshotai, MiniMax each has its own env var See Providers for the full list.

The auth file at ~/.pi/agent/auth.json is created with 0600 permissions and takes priority over matching environment variables. Within auth.json, the key field supports shell commands (!command, executed on read with stdout cached for the process lifetime), environment interpolation ($VAR / ${VAR}, with $$ for literal $ and $! for literal !), and literal strings.

Switching the active model

Three surfaces for the same action:

  • /model opens the interactive model selector. It reloads ~/.pi/agent/models.json each time and triggers a background catalog refresh for configured providers (added in v0.80.8). It is the cheapest way to switch between models you’ve already authenticated.
  • Ctrl+P cycles to the next model in the enabledModels set. Shift+Ctrl+P cycles backward. Ctrl+L opens the model selector directly. Shift+Tab cycles the thinking level.
  • CLI flags: --provider <name>, --model <pattern> (accepts exact id, glob, provider/id, and the :thinking shorthand like sonnet:high or openai/gpt-4o), --models <patterns> for the cycling set, --list-models [search] to print available models, --thinking <level> for off | minimal | low | medium | high | xhigh | max.

The model pattern syntax is globs. claude-*, gpt-4o, gemini-2* all work. Bare exact IDs that match multiple providers used to silently pick the first catalog entry; v0.84.0 changed this so they prefer the sole authenticated provider or emit a clear ambiguity error.

If a model pattern is not in enabledModels, it is hidden from Ctrl+P cycling but still selectable from /model. Use --models 'claude-*,gpt-4o' at the CLI, or set enabledModels in ~/.pi/agent/settings.json (project .pi/settings.json overrides global; nested objects merge).

Custom models and provider overrides

~/.pi/agent/models.json is the customization layer. It reloads on every /model open, so changes take effect mid-session without a restart.

The top-level shape is { "providers": { ... } }. For each provider:

{
  "baseUrl": "https://my-proxy.example.com/v1",
  "api": "openai-completions",
  "apiKey": "$MY_PROXY_KEY",
  "headers": { "X-Org": "team-alpha" },
  "models": [
    { "id": "my-custom-gpt", "name": "Custom GPT", "contextWindow": 200000, "maxTokens": 8192 }
  ],
  "modelOverrides": {
    "claude-sonnet-4-20250514": { "name": "Sonnet (internal)", "maxTokens": 16384 }
  }
}

apiKey and headers values support the same resolution as auth.json keys: $VAR, ${VAR}, !command, $$, $!, and literals. The model id is what pi sends to the API; name is the display label and affects --model pattern matching.

Built-in providers can be overridden — for example, to point Anthropic at a corporate proxy:

{ "providers": { "anthropic": { "baseUrl": "https://my-proxy.example.com/v1" } } }

All built-in models remain available. Existing OAuth or API-key auth continues to work. The merge semantics are: built-in models are kept, custom models are upserted by id within the provider, matching ids replace built-ins, new ids are added alongside built-ins.

modelOverrides applies to built-in provider models (and matching extension-registered provider models). Unknown model ids are silently ignored. Overrideable fields: name, reasoning, thinkingLevelMap, input, cost (partial), contextWindow, maxTokens, samplingParams (merged per key), headers, compat.

Pricing tiers (v0.80.6)

For models with long-context rates that differ from short-context rates (Anthropic Claude, OpenAI GPT-5.6, etc.), pricing tiers give you accurate cost accounting across the boundary:

{
  "cost": {
    "input": 5,
    "output": 30,
    "cacheRead": 0.5,
    "cacheWrite": 6.25,
    "tiers": [
      { "inputTokensAbove": 272000, "input": 10, "output": 45, "cacheRead": 1, "cacheWrite": 12.5 }
    ]
  }
}

A tier supplies a complete alternate rate set and applies to the full request once total input usage (input + cacheRead + cacheWrite) exceeds inputTokensAbove. When multiple tiers match, the highest threshold wins. The tier threshold is total input tokens, not just uncached input — read cache hits and write cache hits all count.

Constrained sampling (v0.82.0)

If you write tools that need guaranteed-shape JSON output, opt into provider-side constrained sampling rather than relying on retries:

{
  "name": "apply_patch",
  "strict": "require",
  "parameters": Type.Object({ "path": Type.String(), "patch": Type.String() })
}

strict: "prefer" asks the provider to enforce the schema when supported and falls back to normal tool calling otherwise. strict: "require" fails the request when the active provider/model cannot honor it — pick this when retrying on shape failure is more expensive than failing the call outright. constrainedSampling: false explicitly opts out, behaving like omitting the field.

The capability is model-gated, not provider-gated: Anthropic, supported Amazon Bedrock Converse models, Mistral, Gemini 3 (via Google Generative AI and Vertex), and OpenAI Chat Completions / Responses with strict-JSON-schema. OpenAI also supports Lark and regex grammar variants via custom tools; if you supply both, Lark is preferred over regex. Earlier Gemini versions fall back for strict: "prefer" and reject strict: "require" outright, so model capability metadata decides the path.

For the built-in default tools (read, bash, edit, write), constrained sampling is currently gated behind PI_EXPERIMENTAL=1. Once stable, this will mean retries and shape failures for those tools become rarer — for now, opt in only on tools you author yourself.

Reading the active model from a script

Two environment variables are exposed in every shell spawned by a tool:

  • PI_PROVIDER — currently selected model provider
  • PI_MODEL — currently selected model id

Both reflect pi’s selection, not whatever upstream router a provider might silently redirect to. When a tool or script asks which model is running, inspect these two variables rather than inferring the answer from the system prompt, since the prompt is constructed from them and can lag behind a recent /model switch.

PI_REASONING_LEVEL reports the current effective thinking level: off | minimal | low | medium | high | xhigh | max. PI_CACHE_RETENTION controls cache retention policy. PI_OFFLINE=1 disables startup network operations including catalog refresh and update checks — useful in air-gapped or low-bandwidth environments.

Catalog freshness and offline use

Built-in catalogs ship with the binary and serve as the baseline. Configured providers may refresh newer catalogs and cache them in ~/.pi/agent/models-store.json for offline use. /model triggers a background refresh each time it opens. To force an immediate refresh, run pi update --models. To disable refresh entirely, set PI_OFFLINE=1.

Concurrent models-store.json reads used to form a file-lock convoy at startup (v0.84.0 fix). If you are debugging stale catalog issues, pi update --models is the cleanest reset; deleting ~/.pi/agent/models-store.json is the nuclear option that forces a full rebuild from built-ins.

When to write your own model vs. override

A common decision point: do you need a new model in models.json, or is a modelOverrides block on a built-in sufficient? Override the built-in when the new model is a repackaged version of one that already exists — a proxy endpoint, a fine-tune, a regional variant. Add a new model when the provider or model is genuinely new and pi would not have it without the file.

For an Ollama, LM Studio, or other local/keyless server, models.json is required: pi will not show a model in /model without an apiKey field, even a dummy one. Add "apiKey": "ollama" (or any non-empty placeholder) and the model appears.

A short worked example: Anthropic via corporate proxy

Suppose you want all Anthropic traffic to route through a corporate proxy that adds authentication headers. Drop the following into ~/.pi/agent/models.json:

{
  "providers": {
    "anthropic": {
      "baseUrl": "https://anthropic-proxy.internal/v1",
      "headers": { "X-Corp-Tenant": "team-alpha" }
    }
  }
}

Built-in Anthropic models — every Claude variant pi ships with — stay available. pi --provider anthropic --model claude-sonnet-4-20250514 now hits the proxy. Auth.json’s ANTHROPIC_API_KEY continues to work; the proxy is expected to trust the same key. If you want to also rename the displayed model to disambiguate internal deployments, add a modelOverrides block:

{
  "providers": {
    "anthropic": {
      "baseUrl": "https://anthropic-proxy.internal/v1",
      "headers": { "X-Corp-Tenant": "team-alpha" }
    }
  },
  "modelOverrides": {
    "claude-sonnet-4-20250514": { "name": "Sonnet (internal)" }
  }
}

The footer and status bar will read “Sonnet (internal)” but the API still sees claude-sonnet-4-20250514. No restart, no schema migration.

Further reading

  • Providers — full provider list and authentication paths
  • Models~/.pi/agent/models.json schema, pricing tiers, sampling params, modelOverrides
  • Custom providers — extension-side pi.registerProvider for OAuth/SSO flows
  • Usage — slash commands (/model, /scoped-models) and CLI flags (--model, --list-models, --provider, --thinking)
  • SettingsenabledModels, defaultProvider, defaultModel, defaultThinkingLevel
  • KeybindingsCtrl+P/Shift+Ctrl+P/Ctrl+L model cycling
  • llama.cpp — local router setup, /llama command
  • Environment variablesPI_PROVIDER, PI_MODEL, PI_REASONING_LEVEL, PI_OFFLINE
  • Packagespi update --models to force catalog refresh
  • packages/ai/README.md — constrained-sampling schema reference