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 placeholder
  • PROVIDER_ITEMS: Contains the logo component, display name, and website URL rendered in the settings UI
  • DEFAULT_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.ts enforce compile-time safety through LLM_PROVIDER_TYPES and Zod schemas
  • Configuration constants in src/utils/constants/providers.ts supply default models, UI logos, and provider metadata via PROVIDER_ITEMS
  • Factory mapping in src/utils/providers/model.ts bridges the provider ID to Vercel AI SDK instantiation via CREATE_AI_MAPPER
  • The getModelById() function orchestrates runtime resolution by selecting the correct factory and returning provider.languageModel(modelId)
  • Special headers can be injected through CUSTOM_HEADER_MAP for provider-specific requirements
  • Contributors can reference the internal checklist at .cursor/commands/add-provider.md for 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →