How to Add a New Custom AI Provider to Read Frog's Vercel AI SDK Integration
Adding a custom AI provider to Read Frog requires extending type definitions in src/types/config/provider.ts, registering UI assets and defaults in src/utils/constants/providers.ts, and wiring the Vercel AI SDK factory function in src/utils/providers/model.ts to enable runtime instantiation.
Read Frog abstracts every LLM service behind a unified provider-model layer compatible with the Vercel AI SDK. When you add a new custom AI provider to Read Frog, you extend this abstraction to support additional language model endpoints without modifying the core chat completion logic.
The Three-Layer Architecture
Read Frog's provider system consists of three distinct layers that handle type safety, user interface rendering, and runtime SDK instantiation. Understanding this architecture ensures your integration remains maintainable and fully type-safe.
Type Definitions and Validation
The first layer establishes compile-time safety through TypeScript literals and Zod schemas. In src/types/config/provider.ts, you must add the provider identifier to LLM_PROVIDER_TYPES (or API_PROVIDER_TYPES if applicable) and define a validation schema for its models using createProviderModelSchema.
This file also exports ALL_PROVIDER_TYPES, which aggregates every supported service. Adding your provider literal here enables TypeScript to validate provider strings throughout the codebase.
Default Configuration and UI Assets
The second layer supplies user-facing metadata and fallback configurations. In src/utils/constants/providers.ts, you define three critical mappings:
DEFAULT_LLM_PROVIDER_MODELS: Specifies the default model identifier, whether custom models are allowed, and the custom model placeholderPROVIDER_ITEMS: Contains the logo component, display name, and website URL rendered in the settings UIDEFAULT_PROVIDER_CONFIG: Provides the complete default provider object including enabled status and localization keys
These constants power the provider selection dropdown in Read Frog's interface.
Factory Mapping and Runtime Resolution
The third layer handles SDK instantiation at runtime. The file src/utils/providers/model.ts exports CREATE_AI_MAPPER, which maps provider ID strings to Vercel AI SDK factory functions.
When a user sends a message, getModelById() retrieves the stored configuration, selects the appropriate factory from CREATE_AI_MAPPER, builds the SDK instance, and returns provider.languageModel(modelId) to the chat engine. If your provider requires special headers (such as beta feature flags), extend CUSTOM_HEADER_MAP in the same file.
Step-by-Step Implementation
Follow these concrete steps to integrate a hypothetical provider named myai that ships with its own Vercel-compatible package @myai/ai-sdk-provider.
1. Install the Provider SDK
Add the provider's package to your dependencies:
pnpm add @myai/ai-sdk-provider
2. Update Type Definitions
Extend the provider type unions and model enums in src/types/config/provider.ts:
// Add to the provider types array
export const LLM_PROVIDER_TYPES = [
// …existing providers,
"myai",
] as const;
// Register available models (typically in utils/constants/models.ts)
export const LLM_PROVIDER_MODELS = {
// …existing entries,
myai: ["my-model-1", "my-model-2"] as const,
};
// Create the Zod validation schema
baseAPIProviderConfigSchema.extend({
provider: z.literal("myai"),
model: createProviderModelSchema<"myai">("myai"),
}),
3. Register UI Assets and Defaults
Populate the configuration constants in src/utils/constants/providers.ts:
import myaiLogo from "@/assets/providers/myai.svg";
// Default model configuration
export const DEFAULT_LLM_PROVIDER_MODELS = {
// …existing entries,
myai: {
model: "my-model-1",
isCustomModel: false,
customModel: null,
},
};
// UI display metadata
export const PROVIDER_ITEMS = {
// …existing entries,
myai: {
logo: () => myaiLogo,
name: "MyAI",
website: "https://myai.example.com",
},
};
// Complete default provider entry
export const DEFAULT_PROVIDER_CONFIG = {
// …existing entries,
myai: {
id: "myai-default",
name: PROVIDER_ITEMS.myai.name,
description: i18n.t("options.apiProviders.providers.description.myai"),
enabled: true,
provider: "myai",
model: DEFAULT_LLM_PROVIDER_MODELS.myai,
},
};
4. Wire the Factory Mapper
Connect the provider to the Vercel AI SDK runtime in src/utils/providers/model.ts:
import { createMyAI } from "@myai/ai-sdk-provider";
const CREATE_AI_MAPPER = {
// …existing entries,
myai: createMyAI,
} as const;
// Optional: Add custom headers if required
const CUSTOM_HEADER_MAP = {
// …existing entries,
myai: { "x-myai-feature": "true" },
};
Once these changes are applied, the myai provider appears in the Read Frog settings UI, persists user selections to storage, and instantiates correctly when getModelById("myai") invokes the factory during chat completion requests.
Summary
- Type definitions in
src/types/config/provider.tsenforce compile-time safety throughLLM_PROVIDER_TYPESand Zod schemas - Configuration constants in
src/utils/constants/providers.tssupply default models, UI logos, and provider metadata viaPROVIDER_ITEMS - Factory mapping in
src/utils/providers/model.tsbridges the provider ID to Vercel AI SDK instantiation viaCREATE_AI_MAPPER - The
getModelById()function orchestrates runtime resolution by selecting the correct factory and returningprovider.languageModel(modelId) - Special headers can be injected through
CUSTOM_HEADER_MAPfor provider-specific requirements - Contributors can reference the internal checklist at
.cursor/commands/add-provider.mdfor additional validation steps
Frequently Asked Questions
Do I need to modify the chat completion logic when adding a new provider?
No. Read Frog's architecture isolates provider-specific code to the three layers described above. The chat engine consumes the generic LanguageModel interface returned by getModelById(), so once you register the factory in CREATE_AI_MAPPER, the existing completion logic handles the new provider automatically according to the Vercel AI SDK specification.
Can I support custom model IDs that aren't predefined in the enum?
Yes. Set isCustomModel: true within DEFAULT_LLM_PROVIDER_MODELS for your provider in src/utils/constants/providers.ts. This exposes a text input in the UI where users can enter arbitrary model identifiers, bypassing the restricted enum validation while still maintaining type safety for the provider itself.
What file should I check if my provider isn't appearing in the settings dropdown?
Verify that you have added an entry to PROVIDER_ITEMS in src/utils/constants/providers.ts and that your provider literal exists in LLM_PROVIDER_TYPES within src/types/config/provider.ts. Missing either entry will prevent the UI from rendering the provider option, as the dropdown consumes both the type union and the metadata object.
How does Read Frog handle authentication headers for custom providers?
The Vercel AI SDK factory pattern encapsulates authentication within the factory function (such as createMyAI) that you import and map in src/utils/providers/model.ts. For provider-specific headers unrelated to authentication (such as feature flags or version markers), extend CUSTOM_HEADER_MAP in the same file to inject additional headers during SDK instantiation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →