Integrations

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.

typescript
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

  1. 01
    Pass the public thread

    Your adapter needs only getState and subscribe, so it cannot invoke composer, message, or run actions.

  2. 02
    Namespace framework IDs

    scopeId prevents identical message and tool IDs from colliding across mounted threads.

  3. 03
    Record existing history

    bindThreadRuntime records existing messages at startup and skips old content after hydration.

  4. 04
    Dispose 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.