AI Providers¶
Doable supports 60+ AI providers via two paths: bring your own key (BYOK) or use platform-managed credentials via the Provider Bridge. Pick at least one path; the chat agent is dormant without a configured provider.
The full provider catalog is defined in packages/shared/src/ai/provider-catalog.ts.
Bring your own key¶
With BYOK, you supply API keys directly, either as server environment variables (global default) or per-workspace in the UI.
Per-workspace overrides are configured from Workspace Settings โ AI โ Providers. The environment variables below are the global defaults the API falls back to.
Anthropic (Claude)¶
Recommended for highest-quality code generation and longest context windows.
Models: Claude Opus 4, Claude Sonnet 4, Claude Haiku 4.5
Capabilities: Streaming, tool calling, vision, extended thinking
OpenAI¶
Models: GPT-4.1, GPT-4o, o3, o4-mini
Capabilities: Streaming, tool calling, vision
Google AI Studio (Gemini)¶
Models: Gemini 2.5 Pro, Gemini 2.5 Flash
Capabilities: Streaming, tool calling, vision
Azure OpenAI¶
AZURE_OPENAI_API_KEY=...
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
AZURE_OPENAI_DEPLOYMENT=your-deployment-name
Models: Your deployed models (GPT-4.1, GPT-4o, etc.)
Capabilities: Streaming, tool calling, vision
AWS Bedrock¶
Models: Claude, Llama, custom models via Bedrock
Capabilities: Streaming, tool calling, vision
Google Vertex AI¶
Models: Gemini, Claude, custom models
Capabilities: Streaming, tool calling, vision
GitHub Copilot SDK¶
The most powerful option (the same agent that powers GitHub Copilot Chat), but requires a separately installed CLI.
Option A: local CLI
- Install the CLI: see the Copilot SDK README.
- Authenticate it once:
copilot auth login. - Set the path:
Doable spawns a subprocess per session.
Option B: remote CLI server
If you want one shared Copilot CLI server (useful for scaling), run copilot --server somewhere and point Doable at it:
Pick a default model
Available models depend on the user's Copilot subscription. Doable surfaces the full list per session.
"Bring your own GitHub Copilot" flow
If a workspace member has a personal Copilot subscription, they can connect it from Settings โ AI โ GitHub Copilot. Doable runs the OAuth flow at GITHUB_COPILOT_REDIRECT_URI and stores an encrypted token. The agent then uses their Copilot quota, not yours. Implementation lives in services/api/src/routes/auth/ and services/api/src/ai/providers/copilot-manager.ts.
Personal vs workspace scope¶
Doable distinguishes workspace-scoped AI accounts (shared across every member) from personal-scoped accounts (visible only to the user who connected them). The split was introduced in migration 072_ai_personal_scope.sql and applies to both github_copilot_accounts and ai_providers.
What changed in migration 072¶
- Both tables gained a
scope ai_account_scopecolumn ('workspace' | 'user') and anowner_user_id uuidcolumn. A CHECK constraint enforces that personal rows haveowner_user_idset and workspace rows have itNULL. - The old workspace-wide UNIQUE on
(workspace_id, github_login)was replaced by two partial uniques:gca_workspace_login_unique(scope = workspace) andgca_user_login_unique(scope = user, scoped to the owning user). Two different users can each connect the same GitHub login as a personal Copilot account in the same workspace; a single user cannot connect the same login twice. - The
enforce_workspace_default_scope()trigger blocksworkspace_ai_settingsfrom pointing at a personal row for any ofdefault,suggestion, orenforced(account or provider). If you try to set a personal row as the workspace default, the INSERT or UPDATE raises an exception. - The
enforce_uap_account_ownership()trigger blocks a user from referencing another user's personal account or provider viauser_ai_preferences. Workspace-scoped rows remain referenceable by anyone in the workspace. - RLS policies (
gca_scope_visibilityandai_providers_scope_visibility) provide defense in depth: workspace rows are visible to workspace members and mutable by admins; personal rows are visible and mutable only by their owning user.
What this means in the UI¶
- The
/ai-settingspage splits its lists into a Personal section (the current user'sscope='user'rows) and a Workspace section (scope='workspace'rows). Personal rows are not shown to anyone else, including workspace admins. - The setup wizard's Copilot tile passes
scope=workspacewhen an admin connects an account during first-time setup (seeapps/web/src/app/setup/steps/Step2AIProvider.tsx); the resulting account is shared, not personal. - Workspace defaults, suggestion defaults, and enforced choices can only point at workspace-scoped rows. If an admin wants to enforce a model for the whole workspace, that model's account or provider must live at workspace scope.
Admin invariant¶
An admin or owner cannot see other users' personal rows, full stop. The gca_scope_visibility policy makes the visibility check scope = 'user' AND owner_user_id = doable_current_user_id() for personal rows; an admin running the same query observes only their own personal rows plus the workspace pool. This is intentional: the migration's header note is explicit that "non-admins couldn't add their own [accounts] before; they could only pick from the admin-curated pool", and the fix should not flip the inverse asymmetry into existence.
If you need to recover access to a personal row that an ex-user left behind, the only legitimate path is a direct SQL operation by a platform admin against the database, with audit logging; the API does not expose a "view all personal rows" endpoint.
Platform-managed (Provider Bridge)¶
With the Provider Bridge, a platform admin loads API keys once for the whole organisation. Users pick a model from the provider picker without ever entering a key themselves.
See Provider Bridge for the full setup guide, security model, and user experience details.
Supported providers¶
Specialized cloud providers¶
High-performance inference or specialized models:
| Provider | Env Variable | Notable Models |
|---|---|---|
| Groq | GROQ_API_KEY |
Llama 3, Mixtral (ultra-fast inference) |
| Mistral AI | MISTRAL_API_KEY |
Mistral Large, Codestral |
| Cohere | COHERE_API_KEY |
Command R+ |
| xAI (Grok) | XAI_API_KEY |
Grok-2 |
| DeepSeek | DEEPSEEK_API_KEY |
DeepSeek V3, DeepSeek Coder |
| Perplexity | PERPLEXITY_API_KEY |
Sonar Pro (web-grounded) |
| SambaNova | SAMBANOVA_API_KEY |
Fast Llama inference |
| Novita AI | NOVITA_API_KEY |
Various open models |
| PPIO | PPIO_API_KEY |
GPU cloud inference |
All specialized providers support streaming and tool calling.
Aggregators (multi-model routers)¶
Access hundreds of models through a single API key:
| Provider | Env Variable | Description |
|---|---|---|
| OpenRouter | OPENROUTER_API_KEY |
200+ models from all providers |
| Together AI | TOGETHER_API_KEY |
Open-source model hosting |
| Fireworks AI | FIREWORKS_API_KEY |
Fast open-model inference |
| Unify AI | UNIFY_API_KEY |
Intelligent model routing |
| DeepInfra | DEEPINFRA_API_KEY |
Serverless GPU inference |
Tip
OpenRouter is a great choice if you want access to models from every provider without managing multiple API keys. Set OPENROUTER_API_KEY and your users can pick from Claude, GPT-4, Gemini, Llama, and more, all from one account.
Regional & emerging providers¶
| Provider | Region | Env Variable |
|---|---|---|
| Moonshot (Kimi) | China | MOONSHOT_API_KEY |
| DashScope (Qwen) | China | DASHSCOPE_API_KEY |
| Zhipu (GLM) | China | ZHIPU_API_KEY |
| Baidu Qianfan | China | QIANFAN_API_KEY |
| Volcengine (Doubao) | China | VOLCENGINE_API_KEY |
| MiniMax | China | MINIMAX_API_KEY |
| StepFun | China | STEPFUN_API_KEY |
| 01.AI (Yi) | China | YI_API_KEY |
| Tencent Hunyuan | China | HUNYUAN_API_KEY |
| Cerebras | US | CEREBRAS_API_KEY |
| AI21 Labs | US | AI21_API_KEY |
| Hyperbolic | US | HYPERBOLIC_API_KEY |
Infrastructure providers¶
Cloud GPU and inference platforms:
| Provider | Env Variable |
|---|---|
| NVIDIA NIM | NVIDIA_API_KEY |
| Cloudflare Workers AI | CLOUDFLARE_API_KEY |
| Nebius | NEBIUS_API_KEY |
| Scaleway | SCALEWAY_API_KEY |
| Infermatic | INFERMATIC_API_KEY |
| Lepton AI | LEPTON_API_KEY |
| OVHcloud | OVH_API_KEY |
Local & self-hosted models¶
Run models on your own hardware with zero API costs. All local providers use the OpenAI-compatible endpoint format:
# Point Doable at your local model server
OPENAI_BASE_URL=http://localhost:11434/v1
OPENAI_API_KEY=not-needed
Primary local engines
| Engine | Default Port | Setup |
|---|---|---|
| Ollama | 11434 | ollama serve then ollama pull llama3 |
| LM Studio | 1234 | Download app, load model, start server |
| vLLM | 8000 | vllm serve model-name |
| llama.cpp | 8080 | ./llama-server -m model.gguf |
| Jan | 1337 | Download app, start local API |
| LocalAI | 8080 | Docker container with model gallery |
| GPT4All | 4891 | Desktop app with local server mode |
Additional self-hosted options
| Engine | Notes |
|---|---|
| text-generation-webui | Popular Gradio UI with API mode |
| KoboldCpp | GGUF models with OpenAI-compatible API |
| TGI (Text Generation Inference) | Hugging Face's production serving |
| TabbyML | Code completion focused |
| llamafile | Single-file executable models |
| Cortex | Local AI platform |
| LMDeploy | High-throughput serving |
| SGLang | Fast structured generation |
| TabbyAPI | ExLlamaV2 backend |
| MLC LLM | Universal deployment |
| Aphrodite | vLLM fork with extras |
Local model frontends
- Msty: Desktop app for managing local models
- Open WebUI: Web interface (Docker-based)
- LibreChat: Self-hosted ChatGPT-like interface
Model discovery
Doable auto-discovers available models by querying GET /v1/models on the configured endpoint. If that fails, it falls back to a chat completions ping to verify connectivity.
OpenAI-compatible endpoints¶
Any server that implements the OpenAI chat completions API (POST /v1/chat/completions) works with Doable:
This covers vLLM, llama.cpp, TGI, LM Studio, Ollama, and dozens of other servers.
Per-workspace overrides¶
Stored in workspaces.ai_settings (JSONB). Edit from Workspace Settings โ AI. The relevant tables:
ai_providers: provider configs with encrypted API keys at workspace scope.ai_provider_models: cached model list per provider.user_ai_preferences: personal model preferences.mode_tool_config: which tools each mode can use.
The encryption key for stored credentials is ENCRYPTION_KEY from your env.
Routing & fallback¶
If multiple providers are configured, the engine resolver (services/api/src/ai/engine-resolver.ts) picks based on:
- Explicit per-message override (the user picked a model in the UI).
- Workspace default model.
- Global default (env var).
- First-available healthy provider.
If a provider call fails (rate limit, 5xx), the resolver retries the next provider in the chain.
Cost control¶
- Credit limits per user / per session, configured in Workspace Settings โ AI โ Limits.
- Model allow-list to restrict expensive models to admins.
- Token budgets: automatic context compaction kicks in well before the model's hard limit (
session.compaction_start/session.compaction_completeevents).
Verifying it works¶
Sign in, create a project, and send the message "What's 2+2?". You should see streaming text within a second or two. If you see "No AI provider configured":
- Confirm the env var is set in the API environment (not just the shell).
- Check the API logs:
docker compose logs apiorjournalctl -u doable -e. - Verify the workspace's AI settings haven't disabled all providers.
Next: Provider Bridge ยท How docore works.