๐ค AI SDK Dart
A Dart/Flutter port of Vercel AI SDK v6 โ provider-agnostic APIs for text generation, streaming, structured output, tool use, embeddings, image generation, speech, and more.
What is this?
AI SDK Dart brings the full power of Vercel AI SDK v6 to Dart and Flutter. Write your AI logic once, swap providers without changing a line of business code, and ship on every platform โ mobile, web, and server. Every API mirrors its JavaScript counterpart so the official Vercel docs apply directly to your Dart code.
Screenshots
Flutter Chat App (examples/flutter_chat)
| Multi-turn Chat | Streaming Response |
![]() |
![]() |
| Completion | Object Stream |
![]() |
![]() |
Advanced App (examples/advanced_app)
| Provider Chat | Tools Chat |
![]() |
![]() |
| Image Generation | Multimodal |
![]() |
![]() |
โจ Features
๐ฃ๏ธ Text Generation & Streaming
generateTextโ single-turn or multi-step text generation with full result envelopestreamTextโ real-time token streaming with typed event taxonomysmoothStreamtransform โ configurable chunk-size smoothing;delayInMsoption adds per-chunk delay for UX pacing- Multi-step agentic loops with
maxSteps,prepareStep, andstopConditions timeoutparameter on all core functions โ applyDurationdeadlines to any model call- Callbacks:
onFinish,onStepFinish,onChunk,onError,experimentalOnStart,onAbort
๐งฉ Structured Output
Output.object(schema)โ parse model output into a typed Dart objectOutput.array(schema)โ parse model output into a typed Dart listOutput.choice(options)โ constrain output to a fixed set of string valuesOutput.json()โ raw JSON without schema validation- Automatic code-fence stripping (
```json ... ```)
๐ง Type-Safe Tools & Multi-Step Agents
tool<Input, Output>()โ fully typed tool definitions with JSON schemadynamicTool()โ tools with unknown input type for dynamic use cases- Tool choice:
auto,required,none, or specific tool - Tool approval workflow with
needsApproval - Multi-step agentic loops with automatic tool result injection
onInputStart,onInputDelta,onInputAvailablelifecycle hooks
๐ผ๏ธ Multimodal
generateImageโ image generation (gpt-image-1 / DALLยทE via OpenAI)generateSpeechโ text-to-speech audio synthesistranscribeโ speech-to-text transcription- Image inputs in prompts (multimodal vision)
๐งฎ Embeddings & Cosine Similarity
embed()โ single value embedding with usage trackingembedMany()โ batch embedding for multiple values with configurable chunk sizecosineSimilarity()โ built-in similarity computationwrapEmbeddingModel()โ composable middleware pipeline for embedding models
๐งฑ Middleware System
wrapLanguageModel(model, middlewares)โ composable middleware pipelineextractReasoningMiddlewareโ strips<think>tags intoReasoningPartextractJsonMiddlewareโ strips```json ```fencessimulateStreamingMiddlewareโ converts non-streaming models to streamingdefaultSettingsMiddlewareโ applies default temperature/top-p/etc.addToolInputExamplesMiddlewareโ enriches tool descriptions with exampleswrapEmbeddingModel/wrapImageModelโ the same composable middleware pattern for embedding and image models
๐ Provider Registry
createProviderRegistryโ map provider aliases to model factoriescustomProvider()โ lightweight on-the-fly provider construction without a full registry- Resolve models by
'provider:modelId'string at runtime - Supports 5 model categories: language, embedding, image, speech, transcription
- Mix providers in a single registry for multi-provider apps
๐ฑ Flutter UI Controllers & Widgets
ChatControllerโ multi-turn streaming chat with message historyCompletionControllerโ single-turn text completion with statusObjectStreamControllerโ streaming typed JSON object updates- 19 prebuilt, themeable Material widgets โ
AiChatScaffold, message list/bubbles, composer, streaming text, typing indicator, tool-call & approval cards, reasoning, citations, usage, and more
๐ MCP Client (Model Context Protocol)
MCPClientโ connect to MCP servers, discover tools, invoke themSseClientTransportโ real Server-Sent-Events streaming transport (MCP HTTP+SSE 2024-11-05)HttpClientTransportโ plain request/response POST transport for single-endpoint serversStdioMCPTransportโ stdio process transport (native platforms)- Web-safe โ
dart:iois isolated behind conditional imports, so the client runs on Flutter web - Discovered tools are directly compatible with
generateText/streamText
๐จ Typed Errors
- Sealed
AiSdkErrorhierarchy โAiApiCallError,AiNoObjectGeneratedError,AiRetryError, and more - Provider API errors are typed โ a non-2xx response throws
AiApiCallErrorcarrying the provider'smessage,type,code,statusCode, raw body, and anisRetryableflag, consistently across every provider
๐งช Conformance Suite
- 1,057 tests (924 Dart + 133 Flutter) covering every public API
- 99.9% line coverage overall โ 11 of 12 packages at 100%, enforced by a CI coverage gate
- Spec-driven JSON fixtures as the source of truth
- Provider wire-format conformance tests for every provider (plus a typed-error conformance test per provider)
MockEmbeddingModelV3testing utility for embedding model conformance
๐ฆ Packages
| Package | pub.dev | What it gives you |
|---|---|---|
ai_sdk_dart |
dart pub add ai_sdk_dart |
generateText, streamText, tools, middleware, embeddings, registry |
ai_sdk_openai |
dart pub add ai_sdk_openai |
openai('gpt-4.1-mini'), embeddings, image gen, speech, transcription, reasoning options |
ai_sdk_anthropic |
dart pub add ai_sdk_anthropic |
anthropic('claude-sonnet-4-5'), extended thinking, speed options |
ai_sdk_google |
dart pub add ai_sdk_google |
google('gemini-2.0-flash'), embeddings |
ai_sdk_azure |
dart pub add ai_sdk_azure |
AzureOpenAIProvider(endpoint, apiKey), language models, embeddings |
ai_sdk_cohere |
dart pub add ai_sdk_cohere |
cohere('command-r-plus'), embeddings, reranking |
ai_sdk_groq |
dart pub add ai_sdk_groq |
groq('llama3-8b-8192'), ultra-low latency inference |
ai_sdk_mistral |
dart pub add ai_sdk_mistral |
mistral('mistral-large-latest'), embeddings |
ai_sdk_ollama |
dart pub add ai_sdk_ollama |
ollama('llama3'), local inference, embeddings |
ai_sdk_flutter_ui |
dart pub add ai_sdk_flutter_ui |
ChatController, CompletionController, ObjectStreamController + 19 prebuilt chat widgets |
ai_sdk_mcp |
dart pub add ai_sdk_mcp |
MCPClient, SseClientTransport, HttpClientTransport, StdioMCPTransport (web-safe) |
ai_sdk_provider |
(transitive) | Provider interfaces for building custom providers |
ai_sdk_openai_compatible |
(transitive) | Shared OpenAI Chat Completions base โ powers the OpenAI/Azure/Groq/Mistral language models |
ai_sdk_providerandai_sdk_openai_compatibleare transitive dependencies โ you do not need to add them directly.
๐ Quick Start
Dart CLI
dart pub add ai_sdk_dart ai_sdk_openai
export OPENAI_API_KEY=sk-...
import 'package:ai_sdk_dart/ai_sdk_dart.dart';
import 'package:ai_sdk_openai/ai_sdk_openai.dart';
void main() async {
// Text generation
final result = await generateText(
model: openai('gpt-4.1-mini'),
prompt: 'Say hello from AI SDK Dart!',
);
print(result.text);
}
Streaming
final result = await streamText(
model: openai('gpt-4.1-mini'),
prompt: 'Count from 1 to 5.',
);
await for (final chunk in result.textStream) {
stdout.write(chunk);
}
Structured Output
final result = await generateText<Map<String, dynamic>>(
model: openai('gpt-4.1-mini'),
prompt: 'Return the capital and currency of Japan as JSON.',
output: Output.object(
schema: Schema<Map<String, dynamic>>(
jsonSchema: const {
'type': 'object',
'properties': {
'capital': {'type': 'string'},
'currency': {'type': 'string'},
},
},
fromJson: (json) => json,
),
),
);
print(result.output); // {capital: Tokyo, currency: JPY}
Type-Safe Tools
final result = await generateText(
model: openai('gpt-4.1-mini'),
prompt: 'What is the weather in Paris?',
maxSteps: 5,
tools: {
'getWeather': tool<Map<String, dynamic>, String>(
description: 'Get current weather for a city.',
inputSchema: Schema(
jsonSchema: const {
'type': 'object',
'properties': {'city': {'type': 'string'}},
},
fromJson: (json) => json,
),
execute: (input, _) async => 'Sunny, 18ยฐC',
),
},
);
print(result.text);
Error handling
try {
final result = await generateText(
model: openai('gpt-4.1-mini'),
prompt: 'Hello',
);
} on AiApiCallError catch (e) {
// Typed provider error โ message, status, and retryability are all available.
print('${e.statusCode}: ${e.message} (retryable: ${e.isRetryable})');
}
Flutter Chat UI
dart pub add ai_sdk_dart ai_sdk_openai ai_sdk_flutter_ui
import 'package:ai_sdk_dart/ai_sdk_dart.dart';
import 'package:ai_sdk_openai/ai_sdk_openai.dart';
import 'package:ai_sdk_flutter_ui/ai_sdk_flutter_ui.dart';
final agent = ToolLoopAgent(
model: openai('gpt-4.1-mini'),
instructions: 'You are a helpful assistant.',
);
final chat = ChatController();
// In your widget โ a complete chat surface:
AiChatScaffold(controller: chat, agent: agent);
๐ค Providers
| Capability | OpenAI | Anthropic | Azure | Cohere | Groq | Mistral | Ollama | |
|---|---|---|---|---|---|---|---|---|
| Text generation | โ | โ | โ | โ | โ | โ | โ | โ |
| Streaming | โ | โ | โ | โ | โ | โ | โ | โ |
| Structured output | โ | โ | โ | โ | โ | โ | โ | โ |
| Native JSON schema output | โ | โ | โ | โ | โ | โ | โ | โ |
| Tool use | โ | โ | โ | โ | โ | โ | โ | โ |
| Embeddings | โ | โ | โ | โ | โ | โ | โ | โ |
| Reranking | โ | โ | โ | โ | โ | โ | โ | โ |
| Image generation | โ | โ | โ | โ | โ | โ | โ | โ |
| Speech synthesis | โ | โ | โ | โ | โ | โ | โ | โ |
| Transcription | โ | โ | โ | โ | โ | โ | โ | โ |
| Extended thinking | โ | โ | โ | โ | โ | โ | โ | โ |
| Reasoning options | โ | โ | โ | โ | โ | โ | โ | โ |
| Multimodal (image input) | โ | โ | โ | โ | โ | โ | โ | โ |
๐ ๏ธ Flutter UI
The ai_sdk_flutter_ui package provides three reactive controllers plus a library of 19 prebuilt,
themeable Material widgets โ so you can wire up a full chat UI in a few lines, or drop down to the
controllers and render everything yourself.
Drop-in chat UI
import 'package:ai_sdk_dart/ai_sdk_dart.dart';
import 'package:ai_sdk_flutter_ui/ai_sdk_flutter_ui.dart';
final agent = ToolLoopAgent(model: openai('gpt-4.1-mini'));
final chat = ChatController();
// A complete message list + composer, wired to the controller + agent:
AiChatScaffold(controller: chat, agent: agent);
Other widgets โ ChatMessageList, ChatMessageBubble, ChatComposer, StreamingTextView,
TypingIndicator, ToolCallCard, ToolApprovalCard, ReasoningView, SourceCitations,
UsageView, PromptSuggestions, ObjectStreamView, and more โ can be composed ร la carte. They
read only the controllers' public state, so they work with any state-management approach.
ChatController โ Multi-turn streaming chat
final agent = ToolLoopAgent(model: openai('gpt-4.1-mini'));
final chat = ChatController();
// In your widget:
ListenableBuilder(
listenable: chat,
builder: (context, _) {
return Column(
children: [
for (final msg in chat.messages)
Text('${msg.role}: ${msg.content}'),
if (chat.isLoading) const CircularProgressIndicator(),
],
);
},
);
// Send a message:
await chat.sendMessage(agent: agent, text: 'What is the capital of France?');
CompletionController โ Single-turn completion
final completion = CompletionController(
agent: ToolLoopAgent(model: openai('gpt-4.1-mini')),
);
await completion.complete('Write a haiku about Dart.');
print(completion.completion);
ObjectStreamController โ Streaming typed JSON
final controller = ObjectStreamController<Map<String, dynamic>>(
model: openai('gpt-4.1-mini'),
schema: Schema<Map<String, dynamic>>(
jsonSchema: const {'type': 'object'},
fromJson: (json) => json,
),
);
await controller.submit('Describe Japan as a JSON object.');
print(controller.value); // Partial updates arrive in real-time
๐ MCP Support
Connect to any Model Context Protocol server and use its tools directly in your AI calls:
import 'package:ai_sdk_mcp/ai_sdk_mcp.dart';
final client = MCPClient(
transport: SseClientTransport(
url: Uri.parse('http://localhost:3000/mcp'),
),
);
await client.initialize();
final tools = await client.tools(); // Returns a ToolSet
final result = await generateText(
model: openai('gpt-4.1-mini'),
prompt: 'What files are in the project?',
tools: tools,
maxSteps: 5,
);
For stdio-based MCP servers (local processes):
final client = MCPClient(
transport: StdioMCPTransport(
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '/path/to/dir'],
),
);
SseClientTransport does real Server-Sent-Events streaming (and surfaces server-pushed
notifications); for servers that expose a single JSON-RPC POST endpoint without SSE, use
HttpClientTransport. The HTTP/SSE transports are web-safe โ dart:io is only pulled in by
StdioMCPTransport on native platforms, behind a conditional import โ so the client also runs on
Flutter web.
๐บ๏ธ Roadmap
โ Implemented
- โ
generateTextโ full result envelope (text, steps, usage, reasoning, sources, files) - โ
streamTextโ complete event taxonomy (20 typed event types),onAbortcallback - โ
generateObject/ structured output (object, array, choice, json) with native JSON schema - โ
embed/embedMany+cosineSimilarity,wrapEmbeddingModel - โ
generateImage(OpenAI gpt-image-1 / DALLยทE) - โ
generateSpeech(OpenAI TTS) - โ
transcribe(OpenAI Whisper) - โ
rerank - โ
timeoutparameter on all core functions - โ
customProvider()for lightweight on-the-fly provider construction - โ Middleware system โ 5 built-in language-model middlewares, plus embedding & image model middleware
- โ
Provider registry (
createProviderRegistry) โ 5 model categories - โ Multi-step agentic loops with tool approval
- โ Flutter UI controllers (Chat, Completion, ObjectStream) + 19 prebuilt Material widgets
- โ MCP client (real SSE + HTTP + stdio transports, prompts, resources, web-safe)
- โ
Typed provider API errors (
AiApiCallErrorwith status / type / code / body) across all providers - โ OpenAI (with reasoning options), Anthropic (with thinking options), Google providers
- โ Cohere, Mistral, Groq, Ollama, Azure OpenAI providers โ all with tools + multimodal
- โ 1,057 tests, 99.9% line coverage with a CI coverage gate
๐ Planned
- ๐ Streaming MCP tool outputs
- ๐ Richer attachment widgets (file/image pickers, audio capture)
- ๐ Dart Edge / Cloudflare Workers support
- ๐ WebSocket transport for MCP
๐ค Contributing
Contributions are welcome! Please open an issue first to discuss changes before submitting a PR.
- ๐ Bug reports โ use the Bug Report template
- ๐ก Feature requests โ use the Feature Request template
- ๐ฌ Questions & discussions โ use GitHub Discussions
Running tests
dart pub global activate melos
melos bootstrap
melos test # run all package tests
melos analyze # dart analyze across all packages
Or with the Makefile:
make get # install all workspace dependencies
make test # run all package tests
make analyze # run dart analyze
make format # format all Dart source files
Runnable examples
Set API keys before running:
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
export GOOGLE_API_KEY=AIza...
| Example | Command | What it shows |
|---|---|---|
| Dart CLI | make run-basic |
generateText, streaming, structured output, tools, embeddings, middleware |
| Flutter chat | make run |
ChatController, CompletionController, ObjectStreamController |
| Flutter chat (web) | make run-web |
Same as above on Chrome |
| Advanced app | make run-advanced |
All providers, tools, image gen, TTS, STT, multimodal, embeddings, completion, object stream + widget gallery |
| Advanced app (web) | make run-advanced-web |
Same as above on Chrome |
| MCP demo | make run-mcp |
MCP tool discovery + direct tool calls (works without an API key) |
Development
Managed with Melos as a monorepo workspace:
dart pub global activate melos
melos bootstrap
melos analyze
melos test
See docs/v6-parity-matrix.md for a feature-by-feature parity matrix against Vercel AI SDK v6.
๐ License
Libraries
- ai_sdk_dart
- test
- Testing utilities for the AI SDK Dart.







