Increasingly, the best software is built around collaboration: people and AI
agents working together in the same documents, in realtime. Live presence,
conflict-free editing, comments, and notifications are becoming the baseline for
modern productivity apps, and not just extras bolted on at the end.

To show what that future looks like, we built an AI slideshow editor. It’s one
example of this new kind of app—a shared canvas where humans and agents
collaborate, each able to see and build on the other’s work as it happens.

<Figure
  caption={
    <>
      <a href="https://slides-example.liveblocks.io/">
        slides-example.liveblocks.io
      </a>
    </>
  }
>
  <MuxVideo
    playbackId="2Bump2kIqXQCsTv5FDNl8SFM5L18XgXPcDnIENZyWWc"
    alt="AI slideshow editor"
    static={true}
  />
</Figure>

Here’s what makes an app like this work, and how you can build the same
foundation into your own product with Liveblocks.

- [Agents as participants, not background jobs](#agents-as-participants): AI
  working amongst humans.
- [Sync engines are necessary](#sync-engines-are-necessary): Humans and agents
  editing simultaneously.
- [Context is everything](#context-is-everything): No explaining, AI should
  already understand.

## Agents as participants, not background jobs [#agents-as-participants]

In the apps of the future, agents won’t run as invisible background jobs—they’ll
be participants you can watch working alongside you. When an AI makes a change,
every connected user should feel their presence and see their modifications
happen in realtime, like you would with a human collaborator.

<Figure>
  <MuxVideo
    playbackId="re02TkBsdDS5t5WgMMngFgXw9FTliioETv00r98XSAOxs"
    alt="AI generates slides"
    static={true}
  />
</Figure>

Live presence is the first thing that makes a productivity app feel alive, and
in this future it applies to agents too. Any server-side workflow or agent
should be able to connect to your app, make changes, and broadcast where it
is—so everyone can see what it’s working on, not just the result when it’s done.

### Agent presence

Presence is especially simple with Liveblocks, and can be slotted into any
workflow and app in minutes. Let’s take a look a simple example of an agent
editing a title field.

<Figure>
  <MuxVideo
    playbackId="hYVTbg021JJUa2BZuSPVrWAtMrMp8bSgs00y01SOPWXvfA"
    alt="AI makes an edit"
    static={true}
  />
</Figure>

To build this, call
[`setPresence`](/docs/api-reference/liveblocks-node#post-rooms-roomId-presence)
from your back end with the agent’s information and presence data, and it
appears live in the room like any other user.

```ts title="Node.js back end"
await liveblocks.setPresence("my-room-id", {
  // +++
  userId: "agent-123",
  // +++

  userInfo: { name: "Agent" },

  data: {
    // +++
    editing: "title-1",
    status: "Thinking…",
    // +++
  },
});
```

In the front-end, you can fetch the agent’s presence data with
[`useOthers`](/docs/api-reference/liveblocks-react#useOthers), and render custom
presence UI with it. `useOthers` returns a list of every connected users, so
we’ll filter the results to only return the agent.

```tsx
function AgentPresence() {
  const others = useOthers();
  const agent = others.find(({ id }) => id === "agent-123");

  // { editing: "title-1", status: "Thinking…" }
  console.log(agent.presence);

  return <Cursor presence={agent.presence} />;
}
```

Learn more in our documentation under
[get started with agent presence](/docs/get-started/nextjs-ai-presence).

## Sync engines are necessary [#sync-engines-are-necessary]

For humans and agents to coexist in the same document, you need a sync engine.
Editing the same data simultaneously, without overwriting each other’s work, is
hard—and it’s the problem every productivity app eventually runs into.

<Figure>
  <MuxVideo
    playbackId="E601iU3GeS7QcFhnGZ6dwVVUO9KiBU00fxpKqT02KK87zo"
    alt="Humans and agents editing simultaneously"
    static={true}
  />
</Figure>

With one in place, any number of humans and agents can work together at once.
Each change is merged and resolved automatically, so nobody’s edits get lost—no
matter how many collaborators, human or otherwise, are in the room. The best
sync engines capture the intent behind every change, not just the final state—so
when you change the theme, the text someone else is editing stays untouched.

<Figure>
  <MuxVideo
    playbackId="Tp0002nXT7pCu7EAj9sP1YznL3TxAA9M00pMQQ2bxyCwgo"
    alt="Humans and agents editing simultaneously"
    static={true}
  />
</Figure>

### Liveblocks Storage [#liveblocks-storage]

[Liveblocks Storage](/docs/products/multiplayer-editing/sync-engine/liveblocks-storage)
is our sync engine designed to power apps like Pitch and Figma, and it works by
using the intent behind changes to automatically merge conflicting changes into
a coherent state. In the slideshow editor, the slides, text elements, and themes
all live in Storage.

<Figure>
  <MuxVideo
    playbackId="7RpQA01LuAOjkNyZvp01Y7Zp01Y9MWh73YGamApaLpMT5c"
    alt="Everything is in Storage"
    static={true}
  />
</Figure>

To change a background color, like in the video above, fetch the current
background color with
[`useStorage`](/docs/api-reference/liveblocks-react#useStorage), and create a
function to change it with
[`useMutation`](/docs/api-reference/liveblocks-react#useMutation).

```tsx
function BackgroundPicker() {
  const background = useStorage((root) => root.background);

  const setBackground = useMutation(({ storage }, newColor: string) => {
    storage.set("background", newColor);
  });

  return <ColorPicker value={background} onChange={setBackground} />;
}
```

You can also make modifications to Liveblocks Storage from the server with
[`mutateStorage`](/docs/api-reference/liveblocks-node#mutate-storage), which is
how agents edit the same document as your users.

```ts title="Node.js back end"
const { text: background } = await generateText({
  model: openai("gpt-5.5"),
  prompt: `Select a background hex code. User prompt: ${prompt}`,
});

await liveblocks.mutateStorage("my-room-id", async ({ root }) => {
  // +++
  root.set("background", background);
  // +++
});
```

All changes made from the client or server are sent in realtime to every
connected user, and conflicts are automatically resolved. Learn more in our
documentation under
[get started with multiplayer editing](/docs/get-started/nextjs).

## Context is everything [#context-is-everything]

AI without context is rarely useful. Ask an agent to “make this larger” in a
generic chat window and it has to guess what “this” is, and a confident wrong
guess is worse than no answer at all. Additionally, when AI work together with
humans, it’s particularly helpful to read the conversation before the agent was
called into action.

Commenting sections are a natural interface for requesting work, whether from an
agent or a teammate. Threads can be anchored to specific elements on the page,
so “this” is never ambiguous, and the AI has the context it needs from the
conversation to work effectively.

<Figure>
  <MuxVideo
    playbackId="E2MSQPhiZ029Fkf0077lMhov3ohDEnSrqwngfvlQm301EU"
    alt="Comments that trigger agents"
    static={true}
  />
</Figure>

### Comments

Our [Comments](/comments) components provide ready-made commenting you can
integrate into your app. With
[`useThreads`](/docs/api-reference/liveblocks-react#useThreads), you can fetch
the threads in the current room, and render them with the
[`Thread`](/docs/api-reference/liveblocks-react-ui#Thread) component.

```tsx
function Comments() {
  const { threads } = useThreads();

  return threads.map((thread) => <Thread key={thread.id} thread={thread} />);
}
```

Users can create new threads with
[`Composer`](/docs/api-reference/liveblocks-react-ui#Composer). To attach a new
thread to a specific element on the page, you can use metadata to reference the
element. You can also add the AI assistant as a user you can `@` mention inside
the composer, helpful for triggering the request.

```tsx
function Comments() {
  return <Composer metadata={{ element: "title-1" }}>;
}
```

To pass the thread’s context into the agent, use
[`getThread`](/docs/api-reference/liveblocks-node#get-rooms-roomId-threads-threadId)
in your back end.

```ts title="Node.js back end"
const thread = await liveblocks.getThread("my-room-id", "thread-123");

const { text } = await generateText({
  model: openai("gpt-5.5"),
  prompt: `
    A user requested a change, see the latest message.
    The thread is anchored to ${thread.metadata.element}.
  `,
  messages: thread.comments.map((comment) => ({
    role: comment.user.id === "agent-123" ? "assistant" : "user",
    content: comment.text,
  })),
});
```

Learn more in our documentation under
[get started with AI comments](/docs/get-started/nextjs-comments-ai).

### Notifications

Additionally, when a user is tagged in a comment, instead of an agent, they’ll
receive a new
[notification](/docs/products/comments/email-and-slack-notifications) in their
inbox. The same primitives that power agent collaboration power human
collaboration too.

<Figure>
  <MuxVideo
    playbackId="V8T7XKLZhuWquZ2mR802YbPi1H5rwHKBeGxvV02spmxm4"
    alt="Comments and notifications for people"
    static={true}
  />
</Figure>

Learn more in our documentation under
[get started with notifications](/docs/get-started/nextjs-notifications-in-app).

## The apps that will define the next decade

AI agents are becoming native users of software. They need to read, write, and
coordinate inside the same documents as humans, with the same presence,
conflict-free editing, and comments that people rely on. The slideshow editor is
just one example—the same foundation works for design tools, docs, whiteboards,
dashboards, and anything else people build together.

The apps that get this right will feel like the future. The ones that don’t will
feel like single-player tools with a chatbot bolted on.

## Get started now

If you’d like to build the next generation of productivity apps, get started
with Liveblocks now.

<ButtonLink href="/docs/get-started" size="lg">
  Get started now
</ButtonLink>

## Contributors

<Contributors gitHubUsernames={["jrowny", "pierrelevaillant"]} />