AI key resolution
Every chat request in Appbricx has to answer one question: which provider, which key, which model? This page explains the resolution chain the server walks on every request, the three scopes an AI key can live in, and the setup patterns that keep the answer predictable.
The mental model
Appbricx recognises three scopes an AI key can live in. Understanding which scope you are configuring is more important than remembering the full priority chain — the chain exists to make these three scopes compose sensibly.
| Scope | Set where | Applies to |
|---|---|---|
| Workspace default | Workspace Settings → AI | Every project in the workspace, unless a project sets its own override. |
| Per-project override | Project Settings → AI | Just this one project. Clear it to fall back to the workspace default. |
| Platform key | Admin → Plans → Platform AI | Every workspace on the plan that has not set its own key (hosted-AI users). |
Environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY) sit under those three as a last-resort fallback for self-host installs.
Resolution order
For every chat request the server walks the following chain, top down, and stops at the first tier that yields a usable provider. Nothing further down is consulted once a match wins.
| # | Tier | What it means |
|---|---|---|
| 1 | Admin enforcement | If the workspace admin turned on enforce AI in Workspace Settings, that provider and model are used for every request. Nothing else in the chain runs. Individual members cannot override. |
| 2 | Explicit request override | A provider or model picked in the editor’s model switcher, or passed on the request body by an API caller. Wins over any saved default. |
| 3 | User default | A default the current user saved for themselves inside this workspace. Only applies when the pick actually resolves to a usable provider — a stale Copilot reference with no connected account is skipped instead of erroring. |
| 4 | Workspace default | The default set in Workspace Settings → AI. Same “must resolve” guard: an empty Copilot default falls through instead of failing. |
| 5 | Auto-pick | No explicit default set? The resolver picks the most recently added valid BYOK provider in the workspace. DeepSeek is preferred when several are present. |
| 6 | Platform key | Hosted-AI: the key the admin registered under Admin → Plans → Platform AI (or the setup wizard). Read live from platform_config on every request, so rotating the key takes effect on the next chat. |
| 7 | Env fallback | Last resort for self-host: ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY. Only reached when the database has nothing at all. |
The priority chain, at a glance
highest priority
───────────────
1. Admin enforcement (workspace admin locked the choice)
2. Explicit request override (model switcher / request param)
3. User default (per-user, per-workspace)
4. Workspace default (Workspace Settings → AI)
5. Auto-pick BYOK (latest valid; DeepSeek preferred)
6. Platform key (hosted-AI; admin-managed pool)
7. Env fallback (self-host; ANTHROPIC_API_KEY etc.)
───────────────
lowest priorityBYOK track — recommended setup
If you are bringing your own key, the shortest path is a single workspace default. It is the tier every project inherits, and it does not depend on any per-project configuration.
- Open Workspace Settings → AI as a workspace admin.
- Add a provider (Anthropic, OpenAI, Azure OpenAI, DeepSeek, Groq, and more — see Bring your own key).
- Set that provider as the workspace default.
Every project in the workspace now uses that key automatically. Do not touch any per-project setting unless step 4 below applies.
Hosted-AI track
On Appbricx-hosted plans the operator has already registered one or more platform keys. There is nothing for you to configure. Chat just works, and metered usage bills against your plan.
If the admin has registered several provider keys, the resolver picks one automatically. DeepSeek is preferred when present; otherwise selection follows the provider preference order below.
Admin — running multiple platform keys
Operators can register several provider keys under Admin → Plans → Platform AI. Register each one with its provider type, base URL (if non-standard), API key, and an optional default model. The resolver picks the highest-priority valid one on every request. DeepSeek is preferred by default; other providers follow the preference order below.
Rotating a platform key takes effect on the next chat request — the resolver reads from platform_config live rather than from a cached workspace clone. See services/api/src/ai/platform-chat-default.ts.
Environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY) serve as fallbacks when the platform key store is empty. This is the shape most self-host installs run in before an admin has configured anything.
Per-project override — when and how
Reach for a per-project override when this specific project truly needs a different key from the rest of the workspace. Common reasons:
- A client engagement that must be billed to a different provider account.
- A regulated project pinned to a specific region (e.g. Azure OpenAI in a particular tenant).
- Experimenting with a model that is not the workspace-wide default.
To set an override:
- Open the project in the editor.
- Go to Project Settings → AI.
- Pick a provider from the dropdown. The override is now active for this project only.
To revert, clear the override in the same panel. The project falls back to the workspace default on the next chat.
Provider preference order
When several valid providers are eligible — a workspace with multiple BYOK keys, a plan with several admin-managed platform keys, or a mix — the auto-selection order is:
- DeepSeek— preferred when present.
- Anthropic
- OpenAI
- Azure OpenAI
- Groq
- All other providers (whichever is present).
Within the same provider, the resolver prefers the most recently added valid key. See findLatestValidProvider in packages/db/src/queries/ai-settings-providers.ts.
Copilot on Node < 22
GitHub Copilot as a provider requires Node.js 22 or newer to start its SDK. If the server is on Node 20 and Copilot fails to initialise, the resolver now falls through to the next provider in the chain instead of throwing.
In practice: your workspace default is Copilot, the runtime is on Node 20, Copilot cannot start — chat still works because tier 5 (auto-pick) or tier 6 (platform key) takes over. The “resolved” provider reported in devtools tells you which tier answered. Fix the Node version at your leisure to restore the Copilot path.
Debugging
- Which provider answered?Open the editor devtools panel — each chat request logs the resolved
providerSourceandmodelSource. Values you will see:admin_override,user_byok,workspace_byok,auto_personal_byok,auto_workspace_byok,platform_live,platform_default,platform_seeded,github_copilot. - Admin audit log. Every resolution writes an
ai_key_resolvedentry with the workspace id, project id, provider source, and (for admin-managed pools) which platform key was selected. Open Admin → Audit and filter by that event type. - “Why did it pick DeepSeek?” Either the admin registered a DeepSeek platform key, or the workspace has a DeepSeek BYOK key present. DeepSeek wins ties in both pools.
- “My per-project override does nothing.” The admin has probably enabled enforcement in Workspace Settings. Tier 1 shadows tiers 2–7 entirely.
Common shapes
| You want | Do this |
|---|---|
| One key for the whole workspace | Workspace Settings → AI → set default. Do not touch projects. |
| Different key for one project | Set workspace default first, then Project Settings → AI on that one project. |
| Lock everyone to one model | Workspace Settings → AI → enable enforce AI. Tier 1 wins for every request. |
| Hosted-AI, one provider | Admin → Plans → Platform AI → register one key. Users do nothing. |
| Hosted-AI, several providers | Register several under Admin → Plans → Platform AI. Resolver auto-selects; DeepSeek wins ties. |
| Self-host, bootstrap only | Set ANTHROPIC_API_KEY / OPENAI_API_KEY / DEEPSEEK_API_KEYin the env. Move to Admin → Platform AI once you can log in. |
Anti-patterns
- Setting the same key on every project one-by-one instead of at the workspace level. Rotation becomes N updates.
- Enabling admin enforcement and then wondering why per-user defaults have no effect. Enforcement is exclusive by design.
- Leaving stale Copilot defaults with no connected account. The resolver now skips these instead of erroring, but the underlying config is still lying — clear it in Workspace Settings.
- Storing provider API keys in project
secrets.refs.json. BYOK keys are separate from workflow secrets — see Secrets & env.
Where this lives in the code
services/api/src/ai/engine-resolver.ts— the resolution chain described above.services/api/src/ai/platform-chat-default.ts— live read of the admin-managed platform key fromplatform_config.packages/db/src/queries/ai-settings-preferences.ts—getEffectiveAiConfig, which joins workspace and user defaults for tiers 3 and 4.packages/db/src/queries/ai-settings-providers.ts—findLatestValidProvider, which powers tier 5 auto-pick.
Related: Bring your own key · Self-host · Secrets & env