Providers
Providers are the model backends veyyon 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.
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 the embedded tiny-model engineering record (title/memory/auto-thinking local models), see Local tiny models. For context-file discovery providers, see Context files.
When a provider is available
At startup the model registry assembles its catalog from four sources, in order:
- The bundled model catalog (every built-in provider and its known models).
- Custom provider and model entries from
~/.veyyon/profiles/default/agent/models.yml. - Runtime-discovered models for providers that support discovery (local engines and discovery-enabled gateways).
- 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:
- its provider ID is not in the effective
disabledProviderslist; and - 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, veyyon resolves it in this order (first match wins):
- Runtime override: a key supplied for the current process, e.g. CLI
--api-key. Never persisted. models.ymlconfig key: anapiKeypinned on a custom provider, registered as a config-sourced bearer. This deliberately beats stored OAuth, so a key supplied for a custombaseUrl/gateway is honored instead of forwarding an upstream OAuth token the proxy would reject.- Stored API key: an API-key credential saved in the auth store.
- Stored OAuth credential: refreshed when needed; multiple accounts are ranked/rotated automatically. For Anthropic, each organization counts as its own account: one email holding both a Team 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.
- Provider environment variable: including values loaded from
.envfiles (see the env-var table). models.ymlfallback resolver: keys for custom providers not otherwise registered.
Stored credentials live in the auth store at ~/.veyyon/profiles/default/agent/agent.db for local auth (or the active profile’s agent.db), or in the configured auth-broker snapshot when running in broker mode. VEYYON_CODING_AGENT_DIR relocates the entire agent directory, 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:
/login: opens the OAuth/key selector./login <provider>jumps straight to one provider (e.g./login anthropic); for an OAuth flow that needs a pasted callback, run/login <redirect-url>to complete it./logout: opens the provider selector to remove stored credentials.
For headless or remote setups backed by a shared auth broker, the CLI exposes veyyon auth-broker login <provider> / veyyon auth-broker logout (and status, list, import, migrate). See Secrets and credentials for the broker model.
When a model has no credentials, veyyon prints the /login command and 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 matches 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).
# ~/.veyyon/profiles/default/agent/models.yml
providers:
my-gateway:
baseUrl: https://gateway.example.com/v1
api: openai-completions
apiKey: MY_GATEWAY_API_KEY # reads this env var; unset means no key, not a literal
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. Providers reached only through OAuth (/login) or local keyless discovery are covered below the tables instead. 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_BEARER_TOKEN_BEDROCK, or AWS_PROFILE, or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY, or a web-identity (AWS_WEB_IDENTITY_TOKEN_FILE + AWS_ROLE_ARN) / ECS credential chain |
Additional hosted providers
| Provider ID | Environment variable(s) |
|---|---|
cerebras | CEREBRAS_API_KEY |
command-code | CMD_API_KEY, then COMMAND_CODE_API_KEY |
deepseek | DEEPSEEK_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, then KIMI_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 |
minimax-code | MINIMAX_CODE_API_KEY |
minimax-code-cn | MINIMAX_CODE_CN_API_KEY |
baseten | BASETEN_API_KEY |
coreweave | COREWEAVE_API_KEY, then WANDB_API_KEY |
devin | DEVIN_API_KEY |
nous-research | NOUS_API_KEY (headless fallback; prefer /login nous-research) |
gitlab-duo-agent | GITLAB_TOKEN |
sakana | SAKANA_API_KEY, then FUGU_API_KEY |
xiaomi-token-plan-ams | XIAOMI_TOKEN_PLAN_AMS_API_KEY |
xiaomi-token-plan-cn | XIAOMI_TOKEN_PLAN_CN_API_KEY |
xiaomi-token-plan-sgp | XIAOMI_TOKEN_PLAN_SGP_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) |
vllm | VLLM_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, nous-research, xai-oauth, wafer-serverless, google-gemini-cli, and google-antigravity are normally reached through /login rather than an environment variable. Nous Portal stores a durable refresh token and mints short-lived inference access tokens for requests and model discovery; NOUS_API_KEY remains available for explicit headless use.
Command Code uses https://api.commandcode.ai/provider/v1, defaults to moonshotai/Kimi-K2.7-Code, and issues keys at Command Code Provider. Nous Research uses https://inference-api.nousresearch.com/v1 and defaults to the tool-capable anthropic/claude-sonnet-4.6; authenticated discovery adds the current tool-capable chat catalog and excludes embedding, media-generation, and non-tool rows. Nous accepts either sign-in: /login nous-research runs the Portal device flow, and /login nous-research-api-key takes a key pasted from the Portal. Both store one credential under nous-research, so the model list and the account card show a single Nous account either way.
.env discovery and precedence
veyyon eagerly loads .env files into the process environment before any provider lookup. It reads four files and, for each variable, the highest-priority source that defines it wins. Effective precedence, high to low:
- The process environment inherited by
veyyon(already-set variables always win). <cwd>/.env<agentDir>/.env, by default~/.veyyon/profiles/default/agent/.env<configRoot>/.env, by default~/.veyyon/profiles/default/.env~/.env
Both <agentDir> and <configRoot> follow the active profile, so --profile work reads ~/.veyyon/profiles/work/agent/.env and ~/.veyyon/profiles/work/.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 <agentDir>/.env, which wins over <configRoot>/.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.
The order does not depend on which part of veyyon runs first. ~/.env is applied before anything resolves a directory, because a VEYYON_CODING_AGENT_DIR or XDG_CONFIG_HOME set there determines where the other two files even are; the remaining layers are applied once those directories are known, and they override the values ~/.env contributed. Whichever module a program imports, it sees the same result.
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:
- blank lines and lines starting with
#are ignored; - keys must match
[A-Za-z_][A-Za-z0-9_]*(shell-identifier shape): other names are dropped; - values may be wrapped in single or double quotes, which are stripped;
- values containing a NUL byte are dropped.
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:
- a provider with the same ID is already configured in
models.yml(your explicit config wins); or - the provider ID appears in the effective
disabledProviderslist.
Install and run these engines with their own tooling (ollama serve, llama-server, LM Studio); Veyyon discovers a running endpoint automatically via the table above.
Disabling model providers
Use the disabledProviders setting to remove a provider’s models from selection:
# ~/.veyyon/profiles/default/agent/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:
- bundled catalog providers;
- custom
models.ymlproviders; - runtime-discovered provider models;
- extension-registered providers;
- implicit local engines.
Disabling a provider does not delete its stored credentials, re-enable it by removing its ID from the effective list.
Per-project provider control
A repository cannot carry settings: <project>/.veyyon/config.yml is not read. When one repository must allow or hide a different provider set than your profile default, use a path-scoped entry (below) or pass a --config overlay for that run:
$ veyyon --config ./no-openai.yml
Settings arrays are replaced wholesale by the higher-precedence layer, not merged or appended. If the profile file disables three providers and an overlay disables one, that process sees only the overlay list. If you want an overlay to add to the profile set, repeat the profile IDs in the overlay. 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
- Bare string entries always apply.
- A scoped entry applies when the current working directory is the configured path or sits under it.
~expands to the home directory. - Accepted path keys:
path,paths,pathPrefix,pathPrefixes. - Accepted value keys:
providers,values,items.
For the example above:
ollamais disabled everywhere.anthropicandopenaiare additionally disabled under~/projects/sensitive.openrouteris additionally disabled under~/work/client-aand~/work/client-b.
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:
- Model providers: the backends on this page (
anthropic,openai,ollama, a custommodels.ymlID, …). Disabling one removes its models from selection. - Discovery providers: sources of context files, MCP servers, commands, skills, hooks, tools, prompts, and settings. Disabling one stops that source from contributing capability items.
| 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 ~/.veyyon/profiles/default/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; `literal:text` for verbatim text
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, then stored credentials, then environment/.env. 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 --config overlay array fully overrides the profile 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 veyyon 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 veyyon models (use veyyon 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.