assistant-ui accessibility
Add paced screen-reader updates to an assistant-ui thread without replaying messages already present in its history.
Install the assistant-ui adapter
Install @generative-a11y/core, @generative-a11y/dom, and @generative-a11y/assistant-ui beside assistant-ui. The adapter subscribes to a thread runtime you already own and leaves rendering, actions, and focus behavior with the host application.
Connect an existing thread runtime
bindThreadRuntime reads only getState and subscribe. It cannot run thread actions, render an interface, or dispose your core runtime.
import { bindThreadRuntime } from "@generative-a11y/assistant-ui";
const binding = bindThreadRuntime({
runtime,
scopeId: "support-thread",
thread,
});
// Removes only the subscription it created.
binding.dispose();How this code works
- 01Pass the public thread
Your adapter needs only getState and subscribe, so it cannot invoke composer, message, or run actions.
- 02Namespace framework IDs
scopeIdprevents identical message and tool IDs from colliding across mounted threads. - 03Record existing history
bindThreadRuntime records existing messages at startup and skips old content after hydration.
- 04Dispose the subscription
Returned cleanup stops observation while leaving assistant-ui and core running.
Options and return values
runtimePick<GenerativeA11yRuntime, 'dispatch'>Required
The runtime that receives events from this adapter. Your app owns it.
- Default
none
scopeIdstringRequired
A stable namespace for assistant messages, tools, approvals, and sources in this thread.
- Default
none
threadPick<ThreadRuntime, 'getState' | 'subscribe'>Required
The documented assistant-ui thread interface. The adapter does not read actions or private state.
- Default
none
maxTrackedEntitiesnumberOptional
Bounds tracked response, tool, approval, source, and text-part identities.
- Default
1000
dispose()voidReturn
Stops the subscription and clears adapter records. It does not dispose the thread or runtime supplied by your app.
- Default
n/a
Lifecycle mapping
Documented thread state supplies response text, final states, tool progress, approvals, and sources. The binding records existing history before it starts dispatching, which prevents old messages from becoming new announcements after hydration.
Expected screen-reader behavior
New response text becomes paced announcement intents. Tool and approval changes receive priority based on the shared policy, while routine status changes leave focus in place. Browser transcripts show what the DOM package wrote; confirm spoken output with the screen readers and browsers your application supports.
What public state cannot prove
Your adapter can report streaming, known final states, tools, approvals, and sources. assistant-ui does not provide general retry or connection events, so generative-a11y does not guess.
Troubleshooting
Repeated historical messages can indicate that a new binding received a different scopeId or started before thread hydration settled. Missing updates can indicate that the supplied thread does not expose the expected public state. Check one active subscription, stable identity, and the documented assistant-ui version before changing announcement policy.