AI Copilots - Hooks

The AI Copilots React hooks allow you to fetch, create, and modify AI chats, enabling you to build custom AI interfaces, even beyond our default components. Chats are stored permanently and the infrastructure is handled for you. All hooks work optimistically, meaning they update immediately, before the server has synched.

List a user’s chats

Each authenticated user has their own private set of chats, and the useAiChats hook fetches all AI chats created by the current user. It’s easy to create a list of chats, with links or buttons that take you to each.

import { useAiChats } from "@liveblocks/react/suspense";
function ListChats() { const { chats } = useAiChats();
return ( <nav> {chats.map((chat) => ( <a key={chat.id} href={`/chats/${chat.id}`}> {chat.title || "Untitled"} </a> ))} </nav> );}

Chats are paginated, returning 50 at a time, and you can filter chats by metadata. There are also ways to handle errors.

Create & delete chats

The useCreateAiChat and useDeleteAiChat hooks allow you to create and delete AI chats. When used in combination with the useAiChats hook, you can add “New Chat” and “Delete Chat” buttons to your listing.

import {  useAiChats,  useCreateAiChat,  useDeleteAiChat,} from "@liveblocks/react/suspense";
function ListChats() { const { chats } = useAiChats(); const createAiChat = useCreateAiChat(); const deleteAiChat = useDeleteAiChat();
return ( <nav> <button onClick={() => createAiChat("my-ai-chat")}>💬 New Chat</button> {chats.map((chat) => ( <a key={chat.id} href={`/chats/${chat.id}`}> {chat.title || "Untitled"} <button onClick={() => deleteAiChat(chat.id)}>❌ Delete chat</button> </a> ))} </nav> );}

When an AI chat is created, a title is automatically generated from the first messages. You can optionally set this title, and add custom metadata to the chat.

createAiChat({  id: "my-ai-chat",  title: "My AI Chat",  metadata: {    color: "red",    tags: ["product", "engineering"],  },});

Send messages to a chat

The useSendAiMessage hook allows you to send messages directly to a chat, as if from a user. This works really well in combination with buttons in your UI, for example you may have a “Explain with AI” button.

import { useSendAiMessage } from "@liveblocks/react/suspense";
function ExplainWithAi() { const sendAiMessage = useSendAiMessage("my-chat-id", { copilotId: "co_h7GBa3...", });
return ( <button onClick={() => sendAiMessage("Explain how this page works")}> Explain with AI </button> );}

Additionally, when using AiChat you can use the hook to display suggestion buttons in the empty state.

import { useSendAiMessage } from "@liveblocks/react/suspense";import { AiChat } from "@liveblocks/react-ui";
function Chat() { const sendAiMessage = useSendAiMessage("my-chat-id", { copilotId: "co_h7GBa3...", });
return ( <AiChat chatId="my-chat-id" copilotId="co_h7GBa3..." components={{ Empty: ( <div> <div>How can I help you?</div> <button onClick={() => sendAiMessage("What's new?")}> Update me </button> <button onClick={() => sendAiMessage("Create a new document")}> Draft a document </button> </div> ), }} /> );}

Get a chat’s information

The useAiChat hook allows you to fetch a chat’s title and custom metadata.

import { useAiChat } from "@liveblocks/react/suspense";
function ChatTitle({ chatId }: { chatId: string }) { const { chat } = useAiChat(chatId);
return <h1>{chat.title || "Untitled chat"}</h1>;}

Get a chat’s status

The useAiChatStatus hook allows you to fetch the status of an AI chat, indicating whether it’s idle or currently generating content. This is helpful for displaying a loading state or freezing part of your app while content is generating.

import { useAiChatStatus } from "@liveblocks/react/suspense";
function ChatStatus({ chatId }: { chatId: string }) { const { status } = useAiChatStatus(chatId);
return status === "idle" ? <div>🟢 Ready</div> : <div>🟡 Generating…</div>;}

Hook types

There are two different ways to use many Liveblocks hooks; with React Suspense, and without it. We recommend using the Suspense versions, as they often result in simpler code.

Suspense hooks

Using Suspense hooks means that any data retrieved, for example chats from useAiChats, will never be undefined, and your component will never see an error.

import { useAiChats } from "@liveblocks/react/suspense";
// Suspense: `chats` is always definedfunction MyAiChats() { const { chats } = useAiChats();
// [{ id: "th_sf8s6sh...", title: "...", ... }, ...] console.log(chats);}

To catch errors and display a loading screen, you can use ErrorBoundary and ClientSideSuspense.

import { ClientSideSuspense } from "@liveblocks/react/suspense";import { ErrorBoundary } from "react-error-boundary";
// Handle errors and loading state in the component abovefunction Component() { return ( <ErrorBoundary fallback={<div>Error</div>}> <ClientSideSuspense fallback={<div>Loading...</div>}> <MyAiChats /> </ClientSideSuspense> </ErrorBoundary> );}

To use Suspense, make sure you’re exporting your hooks from @liveblocks/react/suspense.

// Suspense version of hooksimport { useAiChats, useAiChatMessages } from "@liveblocks/react/suspense";//                                                               ^^^^^^^^

Regular hooks

The regular versions of Liveblocks hooks require you to check for error and isLoading properties. You can then handle these states in the same component.

import { useAiChats } from "@liveblocks/react";
// Handle errors and loading state in the same componentfunction MyAiChats() { const { chats, error, isLoading } = useAiChats();
if (error) { return <div>Error</div>; }
if (isLoading) { return <div>Loading...</div>; }
// Non-Suspense: `chats` is only defined AFTER the `if` checks // [{ id: "th_sf8s6sh...", title: "...", ... }, ...] console.log(chats);}

To use the regular hooks, make sure you’re exporting from @liveblocks/react.

// Regular version of hooksimport { useAiChats, useAiChatMessages } from "@liveblocks/react";//                                             ^^^^^^^^^^^^^^^^^

We use cookies to collect data to improve your experience on our site. Read our Privacy Policy to learn more.