# Adapters
URL: /docs/react-native/adapters

Persistence and title generation adapters for React Native.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

Adapters customize runtime behavior. They can be passed as options to `useLocalRuntime` or `useRemoteThreadListRuntime`.

## Persistence

By default, `useLocalRuntime` stores threads and messages in memory only -- they are lost when the app restarts. To persist data, use one of these approaches:

### Assistant Cloud

The simplest way to add persistence. Pass a `cloud` option to `useLocalRuntime`:

```
import { useLocalRuntime } from "@assistant-ui/react-native";
import { AssistantCloud } from "@assistant-ui/cloud";

const cloud = new AssistantCloud({
  baseUrl: "https://backend.assistant-ui.com",
  authToken: () => fetchTokenFromYourBackend(),
});

const runtime = useLocalRuntime(chatModel, { cloud });
```

This gives you multi-thread support with server-side persistence, cross-device sync, and automatic title generation.

### History adapter

For custom persistence (e.g. saving message history to your own backend), pass a `ThreadHistoryAdapter` via `adapters.history`:

```
import { useLocalRuntime } from "@assistant-ui/react-native";
import type { ThreadHistoryAdapter } from "@assistant-ui/react-native";

const myHistoryAdapter: ThreadHistoryAdapter = {
  async load() {
    // Load saved messages from your storage
    const data = await fetchMessagesFromBackend();
    return data; // { headId, messages }
  },
  async append(item) {
    // Persist a new message
    await saveMessageToBackend(item);
  },
};

const runtime = useLocalRuntime(chatModel, {
  adapters: {
    history: myHistoryAdapter,
  },
});
```

### RemoteThreadListAdapter

For full backend thread management (thread list, archiving, cross-device sync), use `useRemoteThreadListRuntime`. See the [Custom Backend](/docs/react-native/custom-backend) page for a full example.

## RemoteThreadListAdapter

Title generation is configured via the `generateTitle` method on `RemoteThreadListAdapter`. See the [Custom Backend](/docs/react-native/custom-backend) page for a full example.

```
import type { RemoteThreadListAdapter } from "@assistant-ui/react-native";
import { createAssistantStream } from "assistant-stream";

const myAdapter: RemoteThreadListAdapter = {
  // ... other methods ...

  async generateTitle(remoteId, unstable_messages) {
    return createAssistantStream(async (controller) => {
      const res = await fetch(`/api/threads/${remoteId}/title`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ messages: unstable_messages }),
      });
      const { title } = await res.json();
      controller.appendText(title);
    });
  },
};
```

## Which option to choose?

|                       | ChatModelAdapter + `useLocalRuntime` | RemoteThreadListAdapter + `useRemoteThreadListRuntime` |
| --------------------- | ------------------------------------ | ------------------------------------------------------ |
| **Thread storage**    | In-memory (or cloud)                 | Your backend                                           |
| **Message storage**   | In-memory (can add history adapter)  | In-memory (can add history adapter for server-side)    |
| **Cross-device sync** | Only with cloud                      | Yes                                                    |
| **Setup complexity**  | Minimal                              | Moderate                                               |
| **Best for**          | Single-device apps, prototypes       | Production apps with user accounts                     |