CopilotKit v2
Connect your CopilotKit agent to paced screen-reader updates through the AG-UI adapter.
Install the accessibility layers
npm install @generative-a11y/react @generative-a11y/ag-uiStart with an existing CopilotKit app and its configured provider. The
accessibility bridge uses the public useAgent hook from the v2 entry point;
see Compatibility for validation limits.
Use the AG-UI adapter
Create the bridge
Add this component beside your chat. It gets the accessibility runtime from
A11yProvider, waits for the agent, and removes its subscription on unmount.
"use client";
import { useEffect, useId } from "react";
import { useAgent } from "@copilotkit/react-core/v2";
import { bindAgent } from "@generative-a11y/ag-ui";
import { useRuntime } from "@generative-a11y/react";
export function CopilotKitAccessibility({ agentId }: { agentId: string }) {
const runtime = useRuntime();
const bindingScopeId = useId();
const { agent, isReady } = useAgent({ agentId });
useEffect(() => {
if (!isReady) return;
const binding = bindAgent({
agent,
runtime,
scopeId: `copilotkit:${bindingScopeId}`,
});
return () => binding.dispose();
}, [agent, isReady, runtime, bindingScopeId]);
return null;
}Wrap your existing chat
Render this wrapper inside your existing CopilotKit provider. Pass the configured
agent ID and your existing chat as children.
"use client";
import type { ReactNode } from "react";
import { A11yProvider } from "@generative-a11y/react";
import { CopilotKitAccessibility } from "./copilotkit-accessibility";
export function AccessibleCopilotChat({
agentId,
children,
}: {
agentId: string;
children: ReactNode;
}) {
return (
<A11yProvider>
<CopilotKitAccessibility agentId={agentId} />
{children}
</A11yProvider>
);
}One binding per agent
Keep the wrapper mounted across responses. A11yProvider owns the runtime and
browser delivery; the bridge owns only its AG-UI subscription. If your chat
already has an accessibility provider, add just the bridge beneath it.
The bridge renders nothing and preserves your existing visible UI. Routine streaming updates live regions without moving focus. Confirm speech with your supported browsers and screen readers; DOM transcripts alone cannot prove it.
Compatibility
| Dependency | Requirement |
|---|---|
| Node.js | 22+ |
| React / React DOM | 18.2+ within major 18, or 19.x |
@ag-ui/client | >=0.0.59 <0.0.60; adapter checked against 0.0.59 |
| CopilotKit | Public v2 useAgent exposing agent and isReady |
The repository checks the AG-UI adapter, but does not pin or typecheck a CopilotKit package version. Validate the v2 hook and compatible AG-UI dependency in your host app. See the AG-UI lifecycle mapping for confirmed events and partial step, hierarchy, and replay support.
Why there is no CopilotKit package
CopilotKit exposes the agent API the AG-UI adapter already observes. Client tools that lack protocol IDs need an explicit host mapping; the adapter cannot identify approvals or tool completion from names alone.
Troubleshooting
- No updates: verify the component is inside both providers, the agent ID
matches your configuration, and
isReadybecomes true before the run starts. - Duplicate updates: remove extra bridges or AG-UI bindings for the same agent.
- Dependency mismatch: check the resolved AG-UI client against the supported range before assuming the CopilotKit integration is compatible.