diff --git a/src/data/languages/languageData.ts b/src/data/languages/languageData.ts
index b7bbd5e8a2..e1788fdb19 100644
--- a/src/data/languages/languageData.ts
+++ b/src/data/languages/languageData.ts
@@ -44,7 +44,7 @@ export default {
android: '1.2',
},
aiTransport: {
- javascript: '0.2',
+ javascript: '0.3',
},
spaces: {
javascript: '0.5',
diff --git a/src/pages/docs/ai-transport/api/errors.mdx b/src/pages/docs/ai-transport/api/errors.mdx
index e3597de0d1..a9b8c7ec58 100644
--- a/src/pages/docs/ai-transport/api/errors.mdx
+++ b/src/pages/docs/ai-transport/api/errors.mdx
@@ -63,6 +63,7 @@ Auth and channel errors come from the Ably platform, not AI Transport. The most
| 40300 | Forbidden. | The token is valid but not authorised for this resource. |
| 80000 | Channel attach failed. | Check the channel name and capability. |
| 90000 | Internal channel error. | Retry the operation. If the error persists, contact support. |
+| 93002 | `Can only update/delete/append messages on channels with mutableMessages enabled`. The namespace lacks the `mutableMessages` rule, so AI Transport cannot append stream tokens. This is the most common AI Transport setup failure. | Enable the **Message annotations, updates, deletes, and appends** rule on the namespace. See [Configure the channel rule](/docs/ai-transport/getting-started/channel-rules). |
The full Ably error code list lives at [Ably error codes](/docs/sdks/error-codes).
diff --git a/src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-core.mdx b/src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-core.mdx
index 841c2bfad2..f5a7b2303a 100644
--- a/src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-core.mdx
+++ b/src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-core.mdx
@@ -9,6 +9,10 @@ intro: "Vercel AI SDK Core gives you streamText for orchestrating LLMs on the se
Ready to build? See [Get started with Vercel AI SDK](/docs/ai-transport/getting-started/vercel-ai-sdk).
+
+
## What Vercel AI SDK Core brings
| Capability | Description |
diff --git a/src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-ui.mdx b/src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-ui.mdx
index 7571e99ba3..9d06816657 100644
--- a/src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-ui.mdx
+++ b/src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-ui.mdx
@@ -11,6 +11,10 @@ redirect_from:
Ready to build? See [Get started with Vercel AI SDK](/docs/ai-transport/getting-started/vercel-ai-sdk).
+
+
## What Vercel AI SDK UI brings
| Capability | Description |
diff --git a/src/pages/docs/ai-transport/getting-started/core-sdk.mdx b/src/pages/docs/ai-transport/getting-started/core-sdk.mdx
index 32849f8f6d..6d11529c04 100644
--- a/src/pages/docs/ai-transport/getting-started/core-sdk.mdx
+++ b/src/pages/docs/ai-transport/getting-started/core-sdk.mdx
@@ -18,7 +18,7 @@ To use AI Transport with Vercel's `useChat` for message management, see [Get sta
## Prerequisites
-- Node.js 20 or later.
+- Node.js 22 or later.
- An [Ably account](https://ably.com/sign-up) with an API key.
- An Anthropic API key, or any other model provider you prefer.
@@ -36,6 +36,16 @@ Create an auth endpoint at `/api/auth/token` that returns an Ably JWT to the cli
The client below uses `authUrl: '/api/auth/token'` to fetch tokens from this endpoint.
+## Configure the channel rule
+
+AI Transport streams each response by appending tokens to a single channel message. That requires the **Message annotations, updates, deletes, and appends** channel rule (`mutableMessages`) on the namespace your conversations live on.
+
+In your Ably dashboard, enable **Message annotations, updates, deletes, and appends** on the `conversations` namespace. See [Configure the channel rule](/docs/ai-transport/getting-started/channel-rules) for the dashboard, Control API, and CLI steps.
+
+
+
## Create the agent route
Create `app/api/chat/route.ts`. The agent receives an [Invocation](/docs/ai-transport/concepts/invocations), creates an [AgentSession](/docs/ai-transport/api/javascript/core/agent-session), starts a [Run](/docs/ai-transport/concepts/runs), hydrates the conversation, pipes the LLM stream, and ends the Run.
diff --git a/src/pages/docs/ai-transport/getting-started/vercel-ai-sdk.mdx b/src/pages/docs/ai-transport/getting-started/vercel-ai-sdk.mdx
index 367e0e942d..5156d0d703 100644
--- a/src/pages/docs/ai-transport/getting-started/vercel-ai-sdk.mdx
+++ b/src/pages/docs/ai-transport/getting-started/vercel-ai-sdk.mdx
@@ -24,7 +24,7 @@ For direct access to the conversation tree, branching, and pagination, see [Get
## Prerequisites
-- Node.js 20 or later.
+- Node.js 22 or later.
- An [Ably account](https://ably.com/sign-up) with an API key.
- An Anthropic API key, or any other model provider supported by Vercel AI SDK.
@@ -42,6 +42,16 @@ Create an auth endpoint at `/api/auth/token` that returns an Ably JWT to the cli
The client below uses `authUrl: '/api/auth/token'` to fetch tokens from this endpoint.
+## Configure the channel rule
+
+AI Transport streams each response by appending tokens to a single channel message. That requires the **Message annotations, updates, deletes, and appends** channel rule (`mutableMessages`) on the namespace your conversations live on.
+
+In your Ably dashboard, enable **Message annotations, updates, deletes, and appends** on the `conversations` namespace. See [Configure the channel rule](/docs/ai-transport/getting-started/channel-rules) for the dashboard, Control API, and CLI steps.
+
+
+
## Create the agent route
Create `app/api/chat/route.ts`. The agent receives an [Invocation](/docs/ai-transport/concepts/invocations), creates an [AgentSession](/docs/ai-transport/api/javascript/core/agent-session) pre-bound to `UIMessageCodec`, starts a Run, hydrates the conversation, pipes the LLM stream, and ends the Run.
@@ -107,30 +117,37 @@ export async function POST(req) {
## Create the chat component
-Create `app/chat.tsx`. The component uses Vercel's `useChat` hook with `createChatTransport` from `@ably/ai-transport/vercel`. The Vercel wrapper owns the agent-invocation POST; `useChat` calls into it as if it were the default HTTP transport.
+Create `app/chat.tsx`. The component reads the chat transport from the nearest [`ChatTransportProvider`](/docs/ai-transport/api/react/vercel/chat-transport-provider) with [`useChatTransport`](/docs/ai-transport/api/react/vercel/use-chat-transport) and passes it to Vercel's `useChat` hook. The transport owns the agent-invocation POST; `useChat` calls into it as if it were the default HTTP transport. [`useMessageSync`](/docs/ai-transport/api/react/vercel/use-message-sync) feeds channel updates back into `useChat`, so other clients see messages they did not publish.
```javascript
'use client';
-import { useMemo, useState } from 'react';
+import { useState } from 'react';
import { useChat } from '@ai-sdk/react';
-import { useClientSession } from '@ably/ai-transport/react';
-import { createChatTransport } from '@ably/ai-transport/vercel';
+import { useChatTransport, useMessageSync } from '@ably/ai-transport/vercel/react';
-export function Chat({ chatId }) {
+export function Chat() {
const [input, setInput] = useState('');
- const { session } = useClientSession();
+ const { session, chatTransport, chatTransportError } = useChatTransport();
- const chatTransport = useMemo(() => createChatTransport(session), [session]);
-
- const { messages, sendMessage, status, stop } = useChat({
- id: chatId,
+ const { messages, setMessages, sendMessage, status } = useChat({
transport: chatTransport,
});
+ useMessageSync({ setMessages });
+
+ if (chatTransportError) {
+ return
{messages.map((msg) => (
@@ -164,7 +181,7 @@ export function Chat({ chatId }) {
## Wire it together
-Create `app/page.tsx`. `Providers` sets up an authenticated Ably client. [`ClientSessionProvider`](/docs/ai-transport/api/react/core/providers) constructs the underlying [`ClientSession`](/docs/ai-transport/api/javascript/core/client-session) bound to the channel.
+Create `app/page.tsx`. `Providers` sets up an authenticated Ably client. [`ChatTransportProvider`](/docs/ai-transport/api/react/vercel/chat-transport-provider) constructs the underlying [`ClientSession`](/docs/ai-transport/api/javascript/core/client-session) bound to the channel and the [`ChatTransport`](/docs/ai-transport/api/javascript/vercel/chat-transport) over it. It POSTs invocations to `/api/chat` by default, matching the agent route above; set `api` to point elsewhere.
Update `channelName` to match a namespace with the AIT [channel rules](/docs/ai-transport/getting-started/channel-rules) configured.
@@ -175,8 +192,7 @@ Update `channelName` to match a namespace with the AIT [channel rules](/docs/ai-
import { useEffect, useState } from 'react';
import * as Ably from 'ably';
import { AblyProvider } from 'ably/react';
-import { ClientSessionProvider } from '@ably/ai-transport/react';
-import { UIMessageCodec } from '@ably/ai-transport/vercel';
+import { ChatTransportProvider } from '@ably/ai-transport/vercel/react';
import { Chat } from './chat';
function Providers({ children }) {
@@ -193,12 +209,11 @@ function Providers({ children }) {
}
export default function Page() {
- const chatId = 'conversations:my-chat-session';
return (
-
-
-
+
+
+
);
}
diff --git a/src/pages/docs/ai-transport/index.mdx b/src/pages/docs/ai-transport/index.mdx
index 6e2a80383b..5cc184cd5a 100644
--- a/src/pages/docs/ai-transport/index.mdx
+++ b/src/pages/docs/ai-transport/index.mdx
@@ -46,6 +46,10 @@ AI Transport is for conversations between a user and an AI agent. If you are bui
]}
+
+
## Read next
- [Concepts](/docs/ai-transport/concepts): the building blocks (sessions, turns, transport, codec, conversation tree, infrastructure).