MusePi

Providers

English 中文

Providers are the model backends musepi can route requests to: Anthropic, OpenAI, Google Gemini, Groq, OpenRouter, Mistral, xAI, local engines like Ollama, hosted gateways, custom models.yml providers, and providers registered by extensions.

A provider is the account or backend namespace, such as anthropic, openai, google, or ollama. A model is a concrete model under that provider, selected as provider/model-id, such as anthropic/claude-opus-4-6. Disabling a provider removes every model under it from selection; if you only want to narrow individual models, use model settings instead.

This page covers how providers become available, how credentials are resolved, the provider/environment-variable map, local engines, disabling providers, and custom providers. For endpoint-specific request, reasoning, tool, stream, usage, and retry constraints, see Provider endpoint constraints. For model selection and the full models.yml schema, see Model and Provider Configuration. For config-file locations and merge precedence, see Settings. For credential storage and login flows in depth, see Secrets and credentials. For the complete environment-variable reference, see Environment variables. For local engine setup, see Local models. For context-file discovery providers, see Context files.

How musepi decides a provider is available

At startup the model registry assembles its catalog from four sources, in order:

  1. The bundled model catalog (every built-in provider and its known models).
  2. Custom provider and model entries from ~/.musepi/agent/models.yml.
  3. Runtime-discovered models for providers that support discovery (local engines and discovery-enabled gateways).
  4. Providers and models registered by extensions.

The registry can hold a model even when it is not currently selectable. A model becomes available only when both conditions hold:

  1. its provider ID is not in the effective disabledProviders list; and
  2. the provider is either keyless (an implicit local provider, or a custom provider with auth: none) or has resolvable credentials.

disabledProviders is checked before credentials. If a provider ID is disabled, no stored key, OAuth session, environment variable, .env entry, or models.yml apiKey will make it selectable — the provider’s models are dropped from availability regardless of credentials. Removing the ID from the effective list restores them.

Keyless local engines are a special case: ollama, llama.cpp, and lm-studio are treated as keyless when no key is configured, so their discovered models are selectable as soon as the engine answers — no login required. See Built-in local engines.

Credentials and precedence

When a provider needs an API key, musepi resolves it in this order (first match wins):

  1. Runtime override: a key supplied for the current process, for example CLI --api-key. Never persisted.
  2. models.yml config key: an apiKey pinned on a custom provider, registered as a config-sourced bearer. This deliberately beats stored OAuth, so a key supplied for a custom baseUrl or gateway is honored instead of forwarding an upstream OAuth token the proxy would reject.
  3. Stored OAuth credential: refreshed when needed; multiple accounts are ranked and rotated automatically. For Anthropic and ChatGPT (Codex), each organization or workspace counts as its own account: one email holding both a Team or Enterprise seat and a personal plan can log in once per subscription (pick the workspace on the browser consent page), and rotation treats them as two accounts.
  4. Login-sourced stored API key: an API-key credential saved by a successful /login.
  5. Provider environment variable: including values loaded from .env files (see the env-var table).
  6. Other stored API key: for example, a broker-migrated key. This is a last resort so an explicit environment variable wins.
  7. models.yml fallback resolver: keys for custom providers not otherwise registered.

Stored credentials live in the auth store at ~/.musepi/agent/agent.db for local auth, or in the configured auth-broker snapshot when running in broker mode. (PI_CODING_AGENT_DIR relocates the ~/.musepi/agent base, and the auth store moves with it.)

OAuth vs API key, and provider-scoped logins

Logins are provider-scoped: authenticating anthropic does not authenticate openai, and each provider tracks its own credentials. A disabled provider stays disabled even with valid stored auth.

Use the interactive slash commands inside a session:

For headless or remote setups backed by a shared auth broker, the CLI exposes musepi auth-broker login <provider> / musepi auth-broker logout (and status, list, import, migrate). See Secrets and credentials for the broker model.

When a model has no credentials, musepi tells you to run /login or set the provider’s environment variable.

Pinning a key in models.yml

A custom provider’s apiKey is resolved as environment-variable-name-or-literal: if the value names an existing environment variable, that variable’s value is used; otherwise the string itself is the key. Prefixing the value with ! runs it as a shell command and uses the trimmed stdout (see Model and Provider Configuration for the full value syntax).

# ~/.musepi/agent/models.yml
providers:
  my-gateway:
    baseUrl: https://gateway.example.com/v1
    api: openai-completions
    apiKey: MY_GATEWAY_API_KEY # reads this env var if set, else literal text
    models:
      - id: claude-sonnet
        name: Claude Sonnet via Gateway
        contextWindow: 200000
        maxTokens: 8192

If authHeader: true is set on a custom provider, the resolved key is injected as an Authorization: Bearer <key> header on every request to that provider.

Environment variables and .env files

Each provider has one or more environment variables that supply a key when no stored credential exists. The table below is the verified provider → variable map; the full catalog is large, so it is split into core and additional providers. OAuth-backed providers can also accept a token variable in addition to (or instead of) an API key.

Core providers

Provider ID Environment variable(s)
anthropic ANTHROPIC_OAUTH_TOKEN, then ANTHROPIC_API_KEY (Foundry mode prefers ANTHROPIC_FOUNDRY_API_KEY when CLAUDE_CODE_USE_FOUNDRY=true)
openai OPENAI_API_KEY
openai-codex OPENAI_CODEX_OAUTH_TOKEN
google GEMINI_API_KEY
google-vertex GOOGLE_CLOUD_API_KEY, or Application Default Credentials (GOOGLE_APPLICATION_CREDENTIALS + GOOGLE_CLOUD_PROJECT + GOOGLE_CLOUD_LOCATION)
groq GROQ_API_KEY
openrouter OPENROUTER_API_KEY
mistral MISTRAL_API_KEY
xai XAI_API_KEY
xai-oauth XAI_OAUTH_TOKEN, then XAI_API_KEY
github-copilot COPILOT_GITHUB_TOKEN
cursor CURSOR_ACCESS_TOKEN
azure AZURE_OPENAI_API_KEY
amazon-bedrock AWS_PROFILE, or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY, or an ECS/IRSA credential chain

Additional hosted providers

Provider ID Environment variable(s)
cerebras CEREBRAS_API_KEY
deepseek DEEPSEEK_API_KEY
siliconflow SILICONFLOW_API_KEY
siliconflow-cn SILICONFLOW_CN_API_KEY
fireworks FIREWORKS_API_KEY
together TOGETHER_API_KEY
nvidia NVIDIA_API_KEY
huggingface HUGGINGFACE_HUB_TOKEN, then HF_TOKEN
moonshot MOONSHOT_API_KEY
nanogpt NANO_GPT_API_KEY
novita NOVITA_API_KEY
venice VENICE_API_KEY
vercel-ai-gateway AI_GATEWAY_API_KEY (also VERCEL_AI_GATEWAY_API_KEY for catalog discovery)
cloudflare-ai-gateway CLOUDFLARE_AI_GATEWAY_API_KEY
litellm LITELLM_API_KEY; optional LITELLM_BASE_URL for the proxy endpoint
kilo KILO_API_KEY
zai ZAI_API_KEY
zenmux ZENMUX_API_KEY
zhipu-coding-plan ZHIPU_API_KEY
umans UMANS_AI_CODING_PLAN_API_KEY
qianfan QIANFAN_API_KEY
qwen-portal QWEN_OAUTH_TOKEN, then QWEN_PORTAL_API_KEY
synthetic SYNTHETIC_API_KEY
minimax MINIMAX_API_KEY
alibaba-coding-plan ALIBABA_CODING_PLAN_API_KEY
aimlapi AIMLAPI_API_KEY
gitlab-duo GITLAB_TOKEN
opencode-zen, opencode-go OPENCODE_API_KEY
firepass FIREPASS_API_KEY
wafer-serverless WAFER_SERVERLESS_API_KEY
xiaomi XIAOMI_API_KEY
ollama-cloud OLLAMA_CLOUD_API_KEY
ollama OLLAMA_API_KEY (optional; local discovery is keyless by default)
lm-studio LM_STUDIO_API_KEY (optional; keyless by default)
llama.cpp LLAMA_CPP_API_KEY (only when the server requires auth)

OAuth-backed providers such as anthropic, github-copilot, cursor, ollama-cloud, qwen-portal, kimi-code, xai-oauth, wafer-serverless, google-gemini-cli, and google-antigravity are normally reached through /login rather than an environment variable. See Environment variables for search-tool and configuration variables not listed here.

.env discovery and precedence

musepi eagerly loads .env files into the process environment before any provider lookup. It reads four files and, for each variable, the first source that defines it wins. Effective precedence, high to low:

  1. The process environment inherited by musepi (already-set variables always win).
  2. <cwd>/.env
  3. ~/.musepi/agent/.env
  4. ~/.musepi/.env
  5. ~/.env

A variable already present in the process environment is never overwritten by a .env file. Among the files, a value set in <cwd>/.env wins over ~/.musepi/agent/.env, which wins over ~/.musepi/.env, which wins over ~/.env. So a shell-exported OPENAI_API_KEY beats every .env file, and a project’s <cwd>/.env beats your home ~/.env.

Project-local .env is the simplest way to make one repository use a project-specific gateway, key, or local endpoint:

# <project>/.env
OPENROUTER_API_KEY=sk-or-...
OLLAMA_BASE_URL=http://127.0.0.1:11434

.env parsing is intentionally minimal:

Built-in local engines

Three local engines are discovered automatically without needing a models.yml entry. Each uses a base URL that can be overridden by an environment variable:

Provider ID Base URL (env override → default) Notes
ollama OLLAMA_BASE_URL, then OLLAMA_HOST (normalized), else http://127.0.0.1:11434 Keyless by default.
llama.cpp LLAMA_CPP_BASE_URL, else http://127.0.0.1:8080 Keyless unless a key is stored for llama.cpp.
lm-studio LM_STUDIO_BASE_URL, else http://127.0.0.1:1234/v1 Keyless by default.

These implicit engines are skipped when:

For installing and running these engines, see Local models.

Disabling model providers

Use the disabledProviders setting to remove a provider’s models from selection:

# ~/.musepi/agent/config.yml or <project>/.musepi/config.yml
disabledProviders:
  - anthropic
  - openai
  - google
  - groq

Provider IDs are matched exactly. Disable google to hide the Google Gemini API provider; the OAuth-backed Google providers google-gemini-cli and google-antigravity are separate IDs and must be disabled individually. Disable ollama, llama.cpp, or lm-studio to stop local discovery for that engine.

disabledProviders applies uniformly to:

Disabling a provider does not delete its stored credentials — re-enable it by removing its ID from the effective list.

Project-specific provider control

Project settings live in <project>/.musepi/config.yml. Use them when one repository must allow or hide a different provider set than your global default:

# <project>/.musepi/config.yml
disabledProviders:
  - openai
  - openrouter

Settings arrays are replaced wholesale by the higher-precedence layer, not merged or appended. If the global file disables three providers and the project file disables one, the project sees only the project list:

# ~/.musepi/agent/config.yml
disabledProviders:
  - anthropic
  - openai
  - google

# <project>/.musepi/config.yml
disabledProviders:
  - groq

Effective result inside the project:

["groq"]

The project array re-enables anthropic, openai, and google for sessions launched from that project. If you want a project to add to the global set, repeat the global IDs in the project file. See Settings for the full precedence chain, including --config overlays and runtime overrides.

Path-scoped disabledProviders

disabledProviders can mix plain string entries (apply everywhere) with path-scoped entries (apply only when the current working directory matches a configured path):

disabledProviders:
  - ollama
  - path: ~/projects/sensitive
    providers:
      - anthropic
      - openai
  - paths:
      - ~/work/client-a
      - ~/work/client-b
    values:
      - openrouter

For the example above:

Path scopes are resolved after the settings merge. Because a higher-precedence layer replaces the whole array, a project-level disabledProviders array drops any scoped entries that only existed in the global array. enabledModels is the only other setting that supports the same path-scoped form. See Settings for details.

Provider IDs vs discovery provider IDs

disabledProviders uses a single shared ID namespace that gates two different subsystems:

Entry type Examples Effect
Model provider ID anthropic, openai, google, groq, openrouter, ollama, my-gateway Removes that provider’s models from availability.
Discovery provider ID native, claude, codex, gemini, agents, github Stops that discovery source from contributing capability items.

Watch the related names. The Google Gemini API models use the model provider ID google; gemini is a discovery provider ID (the source that reads GEMINI.md), not the Google model provider. Use discovery IDs only when you intend to disable an entire config source. See Context files for the discovery-provider side.

Custom providers in models.yml

Custom providers live in ~/.musepi/agent/models.yml under providers:. A provider ID defined there participates in the same selection, credential resolution, and disabledProviders rules as built-in providers.

Minimal OpenAI-compatible provider:

providers:
  my-openai-compatible:
    baseUrl: https://api.example.com/v1
    api: openai-completions
    apiKey: MY_OPENAI_COMPATIBLE_KEY # env-var-name or literal
    models:
      - id: fast-chat
        name: Fast Chat
        contextWindow: 128000
        maxTokens: 8192

Keyless local provider (no credentials required):

providers:
  local-proxy:
    baseUrl: http://127.0.0.1:4000/v1
    api: openai-completions
    auth: none
    models:
      - id: local-model
        name: Local Model
        contextWindow: 32768
        maxTokens: 4096

Discovery-enabled provider (models fetched from the endpoint at runtime):

providers:
  team-proxy:
    baseUrl: https://models.example.com/v1
    apiKey: TEAM_PROXY_API_KEY
    authHeader: true # send Authorization: Bearer <resolved key>
    disableStrictTools: true
    discovery:
      type: proxy

For the full schema, all allowed api values, discovery types, model overrides, and equivalence settings, see Model and Provider Configuration.

To disable a custom provider, list its ID exactly:

disabledProviders:
  - my-openai-compatible
  - team-proxy

Troubleshooting

A provider’s models are not selectable. Confirm the provider has credentials (/login <provider>, an exported environment variable, or a models.yml apiKey) and that its ID is not in the effective disabledProviders list. Remember the rule: not disabled and (keyless or has credentials). Keyless local engines only appear once the engine is actually running and responding.

The wrong key is being used (a stale key from .env). Resolution favors runtime --api-key, then a models.yml config key, stored OAuth, a key saved by /login, environment or .env, other stored API keys, and finally the models.yml fallback resolver. An already-set process environment variable also beats every .env file, and <cwd>/.env beats ~/.env. If an unexpected key wins, check for an exported shell variable and the four .env files in precedence order, and clear the one that should not apply.

A provider still appears even though I disabled it. disabledProviders arrays are replaced, not merged: a project <project>/.musepi/config.yml array fully overrides the global one. Verify the effective list for the directory you are in (path-scoped entries only apply at or under their configured path), and confirm the ID is spelled exactly. Use musepi config get disabledProviders to inspect the merged value (see Settings).

A discovery provider name had no effect on models (or vice-versa). The ID namespace is shared. gemini, codex, claude, native, and agents are discovery-source IDs; the Google model backend is google. Make sure you are disabling the right kind of provider.

A custom models.yml provider does not load. A YAML or schema error makes the registry skip the custom file. Validate the file with musepi models (use musepi models find <substr> to scope it to one provider), confirm each provider has a baseUrl, a valid api, and at least one model entry, and that an implicit local engine is not silently shadowing it (an explicit ollama/lm-studio/llama.cpp entry replaces the built-in discovery for that ID). See Model and Provider Configuration.