Provider detection
How `@pleach/core/quickstart` resolves an env var to a provider — priority order, overrides, custom aliases.
The createPleachRoute() handler from @pleach/core/quickstart
auto-detects which provider to use based on which env var you set.
This page documents the resolution matrix, the locked default
priority, and how to override it.
The resolution matrix
The four cases the regression-lock test at
packages/core/test/quickstart/providerDetection.test.mjs enforces:
OPENROUTER_API_KEY | ANTHROPIC_API_KEY | detectProvider() returns |
|---|---|---|
| set | unset | "openrouter" |
| unset | set | "anthropic" |
| set | set | "anthropic" (alphabetical) |
| unset | unset | null → route returns HTTP 503 |
The third row is the locked behavior consumers most often ask about. Default priority is alphabetical, not preference-biased. Anthropic precedes OpenRouter alphabetically, so it wins.
This is intentional. The alphabetical default avoids encoding any OpenRouter-primary preference into the "I just installed Anthropic SDK and it works" experience. Operators that want a specific priority pass it explicitly.
Full default priority
anthropic → deepseek → google → mistral → moonshot → openai → openrouterThese map to six of the seven ProviderFamily values exported from
@pleach/core/modelfamily (xai has no standalone env-var
detection) plus openrouter as a gateway transport.
The resolution matrix itself is host-supplied — reached through the
AgentAdapter.resolveModel<C>() seam, not shipped in the package.
Default env-var aliases per provider (from
DEFAULT_PROVIDER_ENV_VARS):
| Provider | Env var(s) |
|---|---|
anthropic | ANTHROPIC_API_KEY |
deepseek | DEEPSEEK_API_KEY |
google | GOOGLE_GENERATIVE_AI_API_KEY, GOOGLE_API_KEY |
mistral | MISTRAL_API_KEY |
moonshot | MOONSHOT_API_KEY |
openai | OPENAI_API_KEY |
openrouter | OPENROUTER_API_KEY |
Google ships keys under two names — the newer
GOOGLE_GENERATIVE_AI_API_KEY (used by @google/generative-ai) and
the legacy GOOGLE_API_KEY. The newer name is checked first.
Custom priority
Pass providers to override:
import { detectProvider } from "@pleach/core/quickstart";
// OpenRouter wins when both keys are set.
const provider = detectProvider({
providers: ["openrouter", "anthropic", "openai"],
});Pass a subset to restrict detection — providers not in the list are ignored even if their env vars are set:
// Only consider Anthropic and OpenAI. OpenRouter is ignored.
const provider = detectProvider({
providers: ["anthropic", "openai"],
});Custom env-var aliases
Override per-provider env-var names via envVars:
const provider = detectProvider({
envVars: {
anthropic: ["MY_CORP_ANTHROPIC_KEY", "ANTHROPIC_API_KEY"],
},
});The override replaces the provider's entire alias list. Providers not
in envVars inherit defaults.
Test-friendly: supply a synthetic env
By default detectProvider reads from process.env. Pass env to
supply your own map — useful in tests, edge environments, and
custom config sources:
const provider = detectProvider({
env: { ANTHROPIC_API_KEY: "sk-ant-test" },
});
// → "anthropic"Pass env: {} to force a "no provider detected" path without
mutating process.env.
Listing all detected providers
detectAvailableProviders() returns every provider with a non-empty
env-var value, in priority order. Useful for diagnostics and for
createPleachRoute callers that want to enumerate fallbacks:
import { detectAvailableProviders } from "@pleach/core/quickstart";
const available = detectAvailableProviders();
// e.g. ["anthropic", "openrouter"] when both keys are setPinning a provider explicitly
If you want to skip detection entirely, pass provider to
createPleachRoute:
export const POST = createPleachRoute({
provider: "anthropic",
});Detection is skipped; the route uses Anthropic regardless of which other env vars are set.
Honest scope-limit
Provider detection works for the seven default providers above.
Custom providers (your own gateway, a self-hosted LLM, a
forked SDK) require orchestratorConfig on createPleachRoute or
direct SessionRuntime construction — see
Upgrading to @pleach/core.
The detection helpers are pure functions over an env map; they do
NOT validate that the key works against the provider. A wrong-key
failure surfaces later as a provider exception inside the stream,
which ChatStreamError.cause preserves.