Import one adapter from its package subpath. The bundle then omits image generation and the adapters you do not call.
TanStack AI exports each activity and each adapter as a separate named function. Import only the ones you use, and your bundler drops the rest.
import { chat } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
const stream = chat({
adapter: openaiText('gpt-6.1-sol'),
messages: [{ role: 'user', content: 'Hello!' }],
threadId: 'thread-1',
})
for await (const chunk of stream) {
console.log(chunk)
}Your bundle now holds:
It does not hold summarize, generateImage, the other activities, or the adapters of other providers.
Import each function by name. Some bundlers cannot drop the unused exports of a namespace import:
// Good: only what you use
import { chat } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'// Avoid: a namespace import can pull in every export
import * as ai from '@tanstack/ai'
import * as openai from '@tanstack/ai-openai'Import each activity and its adapter. Each one is independent:
import { chat, summarize } from '@tanstack/ai'
import { openaiSummarize, openaiText } from '@tanstack/ai-openai'
const stream = chat({
adapter: openaiText('gpt-6.1-sol'),
messages: [{ role: 'user', content: 'Hello!' }],
threadId: 'thread-1',
})
const summary = await summarize({
adapter: openaiSummarize('gpt-5.4-mini'),
text: 'Long text to summarize.',
threadId: 'thread-1',
})The create*Options helpers are separate exports too. See Typed Pre-Configured Options.
Provider adapters call the provider HTTP API with fetch. They do not load the provider SDK, except for the options below. These options load the SDK on first use.
| Adapter | Options that load the SDK |
|---|---|
| OpenAI and OpenAI-compatible | workloadIdentity, provider, dataResidency, credential, x509Transport, no apiKey (admin key only). On Azure: azureADTokenProvider or workloadIdentity |
| Anthropic | middleware, OpenTelemetry tracing (openTelemetry, or a global OpenTelemetry tracer), logLevel: 'info' or 'debug' (or ANTHROPIC_LOG), no apiKey and no authToken |
| Gemini | vertexai: true, enterprise: true, no apiKey, a file path string as the upload |
| fal | An upload larger than 90 MB |
These options decide when the SDK runs. They do not decide what goes into the bundle:
configureFalClient is different. It imports @fal-ai/client statically, because it configures the global fal client. If you import configureFalClient, the SDK is in the startup bundle, also with chunk splitting.
Bundlers such as Vite, Webpack, Rollup, and esbuild follow the static imports and drop the code that you do not reference.
Each activity is a separate export of @tanstack/ai:
| Function | Activity |
|---|---|
| chat | Chat and text generation |
| summarize | Summarization |
| generateImage | Image generation |
| generateSpeech | Text-to-speech |
| generateTranscription | Audio transcription |
| generateVideo | Video generation |
| generateLiveVideo | Live video sessions |
| generateWorld | Live world sessions |
Each provider package exports one function for each activity. Some examples:
| Package | Adapters |
|---|---|
| @tanstack/ai-openai | openaiText, openaiSummarize, openaiImage, openaiSpeech, openaiTranscription, openaiVideo, openaiEmbedding |
| @tanstack/ai-anthropic | anthropicText, anthropicSummarize |
| @tanstack/ai-gemini | geminiText, geminiSummarize, geminiImage, geminiSpeech (experimental), geminiEmbedding |
| @tanstack/ai-ollama | ollamaText, ollamaSummarize, ollamaEmbedding |
Each adapter page lists the full set for its provider.
Each adapter type has its own interface and a kind property:
| Interface | Main method | kind |
|---|---|---|
| TextAdapter | chatStream() | 'text' |
| SummarizeAdapter | summarize() | 'summarize' |
| ImageAdapter | generateImages() | 'image' |
| TTSAdapter | generateSpeech() | 'tts' |
| TranscriptionAdapter | transcribe() | 'transcription' |
| VideoAdapter | createVideoJob(), getVideoStatus(), getVideo() | 'video' |
| LiveVideoAdapter | createLiveVideo() | 'liveVideo' |
| WorldAdapter | createWorld() | 'world' |
import { openaiSummarize, openaiText } from '@tanstack/ai-openai'
const chatAdapter = openaiText('gpt-6.1-sol')
console.log(chatAdapter.kind) // 'text'
const summarizeAdapter = openaiSummarize('gpt-5.4-mini')
console.log(summarizeAdapter.kind) // 'summarize'Separate exports keep the full types. Each adapter knows the models of its provider:
import { openaiText, type OpenAIChatModel } from '@tanstack/ai-openai'
const adapter = openaiText('gpt-6.1-sol')
const model: OpenAIChatModel = 'gpt-6.1-sol' // OK
const model2: OpenAIChatModel = 'invalid' // Type error