--- title: AI SDK Chat Persistence description: Vercel AI SDK chat with thread persistence — open-source React example combining the AI SDK and assistant-ui for streaming, thread management, and message history. --- import { Base } from "@/components/examples/base";
## Overview This example demonstrates integrating assistant-ui with the Vercel AI SDK for building production-ready chat interfaces. It showcases a complete chat application with thread management, message persistence, and a collapsible sidebar for conversation history. ## Features - **AI SDK Integration**: Seamless connection with Vercel's `ai` package - **Thread Management**: Create, switch, and delete conversation threads - **Collapsible Sidebar**: Toggle sidebar visibility for focused chat - **Model Picker**: Switch between different AI models - **Responsive Design**: Mobile-friendly with sheet-based navigation - **Real-time Streaming**: Live message streaming with loading states ## Quick Start ```bash npm install @assistant-ui/react @assistant-ui/react-ai-sdk ai@^6 @ai-sdk/react@^3 @ai-sdk/openai ``` ## Code ### Client Component ```tsx "use client"; import { AssistantRuntimeProvider } from "@assistant-ui/react"; import { Thread } from "@/components/assistant-ui/thread"; import { useChatRuntime } from "@assistant-ui/react-ai-sdk"; export default function Chat() { const runtime = useChatRuntime(); return (
); } ``` ### API Route ```ts // app/api/chat/route.ts import { openai } from "@ai-sdk/openai"; import { streamText, convertToModelMessages } from "ai"; import type { UIMessage } from "ai"; export async function POST(req: Request) { const { messages }: { messages: UIMessage[] } = await req.json(); const result = streamText({ model: openai("gpt-5.4-nano"), messages: await convertToModelMessages(messages), // Optional: Add system prompt system: "You are a helpful assistant.", }); return result.toUIMessageStreamResponse(); } ``` ### Key Integration Points | Hook/Function | Purpose | |---------------|---------| | `useChatRuntime` | Connects AI SDK to assistant-ui | | `streamText` | Server-side streaming response generation | | `toUIMessageStreamResponse` | Converts stream to Response object | ### Adding Persistence `useChatRuntime()` on its own does not persist threads across reloads. The snippet below is a minimal server-side save sketch. For full thread persistence (history reload, branching) use [Assistant Cloud](/docs/cloud) or the [custom persistence adapter](/docs/integrations/persistence/custom-adapter). To persist conversations, add a database and modify the API route. `useChatRuntime` sends the current thread id as `id` in the request body, so you can read it alongside `messages`: ```ts // In your POST /api/chat handler: const { id: threadId, messages } = await req.json(); // Save the latest user message const last = messages.at(-1); if (last) { await db.messages.create({ threadId, role: last.role, parts: last.parts, }); } // Load messages when opening a thread (e.g., from a ThreadHistoryAdapter): const savedMessages = await db.messages.findMany({ threadId }); ``` ## Source