- MCP Server ToolsUpdated
- Managed MCP with chat()Updated
- Manual MCPUpdated
- MCP Type GenerationUpdated
- MCP Client InputUpdated
- MCP Server Tools: AdvancedNew
- MCP EventsNew
- MCP AppsUpdated
- Serve Tools over HTTPUpdated
- Serve Resources and PromptsUpdated
- Ask for InputUpdated
- Draft Text from a ToolUpdated
- MCP Server TasksUpdated
- MCP Server AuthUpdated
- MCP Server SessionsUpdated
- MCP Server on stdioUpdated
Persistence (Advanced)
- GenerationsUpdated
- Realtime Voice ChatUpdated
- Text-to-SpeechUpdated
- TranscriptionUpdated
- Transcription: AdvancedNew
- Voice CreationUpdated
- Audio RecordingUpdated
- Audio GenerationUpdated
- Image GenerationUpdated
- Image Generation: AdvancedNew
- Video GenerationUpdated
- Video Generation: AdvancedNew
- Live GenerationUpdated
- World GenerationUpdated
- Generation HooksUpdated
- OverviewUpdated
- Quick StartUpdated
- ProvidersUpdated
- HarnessesUpdated
- Harness AuthUpdated
- WorkspaceUpdated
- ToolsUpdated
- PolicyUpdated
- Lifecycle & SnapshotsUpdated
- Portable SnapshotsUpdated
- Keep Files After ReloadUpdated
- Save a Named VersionUpdated
- Branch From a VersionUpdated
- Send a Frozen FileUpdated
- Let the Agent Save and ForkUpdated
- Pick Which Files to KeepUpdated
- What a Snapshot StoresUpdated
- Instance DurabilityUpdated
- Durable RunsUpdated
- EventsUpdated
Sandboxes (Advanced)
- Runtime ContextUpdated
- Bring Your Own KeyUpdated
- Debug LoggingUpdated
- Multimodal ContentUpdated
- Files APIUpdated
- Per-Model Type SafetyUpdated
- Runtime Adapter SwitchingUpdated
- Tree-ShakingUpdated
- Extend AdapterUpdated
- Extend Adapter: AdvancedNew
- Typed Pre-Configured OptionsUpdated
- Test with a Fake ModelUpdated
- Prompt CachingUpdated
- Mid-Conversation ChangesUpdated
- Approval Flow ProcessingUpdated
Tree-Shaking
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.
Quick setup#
- Import the activity that you use from @tanstack/ai.
- Import the one adapter that you use from the provider package.
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:
- The chat function, with its streaming and tool code.
- The openaiText adapter.
It does not hold summarize, generateImage, the other activities, or the adapters of other providers.
Use named imports#
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'Use more than one activity#
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.
Tips for smaller bundles#
- Use a specific adapter function, for example openaiText, for each activity.
- Put different activities in different API routes.
- Load code-split routes with dynamic imports.
- In React Native and Expo, keep the chat screens client-only. Import useChat and the connection adapters there. Do not import provider SDKs, server response helpers, React DOM UI, devtools UI, or other framework packages. See Quick Start: React Native for the server-only provider boundary and the mobile transport setup.
How it works#
- Each function is a named ES module export, not a default export.
- Each activity and adapter lives in its own module.
- @tanstack/ai declares "sideEffects": false in its package.json, so bundlers can drop modules that you do not import.
- Type-only imports are removed at build time.
Bundlers such as Vite, Webpack, Rollup, and esbuild follow the static imports and drop the code that you do not reference.
Advanced#
Activity functions#
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 |
Adapter functions by provider#
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.
Adapter types#
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'Type safety#
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