Skip to content

LLM Providers

Nine provider slots. Switching is a settings change; the graph is provider-agnostic.

ProviderLangChain wrapperDefault modelNotes
AnthropicChatAnthropicclaude-sonnet-5Native SDK
OpenAIChatOpenAIgpt-4.1Native SDK; openai.reasoningEffort for o-series/reasoning models
Google GeminiChatGoogleGenerativeAIgemini-2.5-flashNative SDK
GroqChatGroqopenai/gpt-oss-120bNative SDK
xAI GrokChatOpenAImodel per grok.modelOpenAI-compatible, base URL x.ai
DeepSeekChatOpenAIdeepseek-v4-flashOpenAI-compatible
QwenChatOpenAIqwen-maxOpenAI-compatible (DashScope)
GLM (Zhipu AI)ChatOpenAIglm-4.6OpenAI-compatible
LocalChatOpenAIqwen3-coderOpenAI-compatible localhost — Ollama, LM Studio, Docker, OpenRouter

Anything that speaks OpenAI’s API works via the Local slot — set local.baseUrl to point at it.

Model defaults are generated from a single source of truth (scripts/model-config.json → package.json via npm run sync:models), so the values above track the shipped defaults.

Each provider’s {provider}.model setting picks the model. You don’t have to edit settings by hand: the in-chat model picker lists a curated catalog per provider, badged with tool-calling and thinking/reasoning support and a recommended pick, and writes your choice to that provider’s .model setting. Switching model is a one-click change; switching provider is generativeAi.option.

On xAI Grok: it’s a selectable provider option (generativeAi.option: "XGrok") and key resolution routes it to https://api.x.ai/, but under the hood the canonical PROVIDER_REGISTRY aliases Grok to the Anthropic webview provider rather than giving it a first-class agent-mode entry. Treat the other eight slots as the fully independent ones.

sequenceDiagram participant Settings participant KM as getAPIKeyAndModel() participant SS as SecretStorage participant Proxy as CredentialProxy participant BC as buildChatModel() Settings->>KM: generativeAi.option = "Anthropic" KM->>SS: Check OS keychain alt Found SS-->>KM: apiKey else Miss KM->>Settings: settings.json fallback end KM->>KM: Reject placeholder keys<br/>("apiKey", "YOUR_API_KEY_HERE") opt Proxy enabled KM->>Proxy: Route via localhost proxy end KM-->>BC: {apiKey, model, baseUrl?, proxyToken?} BC-->>Settings: LangChain ChatModel

Resolution order: SecretStorage (keychain) → settings.json → credential-proxy indirection if enabled. Placeholder strings ("apiKey", "YOUR_API_KEY_HERE", "not-needed") are rejected before the SDK sees them.

ModeFactoryOutput
AgentbuildChatModel() → LangChain wrapperFed into the deepagents pipeline via AgentFactory
Inline completionCompletionProviderFactory.getProvider()Returns ICodeCompleter — GroqLLM, QwenLLM, GeminiLLM, LocalLLM

ProviderFailoverService monitors provider health, classifies errors, and switches to a backup on failure.

Error classes:

ReasonTriggersCooldown
authHTTP 401, 40310 min
rate_limitHTTP 4291 min
billingBilling / quota errors30 min
timeoutRequest timeout30 s
overloadedHTTP 503, 5292 min
model_not_foundHTTP 4041 hr
formatSchema / format errors—
unknownEverything else—

Health state machine: healthy → degraded → down → healthy. A probe recovery attempt fires 30 s before cooldown expires, restoring the provider without waiting out the full timer.

Failover resolution: resolveProvider(primary) checks the primary → walks candidate list respecting cooldowns → returns first with valid creds. The response carries an isFallback flag so callers know a switch happened. Emits provider_switch, health_update, probe_recovery events.

Settings:

SettingDefaultPurpose
codebuddy.failover.enabledtrueEnable automatic failover
codebuddy.failover.providers[]Ordered fallback list; empty = auto-detect from configured keys

CostTrackingService records per-provider token usage against per-model pricing tables (30+ models, separate input / output / cache-read / cache-creation rates). See Cost Tracking.

Full setting list at Settings Reference. Common shape:

SettingPurpose
generativeAi.optionActive provider — Anthropic, OpenAI, Gemini, Groq, XGrok, Deepseek, Qwen, GLM, Local
{provider}.apiKeyAPI key (typically anthropic.apiKey, openai.apiKey, google.gemini.apiKeys, etc.)
{provider}.modelModel name for that provider
local.baseUrlEndpoint for the Local slot