generative-a11y
Integrations

AG-UI accessibility

Map documented AG-UI runs, subagents, partial steps, responses, tools, and interactions into paced accessible workflow updates.

Install the AG-UI adapter

Terminal
npm install @generative-a11y/core @generative-a11y/dom @generative-a11y/ag-ui

Use the agent your app already owns. See Compatibility for supported host dependencies.

Subscribe to the public agent API

Create the binding

Add this function to your browser app. It creates a runtime and browser delivery, then subscribes to your existing agent.

accessibility/ag-ui.ts
import { createRuntime } from "@generative-a11y/core";
import { bindRuntime } from "@generative-a11y/dom";
import { bindAgent, type AgentSource } from "@generative-a11y/ag-ui";

export function connectAccessibility(agent: AgentSource) {
  const runtime = createRuntime({});
  const delivery = bindRuntime(runtime);
  const binding = bindAgent({
    runtime,
    scopeId: "research-agent",
    agent,
  });

  return () => {
    binding.dispose();
    delivery.dispose();
    runtime.dispose();
  };
}

Connect it to your app lifecycle

Call this once when your agent is ready. Here, agent is your existing public AG-UI agent.

App mount callback
import { connectAccessibility } from "./accessibility/ag-ui";

const disconnectAccessibility = connectAccessibility(agent);

Keep the binding alive across responses. Call the returned function when the surface unmounts or before replacing the agent:

App unmount callback
disconnectAccessibility();

Keep one owner for each resource

The example owns its core runtime and DOM delivery. If your app already has these, pass that runtime directly to bindAgent and clean up only its returned binding. In React, use the runtime from A11yProvider and return () => binding.dispose() from your effect. Do not attach a second delivery layer to that provider.

Keep scopeId stable and unique for each mounted agent. The adapter leaves your visible UI and actions with the host application.

Optional configuration

maxTrackedEntities defaults to 1000 and bounds adapter identity records. copy supplies localized tool and interaction labels. See the bindAgent reference for all options and the localization guide for copy configuration.

Compatibility

DependencySupported rangeChecked version
Node.js22+—
@ag-ui/client>=0.0.59 <0.0.600.0.59

Your existing app supplies the host dependency. The adapter itself needs no React rendering layer; this example uses core and DOM directly.

Lifecycle mapping

Public subscriber evidenceReports
Run and subagent callbacksRun lifecycle and documented parent relationships
Assistant text callbacksResponse text and completion
Tool start and result callbacksTool lifecycle
Interrupt IDs and resume inputInput requests and resolutions
Step callbacksPartial-identity diagnostics only

Text, tool, and interaction events retain run ownership when exposed. Step callbacks provide stepName without stable step IDs. The adapter keeps the name as a label and omits stepId; core does not create step snapshots, announcements, or run summary counts from these diagnostics. Same-name concurrent steps cannot be correlated exactly.

Expected screen-reader behavior

Core paces response text and prioritizes input requests and failure states. DOM updates live regions without moving focus during normal agent activity. A DOM transcript records browser writes; test spoken behavior with real assistive technology.

What the protocol can report

Run identity is exact; step and hierarchy fidelity are partial. A top-level parentRunId describes lineage and is not reinterpreted as delegation. Replay and reconnection fidelity are partial because subscriptions have no mandatory persistent cursor. Retry and connection event fidelity are unavailable. Custom events and arbitrary state deltas require an explicit host mapping.

Troubleshooting

  • Repeated updates: attach only one subscriber per agent with a stable scopeId.
  • Missing interactions: check that callbacks contain stable interrupt IDs and the binding was attached before the run began.
  • Updates stop in a long session: review maxTrackedEntities. The adapter suppresses further dispatch after capacity is reached; use a new binding at a real session boundary instead of inferring missing events.