Introducing A2UI 1.0: What’s New in Google’s Framework-Agnostic Generative UI Protocol

By Anmol Baranwal and Eli Berman
November 11, 2026
Introducing A2UI 1.0: What’s New in Google’s Framework-Agnostic Generative UI Protocol

Google just launched A2UI 1.0 - the first stable version of its framework-agnostic open standard for Generative UI!

We’ve worked closely with Google’s A2UI team since the initial release to bring best-in-class generative UI that’s safe to use in production. A2UI natively travels over AG-UI (Agent-User Interaction Protocol), so any AG-UI agent can use A2UI 1.0 without any custom integration.

A2UI 1.0 adds major upgrades for agent-driven interfaces. One screen can now combine your design system with any other component library, and the protocol enforces your design rules. The UI and the agent can also call each other’s functions directly, with richer validation on top.

Our new Generative UI in CopilotKit is built on this release, and it’s the easiest way to adopt A2UI. It comes with a standard catalog of 70 ready-made components.

In this post, we’ll cover how A2UI solves the generative UI problem, everything that’s new in 1.0, migrating from v0.9, and using it in CopilotKit.

__wf_reserved_inherit

What is A2UI?

A2UI (Agent to UI) gives agents a common language for UI. The agent describes what the user should see, and your app decides how it looks.

It starts with a catalog, the components your app already has. The agent picks from that catalog and replies with JSON that describes the interface. That JSON travels over any transport, like AG-UI or A2A, and your app renders it with your real components.

Frontend developers ship the building blocks once, and the agent composes them for every request. Here's what makes it work:

  • Secure by design: A2UI is data, never executable code. Anything the agent invents outside your catalog is caught before it reaches the screen.
  • Built for LLMs and streaming: the UI is a flat list of small JSON messages that reference each other by ID, so the agent streams them out and your app renders each component as it arrives.
  • Runs everywhere: the same response renders natively on web and mobile, with official renderers for React, Angular, Lit, Flutter, SwiftUI and Jetpack Compose, plus community ones for Vue and even the terminal.
__wf_reserved_inherit

The problem A2UI solves

Without a standard, every library invents its own way for agents to describe UI. The output gets locked to one framework, rarely matches your product and is hard to trust. Teams end up rebuilding the same plumbing for every new agent and every new platform.

A2UI solves this with one open format for the whole ecosystem. Any agent can write it, any app renders it with its own components, and the work you put into your catalog carries across every agent and platform.

v0.9 made A2UI prompt-first, so models could write it reliably straight from the system prompt. 1.0 takes that foundation into production.

__wf_reserved_inherit

Use A2UI with any agent framework

CopilotKit is the fastest way to adopt A2UI, with the agent connection, a ready-made catalog and debugging already built in.

Because A2UI runs over AG-UI, the open protocol that connects agents to user-facing apps, you can use it with any AG-UI framework (LangChain, Mastra, Google ADK, etc) in just two lines of code.

You can also try the components yourself in the A2UI Playground, along with a ready-made prompt that adds A2UI to your app through your coding agent.

The Playground uses A2UI Express by default. It’s Google’s compact format for writing A2UI, with up to 3x fewer tokens and up to 3x lower latency, and any model can write it without tool calling.

__wf_reserved_inherit

What's new in A2UI 1.0

A2UI has finally reached 1.0. Let’s go through every change in detail. For implementation details, read the A2UI 1.0 spec.

Function calls in both directions

This is the biggest upgrade in 1.0. Users get interfaces that respond in place, and developers get typed function calls between the UI and the agent.

In v0.9, anything the UI needed from the agent went out as an event, and the answer came back as a fresh response from the agent. In 1.0, the UI can call a function on the agent, like verifying a provider ID or checking inventory:

{
  "version": "1.0",
  "callAgentFunction": {
    "surfaceId": "contact_form_1",
    "functionCallId": "verify_provider_99",
    "callFunction": {
      "@call": "verifyProvider",
      "args": {
        "providerId": "PRV-102"
      }
    }
  }
}

The agent replies with the result, and it lands right in the component that made the call.

Components don’t care where a function runs. The same @call works in a validation check, a bound value, or a button action. If your app has the function, it runs locally. Otherwise, it goes to the agent.

It works the other way as well. The agent can call functions in the UI for things only the device knows, like the screen size. Your catalog decides which functions each side is allowed to call, and the renderer checks every call against it at runtime.

Many catalogs on one surface

Real products rarely run on one component library. A dashboard might need basic layout components, your own design system and a partner’s map widget, all on the same screen.

In v0.9, each surface was locked to one catalog, so teams merged everything into one giant catalog or split the screen apart. In 1.0, each component can point to its own catalog, and the surface just sets the default.

Here, the title uses the surface’s default basic catalog, while the chart and the map name their own:

"components": [
  { "id": "title", "component": "Text", "text": "# Q3 sales" },
  {
    "id": "revenue",
    "component": "RevenueChart",
    "@catalogId": "https://acme.com/catalogs/shadcn/1.0"
  },
  {
    "id": "stores",
    "component": "StoreMap",
    "@catalogId": "https://maps.partner.com/catalog/1.0"
  }
]

Any catalog your renderer supports can be mixed this way, as long as they all target the same A2UI version. If a component’s catalog isn’t available, the renderer flags an error right away, so nothing quietly renders with the wrong library.

Smarter catalogs

In 1.0, your catalog carries the rules of your design system, along with its components.

With composition rules, you declare which components go inside which. A menu item only belongs in a menu, and a page layout only sits at the top of a surface:

{
  "Menu": { "type": "object", "allowedChildren": ["MenuItem"] },
  "MenuItem": { "type": "object", "allowedParents": ["Menu"] },
  "AppLayout": { "type": "object", "allowedParents": ["Surface"] }
}

If the model puts a component somewhere it doesn’t belong, it gets an error naming the exact rule it broke, so it can correct itself.

Catalogs are also more self-contained. Usage instructions for the model, which used to sit in a separate rules file, now live inside the catalog, and shared design tokens like colors are defined once. When your design system retires a component or prop, you can mark it deprecated with a note on what to use instead.

A full UI in one message

In v0.9, showing anything took three messages: create the surface, add the components, then send the data. In 1.0, createSurface can carry all of it:

{
  "version": "1.0",
  "createSurface": {
    "surfaceId": "user_profile_card",
    "catalogId": "https://a2ui.org/specification/v1_0/catalogs/basic/catalog.json",
    "components": [
      { "id": "root", "component": "Column", "children": ["user_name"] },
      { "id": "user_name", "component": "Text", "text": { "@path": "/name" } }
    ],
    "dataModel": { "name": "John Doe" }
  }
}

Simple UIs appear the moment this message lands, and the model has one complete object to get right instead of three messages in the right order.

It’s easier to debug too, since the full UI sits in one message you can log, read and replay. Larger UIs can still stream in piece by piece.

Richer validation

In v0.9, a check could only pass or fail, with one fixed message. In 1.0, a check returns a validation result with its own code, message and severity:

{
  "valid": false,
  "code": "EXPIRED_CARD",
  "message": "The card expiration date (05/24) has passed.",
  "severity": "error"
}

Severity can be error, warning, or info, so a form can show a gentle hint as well as a hard error. A result can also include your own fields, like a suggested fix the UI can offer.

And because the UI can now call your agent, the check itself can run there, against live data your app doesn’t hold.

User-initiated functions

In 1.0, functions with side effects (like opening a link or copying data) can require a real user action before they run. Without this, a function like openUrl could fire the moment a UI rendered and send users somewhere they never chose to go.

A catalog marks these functions with requiresUserActivation:

"openUrl": {
  "returnType": "void",
  "requiresUserActivation": true,
  ...
}

The renderer only runs them from user actions, such as clicking a confirmation button. Anywhere else, like during rendering or inside a bound value, they’re blocked.

Accessibility built in

In 1.0, accessibility is part of the spec, so agent-generated UI works with screen readers by default.

Every renderer must map labels and descriptions to the platform’s accessibility APIs, like ARIA on the web or Semantics in Flutter. When you don’t set a label, the renderer infers one from visible text, so a Submit button is announced as “Submit”.

Components can also announce their own changes. A status line that updates while the agent works can read each new update aloud to screen reader users:

{
  "id": "status",
  "component": "Text",
  "text": { "@path": "/status" },
  "@accessibility": { "live": "polite" } // or "assertive", "off"
}

Reserved @ prefix

In 1.0, A2UI reserves the @ prefix for its own instructions. Bindings that read from your data and calls that run a function now start with it:

// v0.9
{ "id": "name", "component": "Text", "text": { "path": "/user/name" } }

// 1.0
{ "id": "name", "component": "Text", "text": { "@path": "/user/name" } }

The same goes for the fields A2UI adds to every component, like @catalogId, @accessibility, @metadata and @checks. id, component and your own props stay as they are.

It keeps your data and A2UI’s instructions cleanly apart. In v0.9, if your data happened to contain a path or call field, like a file record or a call log, the renderer could treat it as a binding. Now anything starting with @ is an instruction, and everything else is just your data.

Extensions for your metadata

In 1.0, you can attach your own metadata to A2UI messages without forking the spec.

A2UI 1.0 schemas are strict and reject unknown fields, which keeps every payload easy to validate. Extensions give your extras an approved home on catalogs, surfaces, components and user actions:

"metadata": {
  "extensions": {
    "com_acme_audit": { "sessionId": "abc-123" }
  }
}

Keys are namespaced, like com_acme_audit, so they never clash with official A2UI extensions. Renderers ignore keys they don’t recognize, so your metadata never breaks someone else’s renderer. Teams can use this for access policies, audit signatures, or telemetry IDs.

Migrating from v0.9 to 1.0

1.0 is a breaking release, but most of the migration is mechanical: update the version string, add the @ prefix to bindings, calls and component fields, and drop theme from createSurface, since styling now lives entirely in your app.

v0.9 and 1.0 surfaces can run side by side, so you can move one surface at a time. The evolution guide walks through every change.

A2UI 1.0 with CopilotKit

CopilotKit’s new Generative UI speaks A2UI 1.0 under the hood, so you can build on it with your agent today. You can start with the standard catalog, which comes with 70 ready-made components, including all 18 A2UI basic components.

Install CopilotKit in your app:

npm install @copilotkit/react-core @copilotkit/runtime

Then add the standard catalog to your CopilotKitProvider:

import { standardUI } from "@copilotkit/react-core/v2/generative-ui";

<CopilotKitProvider runtimeUrl="/api/copilotkit" generativeUI={{ ui: standardUI }}>

To use your own components, register them with createGenerativeUI. Each one gets a description that tells the agent when to use it, plus typed props, and extends keeps the standard catalog alongside yours.

export const shopUI = createGenerativeUI({
  id: "acme/shop@1",
  extends: [standardUI],
  components: {
    ProductCard: {
      component: ProductCard,
      description: "One product. Copy every value from a product in a tool result.",
      props: z.object({ name: z.string(), price: z.number(), imageUrl: z.string() }),
    },
  },
});

Here's what happens from the moment your app shares its catalog to the agent's next update!

__wf_reserved_inherit

We also shipped surfaces, which let the agent generate UI outside the chat, anywhere on your page you mark as a surface. With markdown mode, the agent writes A2UI blocks straight into its reply, so text and UI stream together.

When something looks off, the Inspector shows every rendered surface, any rejected output with the reason, and the exact prompt the model received.

If you already use A2UI v0.9 with CopilotKit, nothing breaks. Read the docs and the launch blog for everything that shipped.

Get Started

A2UI 1.0 is the stable, framework-agnostic open standard for generative UI. With CopilotKit, you can build on it today using your own components, on any user-facing surface. We can’t wait to see what you build with it.

To learn more:

Follow CopilotKit on Twitter for updates. If you get stuck, reach out in the CopilotKit or AG-UI communities.

Top posts

See All
Bring ChatGPT's Intelligent UI to your app with A2UI 1.0 and CopilotKit
Anmol Baranwal November 12, 2026
Bring ChatGPT's Intelligent UI to your app with A2UI 1.0 and CopilotKitYou can now bring ChatGPT’s Intelligent UI to your own app. CopilotKit’s new Generative UI is built on Google’s A2UI 1.0, so your agent can answer with charts, calculators and interactive tools built from your own components and design system. It works with any agent framework, renders in the chat or anywhere on your page, fixes itself when the model slips and takes just two lines of code to set up. Here’s how it works, why A2UI 1.0 makes it possible and how to try it live in the A2UI Playground.
Introducing OpenBot 1.0: An Agent Workspace You Can Make Your Own
Sam Julien and Anmol BaranwalNovember 10, 2026
Introducing OpenBot 1.0: An Agent Workspace You Can Make Your OwnToday we’re releasing OpenBot 1.0, the modular, self-hostable agent workspace with built-in governance. Create a Bot or bring your own agent, pick any model, and connect it to your tools, while you decide what it can do on its own. Run it free on Mac or Windows, or deploy OpenBot for Business on your own infrastructure with SSO and a full audit trail.
What’s new in OpenBot 1.0 - the open-source alternative to Grok Bot, OpenAI dots, Muse and Duet
Anmol Baranwal and Eli BermanNovember 10, 2026
What’s new in OpenBot 1.0 - the open-source alternative to Grok Bot, OpenAI dots, Muse and DuetOpenBot 1.0 is out with major upgrades to the modular, self-hostable agent workspace. It now has a desktop app for Mac and Windows with a three-click setup, sign-in with your Claude, ChatGPT, Gemini or xAI plan, skins for OpenDuet, OpenDots and OpenMuse, and Teach a Bot. It also adds subagents and check-ins, generative UI on A2UI 1.0, and hundreds of apps through Composio and Arcade. For teams, OpenBot for Business adds SSO, boundaries, audit and enterprise controls.
Are you ready?

Stay in the know

Subscribe to our blog and get updates on CopilotKit in your inbox.