generative-a11y
Integrations

CopilotKit v2

Connect your CopilotKit agent to paced screen-reader updates through the AG-UI adapter.

Install the accessibility layers

Terminal
npm install @generative-a11y/react @generative-a11y/ag-ui

Start 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.

components/copilotkit-accessibility.tsx
"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.

components/accessible-copilot-chat.tsx
"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

DependencyRequirement
Node.js22+
React / React DOM18.2+ within major 18, or 19.x
@ag-ui/client>=0.0.59 <0.0.60; adapter checked against 0.0.59
CopilotKitPublic 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 isReady becomes 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.