Connecting providers
Configure provider SDKs, credentials, and model options.
Keel ships adapters for Anthropic, OpenAI, and Gemini. Each translates Keel's
model input and transcript into its provider's API and normalizes the result.
All three stream: text deltas reach the wire as the provider produces them,
and each adapter's generate is implemented by collecting its own stream, so
both paths share one contract mapping.
Install the provider SDK
Install only the SDKs your application uses:
npm install @anthropic-ai/sdk # Anthropic
npm install openai # OpenAI
npm install @google/genai # Geminipnpm add @anthropic-ai/sdk
pnpm add openai
pnpm add @google/genaiyarn add @anthropic-ai/sdk
yarn add openai
yarn add @google/genaibun add @anthropic-ai/sdk
bun add openai
bun add @google/genaiUse a provider class
Every provider class and factory requires an explicit model. Omitting it
is a TypeScript error and throws KeelError at runtime for JavaScript callers.
Keel never selects a default model, so library upgrades cannot silently change
your selection.
Choose a known model. Keel resolves its context window, maximum supported output, and tool capabilities from a versioned local catalog:
import { OpenAIProvider } from "@keel-dev/core/providers/openai";
const primary = new OpenAIProvider({
apiKey: process.env.OPENAI_API_KEY,
model: "gpt-5.1",
});Import under @keel-dev/core/providers/ | Class | Equivalent factory | Conventional key variable |
|---|---|---|---|
anthropic | AnthropicProvider | anthropic(options) | ANTHROPIC_API_KEY |
openai | OpenAIProvider | openai(options) | OPENAI_API_KEY |
gemini | GeminiProvider | gemini(options) | GEMINI_API_KEY |
The last column is a naming convention, not a lookup: Keel never reads
environment variables. The adapter uses only the apiKey option you pass —
your application loads its environment (or secret store) and supplies the
value explicitly, as in the example above. A tier constructed without an
apiKey is declared loudly: defineChain warns at definition time, naming
the conventional variable, and at execution the tier reports unavailable
so the chain falls through to the next tier.
The classes wrap the provider SDKs and normalize messages, tool calls, usage, and errors for the chain. Two behaviors of that wrapping are worth knowing:
- The SDK never retries underneath Keel. Each SDK client is constructed
with
maxRetries: 0. Keel's chain is the single retry authority; a second retry loop inside the SDK would multiply attempts invisibly. See Retry and fallback. - A refused model ID fails fast, then re-probes. When the API rejects the
configured model (not found), the adapter reports
bad-request, warns, and keeps failing fast for 60 seconds before asking the API again — no hammering, and no permanent per-process latch. Fix the model ID in the chain definition.
Understand the defaults
The initial catalog includes claude-opus-5, claude-haiku-4-5 (and its
20251001 snapshot), gpt-5.1, and gemini-2.5-pro.
Keep the selected ID in version-controlled configuration so changes can be reviewed. An explicit ID is not necessarily an immutable provider snapshot: use a versioned snapshot ID where the provider offers one. Keel cannot prevent a provider from changing what an alias or custom deployment points to.
provider.capabilities describes the model's supported limits.
provider.windowTokens and provider.maxOutputTokens are the selected
application ceilings. The default output ceiling is 8,192 tokens, reduced
when the model or selected window supports less. Override these options to
use a smaller window or another output ceiling within the model's capacity.
The catalog is a local snapshot exposed as MODEL_CATALOG and
MODEL_CATALOG_VERSION. It performs no live discovery and does not establish
account access or pricing. Supply optional pricing separately.
Use a model outside the catalog
A new model on a supported provider does not need a new adapter. Declare its
capabilities explicitly with customModel:
import { customModel } from "@keel-dev/core";
import { OpenAIProvider } from "@keel-dev/core/providers/openai";
const model = customModel({
provider: "openai",
id: "my-new-model", // Replace with your provider's model ID.
windowTokens: 32_000,
maxOutputTokens: 4_000,
supportsTools: true,
canForceTool: true,
});
const fallback = new OpenAIProvider({
apiKey: process.env.OPENAI_API_KEY,
model,
});These limits are illustrative. Use the capabilities of your actual model or deployment. Custom models use the selected provider's existing SDK and request format; another API protocol requires a custom adapter.
Unknown string IDs and mismatched provider definitions produce TypeScript errors. JavaScript callers receive configuration errors too. Token limits must be positive safe integers, output must fit the window, and forced tool selection requires tool support. Keel never guesses limits from an unknown model name.
Keep local and deployed configuration separate
The bundled examples can run without keys using deterministic adapters. A deployed live chain should use the configured provider tiers and report exhaustion if they all fail. Adding a scripted greeting as a final production fallback would conceal the failure behind a canned response.
Studio's key panel is a local development path: its key settings use browser
storage, and provider calls run from the browser. The Anthropic and OpenAI
SDKs refuse browser execution unless you opt in, so those two adapters accept
a browser: true option that sets the SDK's dangerouslyAllowBrowser flag;
the Gemini adapter needs no such option. Reserve browser: true for local
development, and supply production credentials on your server rather than
distributing them to app users:
import { AnthropicProvider } from "@keel-dev/core/providers/anthropic";
// Local development only — never ship a key to app users.
// `keys` comes from your app's local key handling (Studio's key panel
// hands your `createApp(cfg)` its LiveKeys the same way).
export function localTier(keys: { anthropic: string }) {
return new AnthropicProvider({
apiKey: keys.anthropic,
model: "claude-haiku-4-5",
browser: true,
});
}Inspect in Studio
Load your locally configured app in Studio. Watch WIRE while a turn runs — a streaming tier's text arrives as deltas — and inspect MODEL for the adapter ID and finish reason. If no live tier executes, check the credential warnings and fallback events before changing the agent's prompt.
Next: Retry and fallback.
