Providers and authentication
In Buffaly, an AI Provider generally refers to an LLM provider. A complete model selection is not just a model name. It is a strictly validated 5-part tuple of provider, transport, model, reasoning level, and the authentication route required by that transport.
The 5-Part Provider Tuple
| Term | User-facing meaning | Verified notes |
|---|---|---|
| Provider | The AI family or vendor token (e.g., openai, xai, gemini). | Built-in tokens are defined by ProviderCatalogDefaults; modules can add more. |
| Transport | The execution route used for a provider. | Verified transport tokens include codex_backend, responses_api, and provider_native. |
| Model | The concrete model name available under one provider/transport. | ProviderCatalogService resolves this after validating provider and transport. |
| Reasoning level | A model-scoped reasoning-effort token (low, medium, high). | Validated against each model row; unsupported levels fail explicitly. |
| Authentication | The credential or login route needed by the transport. | OpenAI API keys, Codex auth profiles, and native module credentials are separate concepts. |
Provider identity is not transport
Do not treat OpenAI, Codex, API key, Grok, and Gemini as interchangeable. Buffaly separates the identity of an LLM provider from the route used to call it. Each route can have different model catalogs, tool support, prompt caching, and authentication rules.
OpenAI through Codex backend
Provider-native module
Existing Supported Providers
The source tree contains built-in and verified routes for the following LLM families. Note: Just because a provider is supported by the architecture does not mean it is automatically enabled in your instance. Provider-native modules must be installed and configured.
1. OpenAI & Codex (The Default)
OpenAI via the codex_backend transport is the built-in system default. Omitted provider tokens normalize to openai. It supports standard API Keys via OpenAIFeature.ApiKey OR OAuth/Profile flows via the Codex Auth Feature.
2. Anthropic
Exposed via the anthropic token and provider_native transport. Requires the Anthropic provider module DLLs and an active Anthropic Feature row containing the API key and supported models (e.g., claude-sonnet-4-5).
3. xAI (Grok)
Exposed via the xai token and provider_native transport. Supports standard API keys via the XAI Feature row, or an advanced OAuth 2.0 PKCE flow (detailed below).
4. Google Gemini
Exposed via the gemini token and provider_native transport. Requires the Gemini provider module and Gemini Feature configuration.
OAuth & Authentication Boundaries
Provider credentials belong in SQL-backed feature settings, not in implementation files, wikis, or manifests. Buffaly supports standard API Keys, but two of our existing providers support robust OAuth capabilities:
1. xAI OAuth (Grok)
Current xAI OAuth support uses Buffaly's generic provider-auth profile system. The provider module owns the protocol details, while Buffaly owns the login lifecycle and profile storage.
- Handler discovers endpoints from
https://auth.x.ai/.well-known/openid-configuration. - Generates a PKCE verifier/challenge, state, and nonce.
- User signs in via the browser. Buffaly completes the callback and exchanges the code for tokens.
- The profile is stored under the install's sessions root. Active OAuth profiles override legacy API keys for xAI.
2. Codex Auth Profile (OpenAI)
The Codex Auth Feature uses OAuth-style endpoints, callback settings, and refresh behaviors, distinct from standard OpenAI API keys. If the transport is codex_backend, Buffaly looks here first.
Never paste xAI access tokens, refresh tokens, API keys, authorization codes, or full callback URLs into prompts, tickets, wiki pages, logs, or commits. Use the Settings UI or Feature Rows.
How the provider catalog validates selections
ProviderCatalogService is the absolute boundary for provider selection. The validation behavior is intentionally strict to prevent silent downgrades.
- The requested provider must exist and be enabled.
- The requested transport must exist for that provider and be enabled.
- The requested model must exist for the selected provider/transport.
- The selected reasoning level must be actively supported by that model row.
If selection fails, Buffaly throws an explicit error. Diagnose the entire tuple instead of changing one field at a time until the error disappears.
Troubleshooting Provider Selection
| Symptom | First Checks |
|---|---|
| Provider does not appear in UI | Check ProviderModules.json. Verify the DLL path, catalog source type, and ensure Enabled=true. |
| Provider appears but IsConfigured=false | The module is installed, but credentials are missing. Check the provider's SQL Feature row (e.g., Anthropic Feature) and ensure the JSON settings contract matches. |
| Selection fails to persist | You likely requested a reasoning level (e.g., high) for a model that doesn't declare support for it, or specified the wrong transport. |
| Completion fails (but UI works) | The Web app loaded the catalog DLLs, but the Worker process is missing the completion-executor DLLs. Keep Web and Worker folders aligned. |