.memstack/skills/add-provider-package/SKILL.md
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.
npx skillsauth add s1366560/agi-demos add-provider-packageInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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 LanguageModelV3, EmbeddingModelV3, 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:
LanguageModelV3 for text generation modelsEmbeddingModelV3 for embedding modelsImageModelV1 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 correctlytools
Sandbox MCP Server 是一个隔离的代码执行环境,提供完整的文件系统操作、命令执行、 代码分析、测试运行和远程桌面能力。当你需要执行代码、操作文件、运行测试、 分析代码结构、或需要图形界面操作时使用此技能。支持 Python、Node.js、Java 等多语言环境。
tools
Replace with description of the skill and when Claude should use it.
development
Generate high-quality images using ModelScope's Z-Image API. Use this skill when the user wants to generate images using the specific Z-Image model or ModelScope API they provided. Trigger words: 'Zimage', 'ModelScope', 'generate zimage'.
tools
No-code automation democratizes workflow building. Zapier and Make (formerly Integromat) let non-developers automate business processes without writing code. But no-code doesn't mean no-complexity ...