Back to Copilotkit

A2UI - Google's Generative UI Spec

docs/snippets/shared/generative-ui/a2ui.mdx

1.57.06.0 KB
Original Source

import Image from "next/image"

A2UI - Google's Generative UI Spec

A2UI is Google's declarative, LLM-friendly Generative UI specification that enables agents to generate dynamic user interfaces.

<Image src="/images/gen-ui-specs-light.png" alt="Generative UI Specs" width={4096} height={2304} className="block dark:hidden mb-8" /> <Image src="/images/gen-ui-specs-dark.png" alt="Generative UI Specs" width={4096} height={2304} className="hidden dark:block mb-8" />

What is A2UI?

A2UI is a declarative generative UI specification launched by Google. It's designed to be:

  • JSONL-based - Uses JSON Lines format for streaming
  • LLM-friendly - Easy for language models to generate
  • Platform-agnostic - Can be rendered on any platform
  • Streaming-first - Built for real-time, progressive rendering

Why A2UI?

Declarative Approach

A2UI allows agents to describe UI components declaratively, making it easier for LLMs to generate dynamic interfaces without needing to understand implementation details.

Streaming Support

Built with streaming in mind, A2UI enables progressive rendering as the agent generates responses, providing a better user experience.

Platform Agnostic

A2UI specifications can be rendered on web, mobile, or any other platform, making your agent's UI truly universal.

Setup with CopilotKit

Backend

Enable A2UI in CopilotRuntime and inject a rendering tool (render_a2ui) into your agent so it can produce A2UI surfaces:

ts
import { CopilotRuntime } from "@copilotkit/runtime";

const runtime = new CopilotRuntime({
  agents: { default: myAgent },
  a2ui: {
    injectA2UITool: true,
  },
});

This applies A2UIMiddleware to all registered agents and adds render_a2ui to the agent's tool list, along with usage guidelines so the LLM knows how to call it. Scope to specific agents with a2ui: { injectA2UITool: true, agents: ["my-agent"] }.

Once configured, any A2UI output returned from your agent will automatically be rendered in the chat interface — no additional frontend code required.

Frontend

The A2UI renderer activates automatically — no extra configuration needed on the frontend. Optionally, pass a custom theme:

tsx
import { CopilotKitProvider } from "@copilotkit/react-core/v2";
import "@copilotkit/react-core/v2/styles.css";
import { myCustomTheme } from "@copilotkit/a2ui-renderer";

<CopilotKitProvider runtimeUrl="/api/copilotkit" a2ui={{ theme: myCustomTheme }}>
  {children}
</CopilotKitProvider>

The a2ui prop on <CopilotKitProvider> is only needed if you want to override defaults.

Custom Components (BYOC)

A2UI ships with a built-in catalog of basic components (Text, Image, Card, etc.). You can extend it with your own components that match your app's design.

1. Define component schemas

Create platform-agnostic definitions using Zod. These tell the agent what components and props are available:

ts
import { z } from "zod";

export const myDefinitions = {
  StatusBadge: {
    description: "A colored status badge.",
    props: z.object({
      text: z.string(),
      variant: z.enum(["success", "warning", "error"]).optional(),
    }),
  },
  Metric: {
    description: "A key metric with label and value.",
    props: z.object({
      label: z.string(),
      value: z.string(),
      trend: z.enum(["up", "down"]).optional(),
    }),
  },
};

export type MyDefinitions = typeof myDefinitions;

2. Create React renderers

Map each definition to a React component. Props are type-checked against the Zod schemas:

tsx
"use client";

import { createCatalog, type CatalogRenderers } from "@copilotkit/a2ui-renderer";
import { myDefinitions, type MyDefinitions } from "./definitions";

const myRenderers: CatalogRenderers<MyDefinitions> = {
  StatusBadge: ({ props }) => {
    const colors = {
      success: { bg: "#dcfce7", text: "#166534" },
      warning: { bg: "#fef3c7", text: "#92400e" },
      error: { bg: "#fee2e2", text: "#991b1b" },
    };
    const c = colors[props.variant ?? "success"];
    return (
      <span style={{ padding: "2px 8px", borderRadius: 9999, fontSize: "0.75rem", background: c.bg, color: c.text }}>
        {props.text}
      </span>
    );
  },

  Metric: ({ props }) => (
    <div>
      <div style={{ fontSize: "0.75rem", color: "#6b7280" }}>{props.label}</div>
      <div style={{ fontSize: "1.5rem", fontWeight: 700 }}>
        {props.value} {props.trend === "up" ? "↑" : props.trend === "down" ? "↓" : ""}
      </div>
    </div>
  ),
};

export const myCatalog = createCatalog(myDefinitions, myRenderers, {
  catalogId: "my-app-catalog",
  includeBasicCatalog: true, // merges with built-in components
});

3. Pass the catalog to CopilotKit

tsx
"use client";

import { CopilotKitProvider } from "@copilotkit/react-core/v2";
import "@copilotkit/react-core/v2/styles.css";
import { myCatalog } from "@/lib/a2ui/renderers";

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <CopilotKitProvider runtimeUrl="/api/copilotkit" a2ui={{ catalog: myCatalog }}>
      {children}
    </CopilotKitProvider>
  );
}

That's it — agents will now see your custom components alongside the built-in ones and can use them in A2UI surfaces.

Using A2UI with CopilotKit

Get started with A2UI and A2A with CopilotKit

Check out the A2UI Composer to create and find widgets

Learn More