Guide for adding new AI provider packages to the AI SDK. Use when creating a new @ai-sdk/<provider> package to integrate an AI service into the SDK.
This guide covers the process of creating a new @ai-sdk/<provider> package to integrate an AI service into the AI SDK.
@ai-sdk/<provider> packages: If you prefer a first-party package, please create an issue first to discuss.See https://github.com/vercel/ai/pull/8136/files for a complete example of adding a new provider.
The AI SDK uses a layered provider architecture following the adapter pattern:
@ai-sdk/provider): Defines interfaces like LanguageModelV4, EmbeddingModelV4, etc.@ai-sdk/provider-utils): Shared code for implementing providers@ai-sdk/<provider>): Concrete implementations for each AI serviceai): High-level functions like generateText, streamText, generateObjectCreate a new folder packages/<provider> with the following structure:
packages/<provider>/
├── src/
│ ├── index.ts # Main exports
│ ├── version.ts # Package version
│ ├── <provider>-provider.ts # Provider implementation
│ ├── <provider>-provider.test.ts
│ ├── <provider>-*-options.ts # Model-specific options
│ └── <provider>-*-model.ts # Model implementations (e.g., language, embedding, image)
├── package.json
├── tsconfig.json
├── tsconfig.build.json
├── tsup.config.ts
├── turbo.json
├── vitest.node.config.js
├── vitest.edge.config.js
└── README.md
Do not create a CHANGELOG.md file. It will be auto-generated.
Set up your package.json with:
"name": "@ai-sdk/<provider>""version": "0.0.0" (initial version, will be updated by changeset)"license": "Apache-2.0""sideEffects": false@ai-sdk/provider and @ai-sdk/provider-utils (use workspace:*)@ai-sdk/test-server, @types/node, @vercel/ai-tsconfig, tsup, typescript, zod"engines": { "node": ">=18" }zod (both v3 and v4): "zod": "^3.25.76 || ^4.1.8"Example exports configuration:
{
"exports": {
"./package.json": "./package.json",
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
}
}
}
tsconfig.json:
{
"extends": "@vercel/ai-tsconfig/base.json",
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
tsconfig.build.json:
{
"extends": "./tsconfig.json",
"exclude": [
"**/*.test.ts",
"**/*.test-d.ts",
"**/__snapshots__",
"**/__fixtures__"
]
}
Create tsup.config.ts:
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
sourcemap: true,
clean: true,
});
Create both vitest.node.config.js and vitest.edge.config.js (copy from existing provider like anthropic).
Provider implementation pattern:
// <provider>-provider.ts
import { NoSuchModelError } from '@ai-sdk/provider';
import { loadApiKey } from '@ai-sdk/provider-utils';
export interface ProviderSettings {
apiKey?: string;
baseURL?: string;
// provider-specific settings
}
export class ProviderInstance {
readonly apiKey?: string;
readonly baseURL?: string;
constructor(options: ProviderSettings = {}) {
this.apiKey = options.apiKey;
this.baseURL = options.baseURL;
}
private get baseConfig() {
return {
apiKey: () =>
loadApiKey({
apiKey: this.apiKey,
environmentVariableName: 'PROVIDER_API_KEY',
description: 'Provider API key',
}),
baseURL: this.baseURL ?? 'https://api.provider.com',
};
}
languageModel(modelId: string) {
return new ProviderLanguageModel(modelId, this.baseConfig);
}
// Shorter alias
chat(modelId: string) {
return this.languageModel(modelId);
}
}
// Export default instance
export const providerName = new ProviderInstance();
Each model type (language, embedding, image, etc.) should implement the appropriate interface from @ai-sdk/provider:
LanguageModelV4 for text generation modelsEmbeddingModelV4 for embedding modelsImageModelV4 for image generation modelsSchema guidelines:
Provider Options (user-facing):
.optional() unless null is meaningfulResponse Schemas (API responses):
.nullish() instead of .optional()Include:
__fixtures__ subdirectorySee capture-api-response-test-fixture skill for capturing real API responses for testing.
Create examples in examples/ai-functions/src/ for each model type the provider supports:
generate-text/<provider>.ts - Basic text generationstream-text/<provider>.ts - Streaming textgenerate-object/<provider>.ts - Structured output (if supported)stream-object/<provider>.ts - Streaming structured output (if supported)embed/<provider>.ts - Embeddings (if supported)generate-image/<provider>.ts - Image generation (if supported)Add feature-specific examples as needed (e.g., <provider>-tool-call.ts, <provider>-cache-control.ts).
Create documentation in content/providers/01-ai-sdk-providers/<last number + 10>-<provider>.mdx
Include:
Run pnpm changeset and:
major version (for new packages starting at 0.0.0)Run pnpm update-references from the workspace root to update tsconfig references.
# From workspace root
pnpm build
# From provider package
cd packages/<provider>
pnpm test # Run all tests
pnpm test:node # Run Node.js tests
pnpm test:edge # Run Edge tests
pnpm type-check # Type checking
# From workspace root
pnpm type-check:full # Full type check including examples
Test your examples:
cd examples/ai-functions
pnpm tsx src/generate-text/<provider>.ts
pnpm tsx src/stream-text/<provider>.ts
languageModel(id), imageModel(id), embeddingModel(id) (required).chat(id), .image(id), .embedding(id) (for DX)kebab-case.tskebab-case.test.tskebab-case.test-d.ts<Provider>Provider, <Provider>LanguageModel, etc.JSON.parse directly - use parseJSON or safeParseJSON from @ai-sdk/provider-utilsloadApiKey from @ai-sdk/provider-utilsErrors should extend AISDKError from @ai-sdk/provider and use a marker pattern:
import { AISDKError } from '@ai-sdk/provider';
const name = 'AI_ProviderError';
const marker = `vercel.ai.error.${name}`;
const symbol = Symbol.for(marker);
export class ProviderError extends AISDKError {
private readonly [symbol] = true;
constructor({ message, cause }: { message: string; cause?: unknown }) {
super({ name, message, cause });
}
static isInstance(error: unknown): error is ProviderError {
return AISDKError.hasMarker(error, marker);
}
}
If main is set up to publish beta releases, no further action is necessary. Just make sure not to backport it to the vX.Y stable branch since it will result in an npm version conflict once we exit pre-release mode on main.
packages/<provider>package.json configured with correct dependenciestsconfig.json, tsconfig.build.json)tsup.config.ts)vitest.node.config.js, vitest.edge.config.js)examples/ai-functions/src/content/providers/01-ai-sdk-providers/pnpm update-references runpnpm test from package)pnpm type-check:full from root)pnpm update-references from workspace rootpnpm type-check:full to catch issues earlytsup.config.ts is configured correctly