Runtime Hooks

MessageRuntime

Hooks for accessing message state and edit composer.

useAui (Message Actions)

Access message actions via useAui:

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

const aui = useAui();

// Reload an assistant message (regenerate the response)
aui.message().reload();

// Switch to the previous or next branch
aui.message().switchToBranch({ position: "previous" });
aui.message().switchToBranch({ position: "next" });

// Submit feedback on a message
aui.message().submitFeedback({ type: "positive" });
aui.message().submitFeedback({ type: "negative" });

// Get the plain-text content of the message
const text = aui.message().getCopyText();

// Access a message part by index or tool call ID
aui.message().part({ index: 0 });
aui.message().part({ toolCallId: "call_123" });

// Access an attachment by index
aui.message().attachment({ index: 0 });

// Access the edit composer for this message
aui.message().composer();

// Get a snapshot of the full message state
const state = aui.message().getState();
MessageRuntime
path: MessageRuntimePath

composer: EditComposerRuntime

getState: () => MessageState

reload: (config?: ReloadConfig | undefined) => void

speak: () => void

stopSpeaking: () => void

submitFeedback: ({ type }: { type: "positive" | "negative"; }) => void

switchToBranch: ({ position, branchId, }: { position?: "previous" | "next" | undefined; branchId?: string | undefined; }) => void

unstable_getCopyTextunstable: () => string

subscribe: (callback: () => void) => Unsubscribe

getMessagePartByIndex: (idx: number) => MessagePartRuntime

getMessagePartByToolCallId: (toolCallId: string) => MessagePartRuntime

getAttachmentByIndex: (idx: number) => AttachmentRuntime & { source: "message"; }

useAuiState (Message State)

Access message state reactively:

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

const role = useAuiState((s) => s.message.role);
const content = useAuiState((s) => s.message.content);
const isLast = useAuiState((s) => s.message.isLast);
MessageState
status?: { readonly type: "running"; } | { readonly type: "requires-action"; readonly reason: "tool-calls" | "interrupt"; } | { readonly type: "complete"; readonly reason: "stop" | "unknown"; } | { readonly type: "incomplete"; readonly reason: "length" | "tool-calls" | "cancelled" | "content-filter" | "other" | "error"; readonly error?: ReadonlyJSONValue; }

metadata: ({ readonly unstable_state?: ReadonlyJSONValue; readonly unstable_annotations?: readonly ReadonlyJSONValue[]; readonly unstable_data?: readonly ReadonlyJSONValue[]; readonly steps?: readonly ThreadStep[]; readonly submittedFeedback?: { readonly type: "positive" | "negative"; }; readonly timing?: MessageTiming; readonly custom: Record<string, unknown>; } & { readonly unstable_state?: undefined; readonly unstable_annotations?: undefined; readonly unstable_data?: undefined; readonly steps?: undefined; readonly submittedFeedback?: undefined; readonly timing?: undefined; readonly custom: Record<string, unknown>; }) | ({ readonly unstable_state?: ReadonlyJSONValue; readonly unstable_annotations?: readonly ReadonlyJSONValue[]; readonly unstable_data?: readonly ReadonlyJSONValue[]; readonly steps?: readonly ThreadStep[]; readonly submittedFeedback?: { readonly type: "positive" | "negative"; }; readonly timing?: MessageTiming; readonly custom: Record<string, unknown>; } & { readonly unstable_state?: undefined; readonly unstable_annotations?: undefined; readonly unstable_data?: undefined; readonly steps?: undefined; readonly submittedFeedback?: undefined; readonly timing?: undefined; readonly custom: Record<string, unknown>; }) | ({ readonly unstable_state?: ReadonlyJSONValue; readonly unstable_annotations?: readonly ReadonlyJSONValue[]; readonly unstable_data?: readonly ReadonlyJSONValue[]; readonly steps?: readonly ThreadStep[]; readonly submittedFeedback?: { readonly type: "positive" | "negative"; }; readonly timing?: MessageTiming; readonly custom: Record<string, unknown>; } & { readonly unstable_state: ReadonlyJSONValue; readonly unstable_annotations: readonly ReadonlyJSONValue[]; readonly unstable_data: readonly ReadonlyJSONValue[]; readonly steps: readonly ThreadStep[]; readonly submittedFeedback?: { readonly type: "positive" | "negative"; }; readonly timing?: MessageTiming; readonly custom: Record<string, unknown>; })

attachments?: readonly CompleteAttachment[]

id: string

createdAt: Date

role: "system" | "user" | "assistant"

content: readonly [TextMessagePart] | readonly ThreadUserMessagePart[] | readonly ThreadAssistantMessagePart[]

parentId: string | null

index: number

The position of this message in the thread (0 for first message)

isLast: boolean

branchNumber: number

branchCount: number

speech: SpeechState | undefined

submittedFeedback: SubmittedFeedback | undefined

useAuiState (Edit Composer)

Access the edit composer state (used when editing a message):

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

const editText = useAuiState((s) => s.message.composer.text);
const isEditing = useAuiState((s) => s.message.composer.isEditing);
ComposerState
canCancel: boolean

isEditing: boolean

isEmpty: boolean

text: string

role: "system" | "user" | "assistant"

attachments: readonly Attachment[]

runConfig: RunConfig

attachmentAccept: string

dictation: DictationState | undefined

The current state of dictation. Undefined when dictation is not active.

quote: QuoteInfo | undefined

The currently quoted text, if any. Undefined when no quote is set.

type: "thread" | "edit"