Runtime Hooks

Runtime creation hooks for local, remote, cloud, external-store, and AI SDK powered assistant-ui chat experiences.

API Reference

useCloudThreadListRuntime

useCloudThreadListRuntime
optionsCloudThreadListAdapter

CloudThreadListAdapter
cloudAssistantCloud

AssistantCloud
threadsAssistantCloudThreads

AssistantCloudThreads
messagesAssistantCloudThreadMessages

cloudAssistantCloudAPI

list(query?: AssistantCloudThreadsListQuery) => Promise<AssistantCloudThreadsListResponse>

get(threadId: string) => Promise<CloudThread>

create(body: AssistantCloudThreadsCreateBody) => Promise<AssistantCloudThreadsCreateResponse>

update(threadId: string, body: AssistantCloudThreadsUpdateBody) => Promise<void>

claim(body: AssistantCloudThreadsClaimBody) => Promise<AssistantCloudThreadsClaimResponse>

Moves every thread of the anonymous identity behind `refresh_token` into the caller's workspace.

delete(threadId: string) => Promise<void>

projectsAssistantCloudProjects

AssistantCloudProjects
threadsAssistantCloudProjectThreads

auth__object

__object
tokensAssistantCloudAuthTokens

runsAssistantCloudRuns

AssistantCloudRuns
cloudAssistantCloudAPI

stream(body: AssistantCloudRunsStreamBody) => Promise<AssistantStream>

report(body: AssistantCloudRunReport) => Promise<{ run_id: string; }>

filesAssistantCloudFiles

AssistantCloudFiles
cloudAssistantCloudAPI

pdfToImages(body: PdfToImagesRequestBody) => Promise<PdfToImagesResponse>

generatePresignedUploadUrl(body: GeneratePresignedUploadUrlRequestBody) => Promise<GeneratePresignedUploadUrlResponse>

generatePresignedDownloadUrl(body: { key: string; } | { url: string; }) => Promise<GeneratePresignedDownloadUrlResponse>

eventsAssistantCloudEvents

AssistantCloudEvents
bufferAssistantCloudEvent[]

timer?ReturnType<typeof setTimeout> | undefined

flushing?Promise<void> | undefined

cloudAssistantCloudAPI

isEnabled() => boolean

listeningboolean

track(event: AssistantCloudEvent) => void

listen() => void

unlisten() => void

dispose() => void

onVisibilityChange() => void

flush() => Promise<void>

flushPending() => Promise<void>

scheduleFlush() => void

clearFlushTimer() => void

scoresAssistantCloudScores

AssistantCloudScores
cloudAssistantCloudAPI

create(body: AssistantCloudScoreBody) => Promise<AssistantCloudScoreResponse>

telemetryAssistantCloudTelemetryConfig

AssistantCloudTelemetryConfig
enabled?boolean

Enables Assistant Cloud telemetry. Defaults to `true`. Set to `false` to disable both run reports and engagement events.

events?boolean

Enables Assistant Cloud engagement events. Defaults to `true` when telemetry is enabled. Set to `false` to keep run reports while disabling engagement events.

release?string

environment?string

tags?string[]

beforeReport?( report: AssistantCloudRunReport, ) => AssistantCloudRunReport | null

Called before each telemetry report is sent. Return a modified report to enrich it (e.g. add `model_id`), or return `null` to skip the report.

registerSdk(sdk: SdkIdentity) => void

runtimeHook() => AssistantRuntime

create?() => Promise<ThreadData>

delete?(threadId: string) => Promise<void>

useLocalRuntime

useLocalRuntime
chatModelChatModelAdapter

ChatModelAdapter
run(options: ChatModelRunOptions) => Promise<ChatModelRunResult> | AsyncGenerator<ChatModelRunResult, void>

options?LocalRuntimeOptions

LocalRuntimeOptions
maxSteps?number | undefined

unstable_humanToolNames?string[] | undefinedunstable

Names of tools that pause the run until a result is supplied via `addToolResult`.

unstable_enableMessageQueue?boolean | undefinedunstable

Opt in to message queuing: a message sent during a run is held in `composer.queue` and sent once the run settles. Steering runs it next.

unstable_queueClearOnRewind?boolean | undefineddeprecatedunstable

Auto-clear the message queue when the thread rewinds (message edit). Defaults to `true`.

Deprecated: Removal after 2026-11-05 — the queue will always survive rewinds.

unstable_queueClearOnCancel?boolean | undefineddeprecatedunstable

Auto-clear the message queue when the user cancels the run. Defaults to `true`. When `false`, cancel pauses the queue and keeps the pending items; the next send drains them.

Deprecated: Removal after 2026-11-05 — cancel will always pause the queue and keep the items.

cloud?AssistantCloud | undefined

LocalRuntimeOptions["cloud"]
threadsAssistantCloudThreads

AssistantCloudThreads
messagesAssistantCloudThreadMessages

cloudAssistantCloudAPI

list(query?: AssistantCloudThreadsListQuery) => Promise<AssistantCloudThreadsListResponse>

get(threadId: string) => Promise<CloudThread>

create(body: AssistantCloudThreadsCreateBody) => Promise<AssistantCloudThreadsCreateResponse>

update(threadId: string, body: AssistantCloudThreadsUpdateBody) => Promise<void>

claim(body: AssistantCloudThreadsClaimBody) => Promise<AssistantCloudThreadsClaimResponse>

Moves every thread of the anonymous identity behind `refresh_token` into the caller's workspace.

delete(threadId: string) => Promise<void>

projectsAssistantCloudProjects

AssistantCloudProjects
threadsAssistantCloudProjectThreads

auth__object

__object
tokensAssistantCloudAuthTokens

runsAssistantCloudRuns

AssistantCloudRuns
cloudAssistantCloudAPI

stream(body: AssistantCloudRunsStreamBody) => Promise<AssistantStream>

report(body: AssistantCloudRunReport) => Promise<{ run_id: string; }>

filesAssistantCloudFiles

AssistantCloudFiles
cloudAssistantCloudAPI

pdfToImages(body: PdfToImagesRequestBody) => Promise<PdfToImagesResponse>

generatePresignedUploadUrl(body: GeneratePresignedUploadUrlRequestBody) => Promise<GeneratePresignedUploadUrlResponse>

generatePresignedDownloadUrl(body: { key: string; } | { url: string; }) => Promise<GeneratePresignedDownloadUrlResponse>

eventsAssistantCloudEvents

AssistantCloudEvents
bufferAssistantCloudEvent[]

timer?ReturnType<typeof setTimeout> | undefined

flushing?Promise<void> | undefined

cloudAssistantCloudAPI

isEnabled() => boolean

listeningboolean

track(event: AssistantCloudEvent) => void

listen() => void

unlisten() => void

dispose() => void

onVisibilityChange() => void

flush() => Promise<void>

flushPending() => Promise<void>

scheduleFlush() => void

clearFlushTimer() => void

scoresAssistantCloudScores

AssistantCloudScores
cloudAssistantCloudAPI

create(body: AssistantCloudScoreBody) => Promise<AssistantCloudScoreResponse>

telemetryAssistantCloudTelemetryConfig

AssistantCloudTelemetryConfig
enabled?boolean

Enables Assistant Cloud telemetry. Defaults to `true`. Set to `false` to disable both run reports and engagement events.

events?boolean

Enables Assistant Cloud engagement events. Defaults to `true` when telemetry is enabled. Set to `false` to keep run reports while disabling engagement events.

release?string

environment?string

tags?string[]

beforeReport?( report: AssistantCloudRunReport, ) => AssistantCloudRunReport | null

Called before each telemetry report is sent. Return a modified report to enrich it (e.g. add `model_id`), or return `null` to skip the report.

registerSdk(sdk: SdkIdentity) => void

initialMessages?readonly ThreadMessageLike[] | undefined

adapters?Omit<LocalRuntimeOptionsBase["adapters"], "chatModel"> | undefined

LocalRuntimeOptions["adapters"]
attachments?AttachmentAdapter | undefined

LocalRuntimeOptions["adapters"]["attachments"]
acceptstring

add(state: { file: File; }) => Promise<PendingAttachment> | AsyncGenerator<PendingAttachment, void>

remove(attachment: Attachment) => Promise<void>

send(attachment: PendingAttachment) => Promise<CompleteAttachment>

suggestion?SuggestionAdapter | undefined

LocalRuntimeOptions["adapters"]["suggestion"]
generate( options: SuggestionAdapterGenerateOptions, ) => | Promise<readonly ThreadSuggestion[]> | AsyncGenerator<readonly ThreadSuggestion[], void>

voice?RealtimeVoiceAdapter | undefined

LocalRuntimeOptions["adapters"]["voice"]
connect(options: { abortSignal?: AbortSignal; }) => RealtimeVoiceAdapter.Session

dictation?DictationAdapter | undefined

LocalRuntimeOptions["adapters"]["dictation"]
listen() => DictationAdapter.Session

disableInputDuringDictation?boolean

speech?SpeechSynthesisAdapter | undefined

LocalRuntimeOptions["adapters"]["speech"]
speak(text: string) => SpeechSynthesisAdapter.Utterance

feedback?FeedbackAdapter | undefined

LocalRuntimeOptions["adapters"]["feedback"]
submit(feedback: FeedbackAdapterFeedback) => void

history?ThreadHistoryAdapter | undefined

LocalRuntimeOptions["adapters"]["history"]
load() => Promise<ExportedMessageRepository & { state?: ReadonlyJSONValue; unstable_resume?: boolean; }>

resume?(options: ChatModelRunOptions) => AsyncGenerator<ChatModelRunResult, void, unknown>

append(item: ExportedMessageRepositoryItem) => Promise<void>

update?(item: ExportedMessageRepositoryItem) => Promise<void>

Rewrites a previously appended message in place, keyed by its message id. Adapters that implement this let a runtime persist a run paused for tool approval and finalize the same message once the run resumes. An update may arrive for an id whose earlier write failed; treat it as an upsert keyed on the message id rather than assuming the entry exists.

delete?(items: ExportedMessageRepositoryItem[]) => Promise<void>

withFormat?<TMessage, TStorageFormat extends Record<string, unknown>>(formatAdapter: MessageFormatAdapter<TMessage, TStorageFormat>) => GenericThreadHistoryAdapter<TMessage>

Required when used with `useAISDKRuntime` / `useChatRuntime`.

useRemoteThreadListRuntime

useRemoteThreadListRuntime
optionsRemoteThreadListOptions

RemoteThreadListOptions
runtimeHook() => AssistantRuntime

adapterRemoteThreadListAdapter

The adapter reference should remain stable across renders. Replacing it reloads the list and drops cached threads that are not in the replacement page. In-flight mutations from the previous adapter are cancelled.

RemoteThreadListAdapter
list(params?: RemoteThreadListPageOptions) => Promise<RemoteThreadListResponse>

rename(remoteId: string, newTitle: string) => Promise<void>

updateCustom?(remoteId: string, custom: Record<string, unknown> | undefined) => Promise<void>

archive(remoteId: string) => Promise<void>

unarchive(remoteId: string) => Promise<void>

delete(remoteId: string) => Promise<void>

initialize(threadId: string) => Promise<RemoteThreadInitializeResponse>

generateTitle(remoteId: string, unstable_messages: readonly ThreadMessage[]) => Promise<AssistantStream>

Generates a title for the thread and streams it back. When the generation persists the title itself, the returned stream must not complete before that write has landed. Concurrent generations are ordered by stream completion, and a run whose write outlives its stream can overwrite a newer title.

fetch(threadId: string) => Promise<RemoteThreadMetadata>

unstable_Provider?RemoteThreadListProviderComponent | undefinedunstable

Optional React component wrapped around each active thread. Use it to inject per-thread context such as a history or attachments adapter (see `useCloudThreadListAdapter` for the canonical shape). `useRemoteThreadListRuntime` renders this component when present. If it is omitted, that host synthesizes a `RuntimeAdapterProvider` from `unstable_useAdapters`. The `RemoteThreadList` store entry ignores it; expose `unstable_useAdapters` for that host. The Provider must render `children` on its first commit; deferring them behind a loading state, a Suspense boundary, or a `useEffect`-gated render is unsupported and leaves thread context unavailable to downstream consumers. Load data inside an always-mounted child instead.

unstable_useAdapters?(() => RuntimeAdapters | null | undefined) | undefinedunstable

Hook the `RemoteThreadList` store entry calls once per mounted thread body (the main-thread slot by default; every started thread with `backgroundThreads`), then provides to the `thread` factory. This is not mounted per listed thread. `useRemoteThreadListRuntime` also calls it when `unstable_Provider` is omitted. Resolve `threadListItem` lazily on each adapter call; do not capture it at hook mount. The hook must keep a stable hook count across adapter swaps; a different count throws. Memoize the returned object. Per-thread history also requires the `thread` factory to be keyed by thread id (`withKey(id, thread(...))`). History loaders such as `useExternalHistory` run once per mount; an unkeyed factory keeps one instance across switches and the next thread's messages never load.

initialThreadId?string | undefineddeprecated

When provided, the runtime starts on this thread instead of creating a new empty thread. Useful for URL-based routing (e.g. `/chat/[threadId]`) where the initial thread is known at mount time.

Deprecated: Use `threadId` instead, which also reacts to subsequent changes.

threadId?string | undefined

The current thread ID to display. When this value changes, the runtime automatically switches to the specified thread. Set to `undefined` to switch to a new thread.

onThreadIdChange?((threadId: string | undefined) => void) | undefined

Called whenever the runtime changes the active thread's canonical (remote) ID, so the value can be treated as a managed/controlled variable (e.g. synced to a URL query param). Changes initiated by the controlled `threadId` option are not echoed back. Together these options form the controlled pattern: `threadId` in, `onThreadIdChange` out. Only the settled remote ID is emitted: while a freshly created thread is still optimistic (no remote ID yet) the value is `undefined`, and the real ID is emitted once the thread is initialized. The transient local ID is never surfaced.

allowNesting?boolean | undefined

When true, if this runtime is used inside another RemoteThreadListRuntime, it becomes a no-op and simply calls the runtimeHook directly. This allows wrapping runtimes that internally use RemoteThreadListRuntime.