Hooks

Reactive hooks for accessing runtime state in React Native.

State Hooks

useAuiState

The primary hook for accessing reactive state. It accepts a selector function for fine-grained re-renders — the component only re-renders when the selected value changes (shallow equality).

import { useAuiState } from "@assistant-ui/react-native";

// Thread state
const messages = useAuiState((s) => s.thread.messages);
const isRunning = useAuiState((s) => s.thread.isRunning);
const isEmpty = useAuiState((s) => s.thread.isEmpty);

// Composer state
const text = useAuiState((s) => s.composer.text);
const composerIsEmpty = useAuiState((s) => s.composer.isEmpty);
const attachments = useAuiState((s) => s.composer.attachments);

// Message state (inside a message context)
const role = useAuiState((s) => s.message.role);
const isLast = useAuiState((s) => s.message.isLast);

// Thread list item state
const threadId = useAuiState((s) => s.threadListItem.id);
const title = useAuiState((s) => s.threadListItem.title);

useAui

Access the store methods for imperative actions.

import { useAui } from "@assistant-ui/react-native";

const aui = useAui();

// Composer actions
aui.composer().setText("Hello");
aui.composer().send();

// Thread actions
aui.thread().cancelRun();

useAuiEvent

Subscribe to events without causing re-renders.

import { useAuiEvent } from "@assistant-ui/react-native";

useAuiEvent("thread.modelContextUpdate", ({ threadId }) => {
  console.log("Model context updated:", threadId);
});

Runtime Hooks

useLocalRuntime

Create an AssistantRuntime with a ChatModelAdapter.

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

const runtime = useLocalRuntime(chatModel, {
  initialMessages: [],
});
OptionTypeDescription
initialMessagesThreadMessageLike[]Messages to pre-populate
maxStepsnumberMaximum tool call steps per run
cloudAssistantCloudOptional cloud instance for persistence
adaptersobjectOptional adapter overrides (see below)
unstable_humanToolNamesstring[]Tool names that pause the run until a result is added via addResult

The adapters option accepts the following fields (all optional):

AdapterTypeDescription
historyThreadHistoryAdapterLoad and save thread message history
attachmentsAttachmentAdapterHandle file and attachment uploads
speechSpeechSynthesisAdapterText-to-speech playback
dictationDictationAdapterSpeech-to-text input
feedbackFeedbackAdapterThumbs up/down feedback
suggestionSuggestionAdapterPrompt suggestions

useRemoteThreadListRuntime

Create an AssistantRuntime with a persistent thread list backed by a RemoteThreadListAdapter. This wraps any runtime hook (such as one calling useLocalRuntime or a custom AI SDK hook) and layers thread-list management on top.

import { useRemoteThreadListRuntime } from "@assistant-ui/react-native";

const runtime = useRemoteThreadListRuntime({
  runtimeHook: () => useLocalRuntime(chatModel),
  adapter: myThreadListAdapter,
});
OptionTypeDescription
runtimeHook() => AssistantRuntimeHook that returns a per-thread runtime
adapterRemoteThreadListAdapterBackend adapter for listing/creating/archiving threads
allowNestingbooleanWhen true, silently becomes a no-op if already inside another useRemoteThreadListRuntime

Model Context Hooks

Tools

Author tools in a "use generative" file with defineToolkit, the same API as on the web (Defining Tools). The tool definition is forwarded to the model; when the model calls it, the execute function runs and the render component displays the result.

Add the @assistant-ui/metro plugin so Metro compiles the "use generative" directive:

metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const { withAui } = require("@assistant-ui/metro");

module.exports = withAui(getDefaultConfig(__dirname));
weather-toolkit.tsx
"use generative";

import { defineToolkit } from "@assistant-ui/react-native";
import { Text, View } from "react-native";
import { z } from "zod";

export default defineToolkit({
  get_weather: {
    description: "Get the current weather for a city",
    parameters: z.object({ city: z.string() }),
    execute: async ({ city }) => {
      "use client";
      const res = await fetch(`https://api.weather.example/${city}`);
      return res.json();
    },
    render: ({ args, result }) => (
      <View>
        <Text>
          {args.city}: {result?.temperature}°F
        </Text>
      </View>
    ),
  },
});
ToolProvider.tsx
import { AuiProvider, Tools, useAui } from "@assistant-ui/react-native";
import toolkit from "./weather-toolkit";

function ToolProvider({ children }: { children: React.ReactNode }) {
  const aui = useAui({ tools: Tools({ toolkit }) });
  return <AuiProvider value={aui}>{children}</AuiProvider>;
}

useAssistantDataUI

Register a UI renderer for a named data message part.

import { useAssistantDataUI } from "@assistant-ui/react-native";

useAssistantDataUI({
  name: "weather_card",
  render: ({ data }) => (
    <View>
      <Text>{data.city}: {data.temperature}°F</Text>
    </View>
  ),
});

useAssistantInstructions

Register system instructions in the model context.

import { useAssistantInstructions } from "@assistant-ui/react-native";

useAssistantInstructions("You are a helpful weather assistant.");

useInlineRender

Wrap a tool UI component so that inline state updates (from a parent component's render) are reflected without remounting. Use this when the render function closes over props that change over time.

my-tool-toolkit.tsx
import { defineToolkit, useInlineRender } from "@assistant-ui/react-native";
import { Text } from "react-native";
import { useMemo } from "react";

export function useMyToolToolkit(someOuterProp: string) {
  const stableRender = useInlineRender(({ args, result }) => (
    <Text>{someOuterProp}: {result?.value}</Text>
  ));

  return useMemo(
    () =>
      defineToolkit({
        my_tool: {
          type: "backend",
          render: stableRender,
        },
      }),
    [stableRender],
  );
}

Import the toolkit hook, pass its result to useAui({ tools: Tools({ toolkit }) }), and provide the returned aui with AuiProvider, as shown in the Tools section above.

makeAssistantDataUI

Create a component that registers a data UI renderer when mounted.

import { makeAssistantDataUI } from "@assistant-ui/react-native";

const WeatherCard = makeAssistantDataUI({
  name: "weather_card",
  render: ({ data }) => <Text>{data.city}: {data.temperature}°F</Text>,
});

<WeatherCard />

Shared Providers

These context providers are re-exported from @assistant-ui/core/react and are used internally by the primitives to scope the aui store to a particular item (message, part, thread list item, etc.). They are available for advanced custom rendering scenarios.

MessageByIndexProvider

Scopes the aui context to a specific message by its index in the thread.

import { MessageByIndexProvider } from "@assistant-ui/react-native";

<MessageByIndexProvider index={2}>
  {/* children can read s.message, s.composer */}
</MessageByIndexProvider>

PartByIndexProvider

Scopes the aui context to a specific message part by its index.

import { PartByIndexProvider } from "@assistant-ui/react-native";

<PartByIndexProvider index={0}>
  {/* children can read s.part */}
</PartByIndexProvider>

TextMessagePartProvider

Provides a synthetic text part context from a plain string. Useful for rendering text outside the normal message-part pipeline.

import { TextMessagePartProvider } from "@assistant-ui/react-native";

<TextMessagePartProvider text="Hello world" isRunning={false}>
  {/* children can read s.part as a text part */}
</TextMessagePartProvider>
PropTypeDescription
textstringThe text content
isRunningbooleanWhether the part is still streaming (default false)

ChainOfThoughtByIndicesProvider

Scopes the aui context to a slice of message parts that form a chain-of-thought block.

import { ChainOfThoughtByIndicesProvider } from "@assistant-ui/react-native";

<ChainOfThoughtByIndicesProvider startIndex={1} endIndex={3}>
  {/* children can read s.chainOfThought */}
</ChainOfThoughtByIndicesProvider>

ChainOfThoughtPartByIndexProvider

Scopes the aui context to a specific part within a chain-of-thought block.

import { ChainOfThoughtPartByIndexProvider } from "@assistant-ui/react-native";

<ChainOfThoughtPartByIndexProvider index={0}>
  {/* children can read s.part */}
</ChainOfThoughtPartByIndexProvider>

ThreadListItemByIndexProvider

Scopes the aui context to a specific thread list item by its index.

import { ThreadListItemByIndexProvider } from "@assistant-ui/react-native";

<ThreadListItemByIndexProvider index={0} archived={false}>
  {/* children can read s.threadListItem */}
</ThreadListItemByIndexProvider>

SuggestionByIndexProvider

Scopes the aui context to a specific suggestion by its index.

import { SuggestionByIndexProvider } from "@assistant-ui/react-native";

<SuggestionByIndexProvider index={0}>
  {/* children can read s.suggestion */}
</SuggestionByIndexProvider>