Vercel AI SDK Core
Vercel AI SDK Core gives you streamText for orchestrating LLMs on the server. AI Transport encodes the resulting stream onto an Ably channel, so the same server code feeds durable sessions instead of an ephemeral HTTP response.
Vercel AI SDK Core is Vercel's server library for orchestrating LLM calls. streamText is the workhorse: pass a model, system prompt, and conversation history, and get back a stream of events. The default deployment writes that stream to an HTTP response over Server-Sent Events. AI Transport writes it to an Ably channel instead, so reconnects, multi-device, and bidirectional control come for free.
Ready to build? See Get started with Vercel AI SDK.
What Vercel AI SDK Core brings
| Capability | Description |
|---|---|
| Provider system | Abstracts model providers (Anthropic, OpenAI, Google) behind a unified interface. Switching models is a one-line change. |
streamText | Calls the model and returns a stream of UIMessageChunk events: text deltas, tool calls, tool results, reasoning content, and lifecycle events. |
UIMessage model | Messages with role and parts (text, reasoning, tool calls, tool results, files, sources). Each part tracks its own streaming state. |
| Tool calling | Models invoke tools you define with a schema and an execute function. The SDK feeds the result back to the model. |
result.toUIMessageStream() | Converts the model's event stream into a ReadableStream of UIMessageChunk events for transport. |
AI Transport composes with each of these. It does not replace them. It is the layer that writes the stream to a session instead of a connection.
What AI Transport adds
| Capability | Description |
|---|---|
| Durable sessions | Tokens flow through an Ably channel that outlives any single connection. A client reconnects and resumes from where it left off. |
| Multi-device sync | Every device subscribed to the session sees the same conversation in real time. |
| Bidirectional control | Cancel, steer, and interrupt the agent from any client. No separate control channel. |
| Active turn tracking | useActiveTurns exposes which clients are streaming and which turns are in progress. |
| Conversation branching | Edit and regenerate create forks in the conversation tree, not destructive replacements. |
| Approval gates that reach the user anywhere | Pending tool approvals persist on the session until someone acts on them. |
| History and replay | Load the full conversation on reconnect, page refresh, or new device join. |
| Token compaction | Reconnecting clients receive accumulated responses, not a replay of every token. |
These are the same capability bullets used on the Vercel AI SDK UI page; the capability surface is the same whichever layer you integrate against.
Where they connect
On the server, AI Transport replaces createUIMessageStreamResponse() with turn.streamResponse(). The HTTP response returns immediately; tokens flow to clients through the Ably channel instead of the HTTP body:
1
2
3
4
5
6
7
// Before: default HTTP transport
return createUIMessageStreamResponse({ stream: result.toUIMessageStream() });
// After: Ably transport
const { reason } = await turn.streamResponse(result.toUIMessageStream());
await turn.end(reason);
return new Response(null, { status: 200 });A full server route:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { after } from 'next/server';
import { streamText, convertToModelMessages } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import Ably from 'ably';
import { createServerTransport } from '@ably/ai-transport/vercel';
const ably = new Ably.Realtime({ key: process.env.ABLY_API_KEY });
export async function POST(req) {
const { messages, history, id, turnId, clientId, forkOf, parent } = await req.json();
const channel = ably.channels.get(id);
const transport = createServerTransport({ channel });
const turn = transport.newTurn({ turnId, clientId, parent, forkOf });
await turn.start();
if (messages.length > 0) {
await turn.addMessages(messages, { clientId });
}
const allMessages = [
...(history ?? []).map((h) => h.message),
...messages.map((m) => m.message),
];
const result = streamText({
model: anthropic('claude-sonnet-4-20250514'),
messages: await convertToModelMessages(allMessages),
abortSignal: turn.abortSignal,
});
after(async () => {
const { reason } = await turn.streamResponse(result.toUIMessageStream());
await turn.end(reason);
transport.close();
});
return new Response(null, { status: 200 });
}The integration has three pieces:
- The
UIMessageCodecencodes Vercel'sUIMessageChunkevents as Ably messages. Every chunk type maps to an Ably operation with headers that track the metadata. The codec encodes on the server and decodes on the client. createServerTransport({ channel })constructs the server-side transport bound to one channel. The default codec isUIMessageCodec.turn.streamResponse()reads the model'sUIMessageChunkstream, encodes each chunk, and publishes the resulting Ably messages.turn.abortSignalwires cancellation through from the client.
Scope and trade-offs
Vercel AI SDK Core is intentionally focused on model orchestration. By design, it does not handle session continuity across reconnects, multi-device fan-out, or stream resumability. AI Transport adds those without changing how you call streamText. The same model, the same messages, the same tool definitions; the destination of the stream moves from an HTTP response to a durable session.
If you are building the client side, see Vercel AI SDK UI.
Read next
- Get started with Vercel AI SDK: build a working app.
- Vercel AI SDK UI: the client-side integration that pairs with this page.
- Server transport API reference: the full API surface for the server transport.
- Codec API reference: the codec interface that
UIMessageCodecimplements.