Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/data/languages/languageData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default {
android: '1.2',
},
aiTransport: {
javascript: '0.2',
javascript: '0.3',
},
spaces: {
javascript: '0.5',
Expand Down
1 change: 1 addition & 0 deletions src/pages/docs/ai-transport/api/errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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).

Expand Down
4 changes: 4 additions & 0 deletions src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-core.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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).

<Aside data-type='important'>
AI Transport requires the **Message annotations, updates, deletes, and appends** [channel rule](/docs/ai-transport/getting-started/channel-rules) on the namespace your conversations live on. Enable it once per Ably app, or streaming fails with error `93002`.
</Aside>

## What Vercel AI SDK Core brings <a id="vercel-brings"/>

| Capability | Description |
Expand Down
4 changes: 4 additions & 0 deletions src/pages/docs/ai-transport/frameworks/vercel-ai-sdk-ui.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ redirect_from:

Ready to build? See [Get started with Vercel AI SDK](/docs/ai-transport/getting-started/vercel-ai-sdk).

<Aside data-type='important'>
AI Transport requires the **Message annotations, updates, deletes, and appends** [channel rule](/docs/ai-transport/getting-started/channel-rules) on the namespace your conversations live on. Enable it once per Ably app, or streaming fails with error `93002`.
</Aside>

## What Vercel AI SDK UI brings <a id="vercel-brings"/>

| Capability | Description |
Expand Down
12 changes: 11 additions & 1 deletion src/pages/docs/ai-transport/getting-started/core-sdk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ To use AI Transport with Vercel's `useChat` for message management, see [Get sta

## Prerequisites <a id="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.

Expand All @@ -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 <a id="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.

<Aside data-type='important'>
This is a one-time setup per Ably app. Without the rule, the first token append fails with error `93002` and no tokens stream. The `channelName` you set below must live in a namespace with this rule enabled.
</Aside>

## Create the agent route <a id="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.
Expand Down
51 changes: 33 additions & 18 deletions src/pages/docs/ai-transport/getting-started/vercel-ai-sdk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ For direct access to the conversation tree, branching, and pagination, see [Get

## Prerequisites <a id="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.

Expand All @@ -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 <a id="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.

<Aside data-type='important'>
This is a one-time setup per Ably app. Without the rule, the first token append fails with error `93002` and no tokens stream. The `channelName` you set below must live in a namespace with this rule enabled.
</Aside>

## Create the agent route <a id="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.
Expand Down Expand Up @@ -107,30 +117,37 @@ export async function POST(req) {

## Create the chat component <a id="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.

<Code>
```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 <div>Failed to connect: {chatTransportError.message}</div>;
}

const isStreaming = status === 'submitted' || status === 'streaming';

const stop = () => {
const activeRun = session.view.runs().find((run) => run.status === 'active');
if (activeRun) void session.cancel(activeRun.runId);
};

return (
<div>
{messages.map((msg) => (
Expand Down Expand Up @@ -164,7 +181,7 @@ export function Chat({ chatId }) {

## Wire it together <a id="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.

Expand All @@ -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 }) {
Expand All @@ -193,12 +209,11 @@ function Providers({ children }) {
}

export default function Page() {
const chatId = 'conversations:my-chat-session';
return (
<Providers>
<ClientSessionProvider channelName={chatId} codec={UIMessageCodec}>
<Chat chatId={chatId} />
</ClientSessionProvider>
<ChatTransportProvider channelName="conversations:my-chat-session">
<Chat />
</ChatTransportProvider>
</Providers>
);
}
Expand Down
4 changes: 4 additions & 0 deletions src/pages/docs/ai-transport/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ AI Transport is for conversations between a user and an AI agent. If you are bui
]}
</Tiles>

<Aside data-type='important'>
AI Transport requires one [channel rule](/docs/ai-transport/getting-started/channel-rules), **Message annotations, updates, deletes, and appends**, enabled on the namespace your conversations live on. It is a one-time setup per Ably app, and streaming fails without it.
</Aside>

## Read next <a id="read-next"/>

- [Concepts](/docs/ai-transport/concepts): the building blocks (sessions, turns, transport, codec, conversation tree, infrastructure).
Expand Down