v0-12
Type
External
Status
Published
Created
Mar 17, 2026
Updated
Mar 17, 2026

Major Architecture Change: Unified State API#

Version 0.12 introduces a complete rewrite of the state management system with a more consistent API.

Automatic Migration#

We provide a codemod to automatically migrate your code:

npx assistant-ui@latest upgrade

This will automatically handle the hook renames and update your imports.

Breaking Changes#

1. Assistant API Hooks Renamed#

The core hooks have been renamed for consistency and clarity:

  • useAssistantApiuseAui
  • useAssistantStateuseAuiState
  • useAssistantEventuseAuiEvent
  • AssistantIfAuiIf

The variable naming convention has also changed from api to aui.

Migration#

Before:

import {
  useAssistantApi,
  useAssistantState,
  useAssistantEvent,
} from "@assistant-ui/react";

function MyComponent() {
  const api = useAssistantApi();
  const isRunning = useAssistantState(({ thread }) => thread.isRunning);

  useAssistantEvent("thread.run-start", () => {
    console.log("Thread started running");
  });

  const handleSend = () => {
    api.composer().send();
  };

  return <button onClick={handleSend}>Send</button>;
}

After:

import { useAui, useAuiState, useAuiEvent } from "@assistant-ui/react";

function MyComponent() {
  const aui = useAui();
  const isRunning = useAuiState((s) => s.thread.isRunning);

  useAuiEvent("thread.runStart", () => {
    console.log("Run started");
  });

  const handleSend = () => {
    aui.composer().send();
  };

  return <button onClick={handleSend}>Send</button>;
}

Automatic Migration:

Run the codemod to automatically update your code:

npx assistant-ui@latest upgrade

The codemod will:

  • Rename all hook imports (useAssistantApiuseAui, etc.)
  • Rename const api = useAui() declarations to const aui = useAui()
  • Update all references to the api variable throughout your codebase
  • Correctly handle scoping (won't rename api variables from other sources)

Backwards Compatibility:

The old names are still available as deprecated exports until v0.13:

// Still works, but deprecated
import {
  useAssistantApi,
  useAssistantState,
  useAssistantEvent,
} from "@assistant-ui/react";

const api = useAssistantApi(); // deprecated but functional

2. Context Hooks Replaced with Unified State API#

All individual context hooks have been replaced with a single useAuiState hook and useAui for actions.

What changed#

The following hooks have been removed:

Removed Hooks:

  • useMessageUtils → Use useAuiState((s) => s.message.isHovering) / useAuiState((s) => s.message.isCopied)
  • useMessageUtilsStore → Use useAui() with aui.message().setIsHovering() / aui.message().setIsCopied()
  • useToolUIs → Removed with no direct equivalent. Use useAssistantTool / makeAssistantToolUI to register tool UIs instead.
  • useToolUIsStore → Removed with no direct equivalent.

Deprecated Hooks:

  • useAssistantRuntime → Use useAui()
  • useThread → Use useAuiState((s) => s.thread)
  • useThreadRuntime → Use useAui() with aui.thread()
  • useMessage → Use useAuiState((s) => s.message)
  • useMessageRuntime → Use useAui() with aui.message()
  • useComposer → Use useAuiState((s) => s.composer)
  • useComposerRuntime → Use useAui() with aui.composer()
  • useEditComposer → Use useAuiState((s) => s.message.composer)
  • useThreadListItem → Use useAuiState((s) => s.threadListItem)
  • useThreadListItemRuntime → Use useAui() with aui.threadListItem()
  • useMessagePart → Use useAuiState((s) => s.part)
  • useMessagePartRuntime → Use useAui() with aui.part()
  • useAttachment → Use useAuiState((s) => s.attachment)
  • useAttachmentRuntime → Use useAui() with aui.attachment()
  • useThreadModelContext → Use useAuiState((s) => s.thread.modelContext)
  • useThreadModelConfig → Removed. Use useAui().thread().getModelContext() instead.
  • useThreadComposer → Use useAuiState((s) => s.thread.composer)
  • useThreadList → Use useAuiState((s) => s.threads)

Migration Examples#

Before:

import {
  useThread,
  useThreadRuntime,
  useComposer,
  useComposerRuntime,
  useMessage,
  useMessageRuntime,
} from "@assistant-ui/react";

function MyComponent() {
  // Reading state
  const messages = useThread((t) => t.messages);
  const isRunning = useThread((t) => t.isRunning);
  const composerText = useComposer((c) => c.text);
  const messageRole = useMessage((m) => m.role);

  // Using runtime for actions
  const threadRuntime = useThreadRuntime();
  const composerRuntime = useComposerRuntime();
  const messageRuntime = useMessageRuntime();

  const handleSend = () => {
    composerRuntime.send();
  };

  const handleReload = () => {
    messageRuntime.reload();
  };

  const handleCancel = () => {
    threadRuntime.cancelRun();
  };

  return null;
}

After:

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

function MyComponent() {
  // Reading state - all through single hook
  const messages = useAuiState((s) => s.thread.messages);
  const isRunning = useAuiState((s) => s.thread.isRunning);
  const composerText = useAuiState((s) => s.composer.text);
  const messageRole = useAuiState((s) => s.message.role);

  // Using client for actions
  const aui = useAui();

  const handleSend = () => {
    aui.composer().send();
  };

  const handleReload = () => {
    aui.message().reload();
  };

  const handleCancel = () => {
    aui.thread().cancelRun();
  };

  return null;
}

3. Event Names Changed to camelCase#

Event names used with useAuiEvent have been standardized to use camelCase instead of kebab-case.

What changed#

The following event names have been updated:

Old Name (kebab-case)New Name (camelCase)
thread.run-startthread.runStart
thread.run-endthread.runEnd
thread.model-context-updatethread.modelContextUpdate
composer.attachment-addcomposer.attachmentAdd
thread-list-item.switched-tothreadListItem.switchedTo
thread-list-item.switched-awaythreadListItem.switchedAway

Events that remain unchanged:

  • thread.initialize
  • composer.send

Migration#

Before:

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

function MyComponent() {
  useAuiEvent("thread.run-start", () => {
    console.log("Thread started running");
  });

  useAuiEvent("thread.run-end", () => {
    console.log("Thread finished running");
  });

  useAuiEvent("composer.attachment-add", () => {
    console.log("Attachment added");
  });

  return null;
}

After:

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

function MyComponent() {
  useAuiEvent("thread.runStart", () => {
    console.log("Thread started running");
  });

  useAuiEvent("thread.runEnd", () => {
    console.log("Thread finished running");
  });

  useAuiEvent("composer.attachmentAdd", () => {
    console.log("Attachment added");
  });

  return null;
}

Automatic Migration:

Run the codemod to automatically update event names:

npx assistant-ui@latest upgrade

The codemod will automatically replace all occurrences of the old kebab-case event names with their new camelCase equivalents.

Getting Help#

If you encounter issues during migration:

  1. Check the updated API documentation for detailed examples
  2. Review the example applications in the repository
  3. Report issues at https://github.com/assistant-ui/assistant-ui/issues