diff --git a/README.md b/README.md index 38fb9324..169ffb2f 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,12 @@ to generate or populate rich user interfaces. *A gallery of A2UI rendered cards, showing a variety of UI compositions that A2UI can achieve.* -## ⚠️ Status: Experimental +## ⚠️ Status: Early Stage Public Preview > **Note:** A2UI is currently in **v0.8 (Public Preview)**. The specification and -implementations are functional but evolving. We are opening the project to gather -feedback on the format and collaborate on client renderers. Expect changes. +implementations are functional but are still evolving. We are opening the project to +foster collaboration, gather feedback, and solicit contributions (e.g., on client renderers). +Expect changes. ## Summary @@ -40,7 +41,7 @@ The project's core philosophies: security risk. A2UI is a declarative data format, not executable code. Your client application maintains a "catalog" of trusted, pre-approved UI components (e.g., Card, Button, TextField), and the agent can only request -to render components from that catalog. +to render components from that catalog. * **LLM-friendly and incrementally updateable**: The UI is represented as a flat list of components with ID references which is easy for LLMs to generate incrementally, allowing for progressive rendering and a responsive user @@ -66,36 +67,35 @@ component logic rather than relying solely on the core system. Some of the use cases include: -* **Dynamic Data Collection:** An agent generates a bespoke form (date pickers, +* **Dynamic Data Collection:** An agent generates a bespoke form (date pickers, sliders, inputs) based on the specific context of a conversation (e.g., booking a specialized reservation). -* **Remote Sub-Agents:** An orchestrator agent delegates a task to a +* **Remote Sub-Agents:** An orchestrator agent delegates a task to a remote specialized agent (e.g., a travel booking agent) which returns a UI payload to be rendered inside the main chat window. -* **Adaptive Workflows:** Enterprise agents that generate approval +* **Adaptive Workflows:** Enterprise agents that generate approval dashboards or data visualizations on the fly based on the user's query. ## Architecture The A2UI flow disconnects the generation of UI from the execution of UI: -1. **Generation:** An Agent (using Gemini or another LLM) generates or uses +1. **Generation:** An Agent (using Gemini or another LLM) generates or uses a pre-generated `A2UI Response`, a JSON payload describing the composition of UI components and their properties. -2. **Transport:** This message is sent to the client application +2. **Transport:** This message is sent to the client application (via A2A, AG UI, etc.). -3. **Resolution:** The Client's **A2UI Renderer** parses the JSON. -4. **Rendering:** The Renderer maps the abstract components +3. **Resolution:** The Client's **A2UI Renderer** parses the JSON. +4. **Rendering:** The Renderer maps the abstract components (e.g., `type: 'text-field'`) to the concrete implementation in the client's codebase. - ## Dependencies A2UI is designed to be a lightweight format, but it fits into a larger ecosystem: -* **Transports:** Compatible with **A2A Protocol** and **AG UI**. -* **LLMs:** Can be generated by any model capable of generating JSON output. -* **Host Frameworks:** Requires a host application built in a supported framework +* **Transports:** Compatible with **A2A Protocol** and **AG UI**. +* **LLMs:** Can be generated by any model capable of generating JSON output. +* **Host Frameworks:** Requires a host application built in a supported framework (currently: Web or Flutter). ## Getting Started @@ -103,31 +103,36 @@ A2UI is designed to be a lightweight format, but it fits into a larger ecosystem The best way to understand A2UI is to run the samples. ### Prerequisites -* Node.js (for web clients) -* Python (for agent samples) -* A valid [Gemini API Key](https://aistudio.google.com/) is required for the samples. + +* Node.js (for web clients) +* Python (for agent samples) +* A valid [Gemini API Key](https://aistudio.google.com/) is required for the samples. ### Running the Restaurant Finder Demo -1. **Clone the repository:** +1. **Clone the repository:** + ```bash git clone https://github.com/google/A2UI.git cd A2UI ``` -2. **Set your API Key:** +2. **Set your API Key:** + ```bash export GEMINI_API_KEY="your_gemini_api_key" ``` -3. **Run the Agent (Backend):** +3. **Run the Agent (Backend):** + ```bash cd samples/agent/adk/restaurant_finder uv run . ``` -4. **Run the Client (Frontend):** +4. **Run the Client (Frontend):** Open a new terminal window: + ```bash cd samples/client/lit/shell npm install @@ -140,15 +145,14 @@ which uses A2UI under the hood. CopilotKit has a public [A2UI Widget Builder](https://go.copilotkit.ai/A2UI-widget-builder) to try out as well. - ## Roadmap We hope to work with the community on the following: -* **Spec Stabilization:** Moving towards a v1.0 specification. -* **More Renderers:** Adding official support for React, Jetpack Compose, iOS (SwiftUI), and more. -* **Additional Transports:** Support for REST and more. -* **Additional Agent Frameworks:** Genkit, LangGraph, and more. +* **Spec Stabilization:** Moving towards a v1.0 specification. +* **More Renderers:** Adding official support for React, Jetpack Compose, iOS (SwiftUI), and more. +* **Additional Transports:** Support for REST and more. +* **Additional Agent Frameworks:** Genkit, LangGraph, and more. ## Contribute diff --git a/docs/agents.md b/docs/agents.md new file mode 100644 index 00000000..4d805d26 --- /dev/null +++ b/docs/agents.md @@ -0,0 +1,51 @@ +# Agents (Server-Side) + +Agents are server-side programs that generate A2UI messages in response to user requests. + +The actual component rendering is done by the [renderer](renderers.md), +after messages are [transported](transports.md) to the client. +The agent is only responsible for generating the A2UI messages. + +## How Agents Work + +``` +User Input → Agent Logic → LLM → A2UI JSON → Send to Client +``` + +1. **Receive** user message +2. **Process** with LLM (Gemini, GPT, Claude, etc.) +3. **Generate** A2UI JSON messages as structured output +4. **Send** to client via transport + +User interactions from the client can be treated as new user input. + +## Sample Agents + +The A2UI repository includes sample agents you can learn from: + +- [Restaurant Finder](https://github.com/google/A2UI/tree/main/samples/agent/adk/restaurant_finder) + - Table reservations with forms + - Written with the ADK +- [Contact Lookup](https://github.com/google/A2UI/tree/main/samples/agent/adk/contact_lookup) + - Search with result lists + - Written with the ADK +- [Rizzcharts](https://github.com/google/A2UI/tree/main/samples/agent/adk/rizzcharts) + - A2UI Custom components demo + - Written with the ADK + +## Different types of agents you will use A2A with + +### 1. User Facing Agent (standalone) + +A user facing agent is one that is directly interacted with by the user. + +### 2. User Facing Agent as a host for a Remote Agent + +This is a pattern where the user facing agent is a host for one or more remote agents. The user facing agent will call the remote agent and the remote agent will generate the A2UI messages. This is a common pattern in [A2A](https://a2a-protocol.org) with the client agent calling the server agent. + +- The user facing agent may "passthrough" the A2UI message without altering them +- The user facing agent may alter the A2UI message before sending it to the client + +### 3. Remote Agent + +A remote agent is not directly a part of the user facing UI. Instead it is registered in as a remote agent and can be called by the user facing agent. This is a common pattern in [A2A](https://a2a-protocol.org) with the client agent calling the server agent. \ No newline at end of file diff --git a/docs/assets/A2UI-widget-builder.png b/docs/assets/A2UI-widget-builder.png new file mode 100644 index 00000000..b58cb259 Binary files /dev/null and b/docs/assets/A2UI-widget-builder.png differ diff --git a/docs/assets/end-to-end-data-flow.png b/docs/assets/end-to-end-data-flow.png new file mode 100644 index 00000000..77728afa Binary files /dev/null and b/docs/assets/end-to-end-data-flow.png differ diff --git a/docs/community.md b/docs/community.md new file mode 100644 index 00000000..6f701e67 --- /dev/null +++ b/docs/community.md @@ -0,0 +1,86 @@ +# Community + +Welcome to the A2UI community! We're building the future of agent-driven interfaces together. + +## Get Involved + +A2UI is an open-source project licensed under Apache 2.0. We welcome contributions from developers, researchers, and anyone interested in advancing agentic user interfaces. + +## Community Showcase + +!!! info "Coming soon..." + We are considering how best to showcase community projects, examples, themes, renderers, custom components, and more. A 4 minute (or less) demo video and code sample linked in Github discussions is a great way to show off your work. + +## Project Partners + +A2UI is developed in collaboration with several organizations: + +### Google Opal + +[Opal](http://opal.google) lets users build, edit, and share AI mini-apps using natural language. The Opal team has been a core contributor to A2UI's development. + +### Flutter + +The [GenUI SDK for Flutter](https://docs.flutter.dev/ai/genui) uses A2UI as the UI declaration format for generating dynamic, personalized UIs in Flutter applications. + +### Gemini Enterprise + +A2UI is being integrated into [Gemini Enterprise](https://cloud.google.com/gemini-enterprise?e=48754805) to enable custom agents to render rich, interactive UIs within enterprise applications. + +### AG UI / CopilotKit + +[AG UI](https://ag-ui.com/) and [CopilotKit](https://www.copilotkit.ai/) provide day-zero compatibility with A2UI, enabling developers to build rich, state-synced applications that render dynamic UIs from agents. + +### A2A + +Google's [A2A team](https://a2a-protocol.org/) have been core contributors to A2UI's development, with support from the A2A Technical Steering Committee (TSC). + +### ... and more + +There are many organizations and individuals contributing to A2UI's development. + +If you have made signiciant contributions to A2UI, please submit your name to this list. + +## Code of Conduct + +We are committed to providing a welcoming and inclusive environment for everyone. All participants are expected to: + +- Be respectful and considerate +- Welcome newcomers and help them get started +- Focus on what's best for the community +- Show empathy towards others + +Unacceptable behavior will not be tolerated. Report concerns to the project maintainers. + +## Recognition + +We appreciate all contributions! Contributors are recognized in: + +- GitHub's contributor graph +- Release notes +- Project acknowledgments + +Significant contributors may be invited to join the project's maintainer team. + +## Stay Updated + +- **Watch the GitHub repo** for notifications +- **Star the repo** to bookmark and show support +- **Follow releases** to get notified of new versions + +## Ways to Contribute + +**[github.com/google/A2UI](https://github.com/google/A2UI)** + +- **Report Issues**: Found a bug? [Open an issue](https://github.com/google/A2UI/issues) +- **Build Renderers**: See the [roadmap](roadmap.md) for planned frameworks +- **Share Examples**: Post with `#A2UI` on X/LinkedIn, start a [discussion](https://github.com/google/A2UI/discussions) +- **Improve Docs**: PRs welcome in the `docs/` directory + +## Questions? + +- Check the [documentation](introduction/what-is-a2ui.md) +- Search [GitHub Discussions](https://github.com/google/A2UI/discussions) +- Ask in [GitHub Issues](https://github.com/google/A2UI/issues) + +Thank you for being part of the A2UI community! diff --git a/docs/composer.md b/docs/composer.md new file mode 100644 index 00000000..f2f28313 --- /dev/null +++ b/docs/composer.md @@ -0,0 +1,16 @@ +# A2UI Composer + +Try building A2UI widgets interactively with the **CopilotKit A2UI Widget Builder**. + +[![A2UI Composer](assets/A2UI-widget-builder.png)](https://go.copilotkit.ai/A2UI-widget-builder) + +**[Launch Widget Builder →](https://go.copilotkit.ai/A2UI-widget-builder)** + +## What it does + +- Experiment with A2UI components visually +- Generate A2UI JSON by describing what you want +- See real-time previews +- Copy JSON to use in your agents + +Built by the [CopilotKit](https://www.copilotkit.ai/) team. \ No newline at end of file diff --git a/docs/concepts/components.md b/docs/concepts/components.md new file mode 100644 index 00000000..79d97bfa --- /dev/null +++ b/docs/concepts/components.md @@ -0,0 +1,120 @@ +# Components & Structure + +A2UI uses an **adjacency list model** for component hierarchies. Instead of nested JSON trees, components are a flat list with ID references. + +## Why Flat Lists? + +**Traditional nested approach:** +- LLM must generate perfect nesting in one pass +- Hard to update deeply nested components +- Difficult to stream incrementally + +**A2UI adjacency list:** +- ✅ Flat structure, easy for LLMs to generate +- ✅ Send components incrementally +- ✅ Update any component by ID +- ✅ Clear separation of structure and data + +## The Adjacency List Model + +```json +{ + "surfaceUpdate": { + "components": [ + {"id": "root", "component": {"Column": {"children": {"explicitList": ["greeting", "buttons"]}}}}, + {"id": "greeting", "component": {"Text": {"text": {"literalString": "Hello"}}}}, + {"id": "buttons", "component": {"Row": {"children": {"explicitList": ["cancel-btn", "ok-btn"]}}}}, + {"id": "cancel-btn", "component": {"Button": {"child": "cancel-text", "action": {"name": "cancel"}}}}, + {"id": "cancel-text", "component": {"Text": {"text": {"literalString": "Cancel"}}}}, + {"id": "ok-btn", "component": {"Button": {"child": "ok-text", "action": {"name": "ok"}}}}, + {"id": "ok-text", "component": {"Text": {"text": {"literalString": "OK"}}}} + ] + } +} +``` + +Components reference children by ID, not by nesting. + +## Component Basics + +Every component has: + +1. **ID**: Unique identifier (`"welcome-message"`) +2. **Type**: Component type (`Text`, `Button`, `Card`) +3. **Properties**: Configuration specific to that type + +```json +{"id": "welcome", "component": {"Text": {"text": {"literalString": "Hello"}, "usageHint": "h1"}}} +``` + +## The Standard Catalog + +A2UI defines a standard catalog of components organized by purpose: + +- **Layout**: Row, Column, List - arrange other components +- **Display**: Text, Image, Icon, Video, Divider - show information +- **Interactive**: Button, TextField, CheckBox, DateTimeInput, Slider - user input +- **Container**: Card, Tabs, Modal - group and organize content + +For the complete component gallery with examples, see [Component Reference](../reference/components.md). + +## Static vs. Dynamic Children + +**Static (`explicitList`)** - Fixed list of child IDs: +```json +{"children": {"explicitList": ["back-btn", "title", "menu-btn"]}} +``` + +**Dynamic (`template`)** - Generate children from data array: +```json +{"children": {"template": {"dataBinding": "/items", "componentId": "item-template"}}} +``` + +For each item in `/items`, render the `item-template`. See [Data Binding](data-binding.md) for details. + +## Hydrating with Values + +Components get their values two ways: + +**Literal** - Fixed value: `{"text": {"literalString": "Welcome"}}` +**Data-bound** - From data model: `{"text": {"path": "/user/name"}}` + +LLMs can generate components with literal values or bind them to data paths for dynamic content. + +## Composing Surfaces + +Components compose into **surfaces** (widgets): + +1. LLM generates component definitions via `surfaceUpdate` +2. LLM populates data via `dataModelUpdate` +3. LLM signals render via `beginRendering` +4. Client renders all components as native widgets + +A surface is a complete, cohesive UI (form, dashboard, chat, etc.). + +## Incremental Updates + +**Add** - Send new `surfaceUpdate` with new component IDs +**Update** - Send `surfaceUpdate` with existing ID and new properties +**Remove** - Update parent's `children` list to exclude removed IDs + +The flat structure makes all updates simple ID-based operations. + +## Custom Components + +Beyond the standard catalog, clients can define custom components for domain-specific needs: + +- **How**: Register custom component types in your renderer +- **What**: Charts, maps, custom visualizations, specialized widgets +- **Security**: Custom components still part of the client's trusted catalog + +Custom components are _advertised_ from the client's renderer to the LLM. The LLM can then use them in addition to the standard catalog. + +See [Custom Components Guide](../guides/custom-components.md) for implementation details. + +## Best Practices + +1. **Descriptive IDs**: Use `"user-profile-card"` not `"c1"` +2. **Shallow hierarchies**: Avoid deep nesting +3. **Separate structure from content**: Use data bindings, not literals +4. **Reuse with templates**: One template, many instances via dynamic children diff --git a/docs/concepts/data-binding.md b/docs/concepts/data-binding.md new file mode 100644 index 00000000..54da691f --- /dev/null +++ b/docs/concepts/data-binding.md @@ -0,0 +1,132 @@ +# Data Binding + +Data binding connects UI components to application state using JSON Pointer paths ([RFC 6901](https://tools.ietf.org/html/rfc6901)). It's what allows A2UI to efficiently define layouts for large arrays of data, or to show updated content without being regenerated from scratch. + +## Structure vs. State + +A2UI separates: + +1. **UI Structure** (Components): What the interface looks like +2. **Application State** (Data Model): What data it displays + +This enables: reactive updates, data-driven UIs, reusable templates, and bidirectional binding. + +## The Data Model + +Each surface has a JSON object holding state: + +```json +{ + "user": {"name": "Alice", "email": "alice@example.com"}, + "cart": { + "items": [{"name": "Widget", "price": 9.99, "quantity": 2}], + "total": 19.98 + } +} +``` + +## JSON Pointer Paths + +**Syntax:** + +- `/user/name` - Object property +- `/cart/items/0` - Array index (zero-based) +- `/cart/items/0/price` - Nested path + +**Example:** + +```json +{"user": {"name": "Alice"}, "items": ["Apple", "Banana"]} +``` + +- `/user/name` → `"Alice"` +- `/items/0` → `"Apple"` + +## Literal vs. Path Values + +**Literal (fixed):** +```json +{"id": "title", "component": {"Text": {"text": {"literalString": "Welcome"}}}} +``` + +**Data-bound (reactive):** +```json +{"id": "username", "component": {"Text": {"text": {"path": "/user/name"}}}} +``` + +When `/user/name` changes from "Alice" to "Bob", the text **automatically updates** to "Bob". + +## Reactive Updates + +Components bound to data paths automatically update when the data changes: + +```json +{"id": "status", "component": {"Text": {"text": {"path": "/order/status"}}}} +``` + +**Initial:** `/order/status` = "Processing..." → displays "Processing..." +**Update:** Send `dataModelUpdate` with `status: "Shipped"` → displays "Shipped" + +No component updates needed—just data updates. + +## Dynamic Lists + +Use templates to render arrays: + +```json +{ + "id": "product-list", + "component": { + "Column": { + "children": {"template": {"dataBinding": "/products", "componentId": "product-card"}} + } + } +} +``` + +**Data:** +```json +{"products": [{"name": "Widget", "price": 9.99}, {"name": "Gadget", "price": 19.99}]} +``` + +**Result:** Two cards rendered, one per product. + +### Scoped Paths + +Inside a template, paths are scoped to the array item: + +```json +{"id": "product-name", "component": {"Text": {"text": {"path": "/name"}}}} +``` + +For `/products/0`, `/name` resolves to `/products/0/name` → "Widget" +For `/products/1`, `/name` resolves to `/products/1/name` → "Gadget" + +Adding/removing items automatically updates the rendered components. + +## Input Bindings + +Interactive components update the data model bidirectionally: + +| Component | Example | User Action | Data Update | +|-----------|---------|-------------|-------------| +| **TextField** | `{"text": {"path": "/form/name"}}` | Types "Alice" | `/form/name` = "Alice" | +| **CheckBox** | `{"value": {"path": "/form/agreed"}}` | Checks box | `/form/agreed` = true | +| **MultipleChoice** | `{"selections": {"path": "/form/country"}}` | Selects "Canada" | `/form/country` = ["ca"] | + +## Best Practices + +**1. Use granular updates** - Update only changed paths: +```json +{"dataModelUpdate": {"path": "/user", "contents": [{"key": "name", "valueString": "Alice"}]}} +``` + +**2. Organize by domain** - Group related data: +```json +{"user": {...}, "cart": {...}, "ui": {...}} +``` + +**3. Pre-compute display values** - Agent formats data (currency, dates) before sending: +```json +{"price": "$19.99"} // Not: {"price": 19.99} +``` diff --git a/docs/concepts/data-flow.md b/docs/concepts/data-flow.md new file mode 100644 index 00000000..6bd81eab --- /dev/null +++ b/docs/concepts/data-flow.md @@ -0,0 +1,90 @@ +# Data Flow + +How messages flow from agents to UI. + +## Architecture + +``` +Agent (LLM) → A2UI Generator → Transport (SSE/WS/A2A) + ↓ +Client (Stream Reader) → Message Parser → Renderer → Native UI +``` + +![end-to-end-data-flow](../assets/end-to-end-data-flow.png) + +## Message Format + +A2UI defines a sequence of JSON messages that describe the UI. When streamed, these messages are often formatted as **JSON Lines (JSONL)**, where each line is a complete JSON object. + +```jsonl +{"surfaceUpdate":{"surfaceId":"main","components":[...]}} +{"dataModelUpdate":{"surfaceId":"main","contents":[{"key":"user","valueMap":[{"key":"name","valueString":"Alice"}]}]}} +{"beginRendering":{"surfaceId":"main","root":"root-component"}} +``` + +**Why this format?** A sequence of self-contained JSON objects is streaming-friendly, easy for LLMs to generate incrementally, and resilient to errors. + +## Lifecycle Example: Restaurant Booking + +**User:** "Book a table for 2 tomorrow at 7pm" + +**1. Agent defines UI structure:** + +```json +{"surfaceUpdate": {"surfaceId": "booking", "components": [ + {"id": "root", "component": {"Column": {"children": {"explicitList": ["header", "guests-field", "submit-btn"]}}}}, + {"id": "header", "component": {"Text": {"text": {"literalString": "Confirm Reservation"}, "usageHint": "h1"}}}, + {"id": "guests-field", "component": {"TextField": {"label": {"literalString": "Guests"}, "text": {"path": "/reservation/guests"}}}}, + {"id": "submit-btn", "component": {"Button": {"child": "submit-text", "action": {"name": "confirm", "context": [{"key": "details", "value": {"path": "/reservation"}}]}}}} +]}} +``` + +**2. Agent populates data:** + +```json +{"dataModelUpdate": {"surfaceId": "booking", "path": "/reservation", "contents": [ + {"key": "datetime", "valueString": "2025-12-16T19:00:00Z"}, + {"key": "guests", "valueString": "2"} +]}} +``` + +**3. Agent signals render:** + +```json +{"beginRendering": {"surfaceId": "booking", "root": "root"}} +``` + +**4. User edits guests to "3"** → Client updates `/reservation/guests` automatically (no message to agent yet) + +**5. User clicks "Confirm"** → Client sends action with updated data: + +```json +{"userAction": {"name": "confirm", "surfaceId": "booking", "context": {"details": {"datetime": "2025-12-16T19:00:00Z", "guests": "3"}}}} +``` + +**6. Agent responds** → Updates UI or sends `{"deleteSurface": {"surfaceId": "booking"}}` to clean up + +## Transport Options + +- **A2A Protocol**: Multi-agent systems, can also be used for agent to UI communication +- **AG UI**: Bidirectional, real-time +- ... others + +See [transports](../transports.md) for more details. + +## Progressive Rendering + +Instead of waiting for the entire response to be generated before showing anything to the user, chunks of the response can be streamed to the client as they are generated and progressively rendered. + +Users see UI building in real-time instead of staring at a spinner. + +## Error Handling + +**Malformed messages:** Skip and continue, or send error back to agent for correction +**Network interruptions:** Display error state, reconnect, agent resends or resumes + +## Performance + +**Batching:** Buffer updates for 16ms, batch render together +**Diffing:** Compare old/new components, update only changed properties +**Granular updates:** Update `/user/name` not entire `/` model diff --git a/docs/concepts/overview.md b/docs/concepts/overview.md new file mode 100644 index 00000000..af1a6b2b --- /dev/null +++ b/docs/concepts/overview.md @@ -0,0 +1,33 @@ +# Core Concepts + +This section explains the fundamental architecture of A2UI. Understanding these concepts will help you build effective agent-driven interfaces. + +## The Big Picture + +A2UI is built around three core ideas: + +1. **Streaming Messages**: UI updates flow as a sequence of JSON messages from agent to client +2. **Declarative Components**: UIs are described as data, not programmed as code +3. **Data Binding**: UI structure is separate from application state, enabling reactive updates + +## Key Topics + +### [Data Flow](data-flow.md) +How messages travel from agents to rendered UI. Includes a complete lifecycle example of a restaurant booking flow, transport options (SSE, WebSockets, A2A), progressive rendering, and error handling. + +### [Component Structure](components.md) +A2UI's **adjacency list model** for representing component hierarchies. Learn why flat lists are better than nested trees, how to use static vs. dynamic children, and best practices for incremental updates. + +### [Data Binding](data-binding.md) +How components connect to application state using JSON Pointer paths. Covers reactive components, dynamic lists, input bindings, and the separation of structure from state that makes A2UI powerful. + +## Message Types + +A2UI uses four message types: + +- **`surfaceUpdate`**: Define or update UI components +- **`dataModelUpdate`**: Update application state +- **`beginRendering`**: Signal the client to render +- **`deleteSurface`**: Remove a UI surface + +For complete technical details, see [Message Reference](../reference/messages.md). diff --git a/docs/guides/agent-development.md b/docs/guides/agent-development.md new file mode 100644 index 00000000..18d68523 --- /dev/null +++ b/docs/guides/agent-development.md @@ -0,0 +1,182 @@ +# Agent Development Guide + +Build AI agents that generate A2UI interfaces. This guide covers generating and streaming UI messages from LLMs. + +## Quick Overview + +Building an A2UI agent: + +1. **Understand user intent** → Decide what UI to show +2. **Generate A2UI JSON** → Use LLM structured output or prompts +3. **Validate & stream** → Check schema, send to client +4. **Handle actions** → Respond to user interactions + +## Start with a simple agent + +We will use the ADK to build a simple agent. We will start with text and eventually upgrade it to A2UI. + +See step by step instructions at the [ADK quickstart](https://google.github.io/adk-docs/get-started/python/). + +```bash +pip install google-adk +adk create my_agent +``` + +Then edit the `my_agent/agent.py` file with a very simple agent for restaurant recommendations. + +```python +import json +from google.adk.agents.llm_agent import Agent +from google.adk.tools.tool_context import ToolContext + +def get_restaurants(tool_context: ToolContext) -> str: + """Call this tool to get a list of restaurants.""" + return json.dumps([ + { + "name": "Xi'an Famous Foods", + "detail": "Spicy and savory hand-pulled noodles.", + "imageUrl": "http://localhost:10002/static/shrimpchowmein.jpeg", + "rating": "★★★★☆", + "infoLink": "[More Info](https://www.xianfoods.com/)", + "address": "81 St Marks Pl, New York, NY 10003" + }, + { + "name": "Han Dynasty", + "detail": "Authentic Szechuan cuisine.", + "imageUrl": "http://localhost:10002/static/mapotofu.jpeg", + "rating": "★★★★☆", + "infoLink": "[More Info](https://www.handynasty.net/)", + "address": "90 3rd Ave, New York, NY 10003" + }, + { + "name": "RedFarm", + "detail": "Modern Chinese with a farm-to-table approach.", + "imageUrl": "http://localhost:10002/static/beefbroccoli.jpeg", + "rating": "★★★★☆", + "infoLink": "[More Info](https://www.redfarmnyc.com/)", + "address": "529 Hudson St, New York, NY 10014" + }, + ]) + +AGENT_INSTRUCTION=""" +You are a helpful restaurant finding assistant. Your goal is to help users find and book restaurants using a rich UI. + +To achieve this, you MUST follow this logic: + +1. **For finding restaurants:** + a. You MUST call the `get_restaurants` tool. Extract the cuisine, location, and a specific number (`count`) of restaurants from the user's query (e.g., for "top 5 chinese places", count is 5). + b. After receiving the data, you MUST follow the instructions precisely to generate the final a2ui UI JSON, using the appropriate UI example from the `prompt_builder.py` based on the number of restaurants.""" + +root_agent = Agent( + model='gemini-2.5-flash', + name="restaurant_agent", + description="An agent that finds restaurants and helps book tables.", + instruction=AGENT_INSTRUCTION, + tools=[get_restaurants], +) +``` + +Don't forget to set the `GOOGLE_API_KEY` environment variable to run this example. + +```bash +echo 'GOOGLE_API_KEY="YOUR_API_KEY"' > .env +``` + +You can test out this agent with the ADK web interface: + +```bash +adk web +``` + +Select `my_agent` from the list, and ask questions about restaurants in new york. You should see a list of restaurants in the UI as plain text. + +## Generating A2UI Messages + +Getting the LLM to generate A2UI messages requires some prompt engineering. + +!!! warning "Attention" + This is an area we are still designing. The developer ergonomics of this are not yet finalized. + +For now, let's copy the `a2ui_schema.py` from the contact lookup example. This is the easiest way to get the A2UI schema and examples for your agent (subject to change). + +```bash +cp samples/agent/adk/contact_lookup/a2ui_schema.py my_agent/ +``` + +First lets add the new imports to the `agent.py` file: + +```python +# The schema for any A2UI message. This never changes. +from .a2ui_schema import A2UI_SCHEMA +``` + +Now we will modify the agent instructions to generate A2UI messages instead of plain text. We will leave a placeholder for future UI examples. + +```python + +# Eventually you can copy & paste some UI examples here, for few-shot in context learning +RESTAURANT_UI_EXAMPLES = """ +""" + +# Construct the full prompt with UI instructions, examples, and schema +A2UI_AND_AGENT_INSTRUCTION = AGENT_INSTRUCTION + f""" + +Your final output MUST be a a2ui UI JSON response. + +To generate the response, you MUST follow these rules: +1. Your response MUST be in two parts, separated by the delimiter: `---a2ui_JSON---`. +2. The first part is your conversational text response. +3. The second part is a single, raw JSON object which is a list of A2UI messages. +4. The JSON part MUST validate against the A2UI JSON SCHEMA provided below. + +--- UI TEMPLATE RULES --- +- If the query is for a list of restaurants, use the restaurant data you have already received from the `get_restaurants` tool to populate the `dataModelUpdate.contents` array (e.g., as a `valueMap` for the "items" key). +- If the number of restaurants is 5 or fewer, you MUST use the `SINGLE_COLUMN_LIST_EXAMPLE` template. +- If the number of restaurants is more than 5, you MUST use the `TWO_COLUMN_LIST_EXAMPLE` template. +- If the query is to book a restaurant (e.g., "USER_WANTS_TO_BOOK..."), you MUST use the `BOOKING_FORM_EXAMPLE` template. +- If the query is a booking submission (e.g., "User submitted a booking..."), you MUST use the `CONFIRMATION_EXAMPLE` template. + +{RESTAURANT_UI_EXAMPLES} + +---BEGIN A2UI JSON SCHEMA--- +{A2UI_SCHEMA} +---END A2UI JSON SCHEMA--- +""" + +root_agent = Agent( + model='gemini-2.5-flash', + name="restaurant_agent", + description="An agent that finds restaurants and helps book tables.", + instruction=A2UI_AND_AGENT_INSTRUCTION, + tools=[get_restaurants], +) +``` + +## Understanding the Output + +Your agent will no longer strictly output text. Instead, it will output text and a **JSON list** of A2UI messages. + +The `A2UI_SCHEMA` that we imported is a standard JSON schema that defines valid operations like: + +* `render` (displaying a UI) +* `update` (changing data in an existing UI) + +Because the output is structured JSON, you may parse and validate it before sending it to the client. + +```python +# 1. Parse the JSON +# Warning: Parsing the output as JSON is a fragile implementation useful for documentation. +# LLMs often put Markdown fences around JSON output, and can make other mistakes. +# Rely on frameworks to parse the JSON for you. +parsed_json_data = json.loads(json_string_cleaned) + +# 2. Validate against A2UI_SCHEMA +# This ensures the LLM generated valid A2UI commands +jsonschema.validate( + instance=parsed_json_data, schema=self.a2ui_schema_object +) +``` + +By validating the output against `A2UI_SCHEMA`, you ensure that your client never receives malformed UI instructions. + +TODO: Continue this guide with examples of how to parse, validate, and send the output to the client renderer without the A2A extension. diff --git a/docs/guides/client-setup.md b/docs/guides/client-setup.md new file mode 100644 index 00000000..d0ce28ea --- /dev/null +++ b/docs/guides/client-setup.md @@ -0,0 +1,108 @@ +# Client Setup Guide + +Integrate A2UI into your application using the renderer for your platform. + +## Renderers + +| Renderer | Platform | Status | +| ------------------------ | ------------------ | ----------------- | +| **Lit (Web Components)** | Web | ✅ Stable | +| **Angular** | Web | ✅ Stable | +| **Flutter (GenUI SDK)** | Mobile/Desktop/Web | ✅ Stable | +| **React** | Web | 🚧 Coming Q1 2026 | +| **SwiftUI** | iOS/macOS | 🚧 Planned Q2 2026 | +| **Jetpack Compose** | Android | 🚧 Planned Q2 2026 | + +## Web Components (Lit) + +!!! warning "Attention" + The Lit client library is not yet published to NPM. Check back in the + coming days. + +```bash +npm install @a2ui/web-lib lit @lit-labs/signals +``` + +The Lit renderer uses: + +- **Message Processor**: Manages A2UI state and processes incoming messages +- **`` component**: Renders surfaces in your app +- **Lit Signals**: Provides reactive state management for automatic UI updates + +TODO: Add verified setup example. + +**See working example:** [Lit shell sample](https://github.com/google/a2ui/tree/main/samples/client/lit/shell) + +## Angular + +!!! warning "Attention" + The Angular client library is not yet published to NPM. Check back in the + coming days. + +```bash +npm install @a2ui/angular @a2ui/web-lib +``` + +The Angular renderer provides: + +- **`provideA2UI()` function**: Configures A2UI in your app config +- **`Surface` component**: Renders A2UI surfaces +- **`MessageProcessor` service**: Handles incoming A2UI messages + +TODO: Add verified setup example. + +**See working example:** [Angular restaurant sample](https://github.com/google/a2ui/tree/main/samples/client/angular/projects/restaurant) + +## Flutter (GenUI SDK) + +```bash +flutter pub add flutter_genui +``` + +Flutter uses the GenUI SDK which provides native A2UI rendering. + +**Docs:** [GenUI SDK](https://docs.flutter.dev/ai/genui) | [GitHub](https://github.com/flutter/genui) | [README in GenUI Flutter Package](https://github.com/flutter/genui/blob/main/packages/genui/README.md#getting-started-with-genui) + +## Connecting to Agents + +Your client application needs to: +1. **Receive A2UI messages** from the agent (via transport) +2. **Process messages** using the Message Processor +3. **Send user actions** back to the agent + +Common transport options: +- **Server-Sent Events (SSE)**: One-way streaming from server to client +- **WebSockets**: Bidirectional real-time communication +- **A2A Protocol**: Standardized agent-to-agent communication with A2UI support + +TODO: Add transport implementation examples. + +**See:** [Transports guide](../transports.md) + +## Handling User Actions + +When users interact with A2UI components (clicking buttons, submitting forms, etc.), the client: +1. Captures the action event from the component +2. Resolves any data context needed for the action +3. Sends the action to the agent +4. Processes the agent's response messages + +TODO: Add action handling examples. + +## Error Handling + +Common errors to handle: +- **Invalid Surface ID**: Surface referenced before `beginRendering` was received +- **Invalid Component ID**: Component IDs must be unique within a surface +- **Invalid Data Path**: Check data model structure and JSON Pointer syntax +- **Schema Validation Failed**: Verify message format matches A2UI specification + +TODO: Add error handling examples. + +## Next Steps + +- **[Quickstart](../quickstart.md)**: Try the demo application +- **[Theming & Styling](theming.md)**: Customize the look and feel +- **[Custom Components](custom-components.md)**: Extend the component catalog +- **[Agent Development](agent-development.md)**: Build agents that generate A2UI +- **[Reference Documentation](../reference/messages.md)**: Deep dive into the protocol diff --git a/docs/guides/custom-components.md b/docs/guides/custom-components.md new file mode 100644 index 00000000..9582021f --- /dev/null +++ b/docs/guides/custom-components.md @@ -0,0 +1,79 @@ +# Custom Component Catalogs + +Extend A2UI by defining **custom catalogs** that include your own components alongside standard A2UI components. + +## Why Custom Catalogs? + +The A2UI Standard Catalog provides common UI elements (buttons, text fields, etc.), but your application might need specialized components: + +- **Domain-specific widgets**: Stock tickers, medical charts, CAD viewers +- **Third-party integrations**: Google Maps, payment forms, chat widgets +- **Brand-specific components**: Custom date pickers, product cards, dashboards + +**Custom catalogs** are collections of components that can include: +- Standard A2UI components (Text, Button, TextField, etc.) +- Your custom components (GoogleMap, StockTicker, etc.) +- Third-party components + +You register entire catalogs with your client application, not individual components. This allows agents and clients to agree on a shared, extended set of components while maintaining security and type safety. + +## How Custom Catalogs Work + +1. **Client Defines Catalog**: You create a catalog definition that lists both standard and custom components. +2. **Client Registers Catalog**: You register the catalog (and its component implementations) with your client app. +3. **Client Announces Support**: The client informs the agent which catalogs it supports. +4. **Agent Selects Catalog**: The agent chooses a catalog for a given UI surface. +5. **Agent Generates UI**: The agent generates `surfaceUpdate` messages using components from that catalog by name. + +## Defining Custom Catalogs + +TODO: Add detailed guide for defining custom catalogs for each platform. + +**Web (Lit / Angular):** +- How to define a catalog with both standard and custom components +- How to register the catalog with the A2UI client +- How to implement custom component classes + +**Flutter:** +- How to define custom catalogs using GenUI +- How to register custom component renderers + +**See working examples:** +- [Lit samples](https://github.com/google/a2ui/tree/main/samples/client/lit) +- [Angular samples](https://github.com/google/a2ui/tree/main/samples/client/angular) +- [Flutter GenUI docs](https://docs.flutter.dev/ai/genui) + +## Agent-Side: Using Components from a Custom Catalog + +Once a catalog is registered on the client, agents can use components from it in `surfaceUpdate` messages. + +The agent specifies which catalog to use via the `catalogId` in the `beginRendering` message. + +TODO: Add examples of: +- How agents select catalogs +- How agents reference custom components from catalogs +- How catalog versioning works + +## Data Binding and Actions + +Custom components support the same data binding and action mechanisms as standard components: + +- **Data binding**: Custom components can bind properties to data model paths using JSON Pointer syntax +- **Actions**: Custom components can emit actions that the agent receives and handles + +## Security Considerations + +When creating custom catalogs and components: + +1. **Allowlist components**: Only register components you trust in your catalogs +2. **Validate properties**: Always validate component properties from agent messages +3. **Sanitize user input**: If components accept user input, sanitize it before processing +4. **Limit API access**: Don't expose sensitive APIs or credentials to custom components + +TODO: Add detailed security best practices and code examples. + +## Next Steps + +- **[Theming & Styling](theming.md)**: Customize the look and feel of components +- **[Component Reference](../reference/components.md)**: See all standard components +- **[Agent Development](agent-development.md)**: Build agents that use custom components diff --git a/docs/guides/theming.md b/docs/guides/theming.md new file mode 100644 index 00000000..5a37f5d8 --- /dev/null +++ b/docs/guides/theming.md @@ -0,0 +1,180 @@ +# Theming & Styling + +Customize the look and feel of A2UI components to match your brand. + +## The A2UI Styling Philosophy + +A2UI follows a **client-controlled styling** approach: + +- **Agents describe *what* to show** (components and structure) +- **Clients decide *how* it looks** (colors, fonts, spacing) + +This ensures: + +- ✅ **Brand consistency**: All UIs match your app's design system +- ✅ **Security**: Agents can't inject arbitrary CSS or styling +- ✅ **Accessibility**: You control contrast, focus states, and ARIA attributes +- ✅ **Platform-native feel**: Web apps look like web, mobile looks like mobile + +## Styling Layers + +A2UI styling works in layers: + +```mermaid +flowchart TD + A["1. Semantic Hints
Agent provides hints
(e.g., usageHint: 'h1')"] + B["2. Theme Configuration
You configure
(colors, fonts, spacing)"] + C["3. Component Overrides
You customize
(CSS/styles for specific components)"] + D["4. Rendered Output
Native platform widgets"] + + A --> B --> C --> D +``` + +## Layer 1: Semantic Hints + +Agents provide semantic hints (not visual styles) to guide client rendering: + +```json +{ + "id": "title", + "component": { + "Text": { + "text": {"literalString": "Welcome"}, + "usageHint": "h1" + } + } +} +``` + +**Common `usageHint` values:** +- Text: `h1`, `h2`, `h3`, `h4`, `h5`, `body`, `caption` +- Other components have their own hints (see [Component Reference](../reference/components.md)) + +The client renderer maps these semantic hints to actual visual styles based on your theme and design system. + +## Layer 2: Theme Configuration + +Each renderer provides a way to configure your design system globally, including: + +- **Colors**: Primary, secondary, background, surface, error, success, etc. +- **Typography**: Font families, sizes, weights, line heights +- **Spacing**: Base units and scale (xs, sm, md, lg, xl) +- **Shapes**: Border radius values +- **Elevation**: Shadow styles for depth + +TODO: Add platform-specific theming guides: + +**Web (Lit):** +- How to configure theme via renderer initialization +- Available theme properties + +**Angular:** +- Integration with Angular Material theming +- Standalone A2UI theme configuration + +**Flutter:** +- How A2UI uses Flutter's `ThemeData` +- Custom theme properties + +**See working examples:** +- [Lit samples](https://github.com/google/a2ui/tree/main/samples/client/lit) +- [Angular samples](https://github.com/google/a2ui/tree/main/samples/client/angular) +- [Flutter GenUI docs](https://docs.flutter.dev/ai/genui) + +## Layer 3: Component Overrides + +Beyond global theming, you can override styles for specific components: + +**Web renderers:** +- CSS custom properties (CSS variables) for fine-grained control +- Standard CSS selectors for component-specific overrides + +**Flutter:** +- Widget-specific theme overrides via `ThemeData` + +TODO: Add detailed component override examples for each platform. + +## Common Styling Features + +### Dark Mode + +A2UI renderers typically support automatic dark mode based on system preferences: + +- Auto-detect system theme (`prefers-color-scheme`) +- Manual light/dark theme selection +- Custom dark theme configuration + +TODO: Add dark mode configuration examples. + +### Responsive Design + +A2UI components are responsive by default. You can further customize responsive behavior: + +- Media queries for different screen sizes +- Container queries for component-level responsiveness +- Responsive spacing and typography scales + +TODO: Add responsive design examples. + +### Custom Fonts + +Load and use custom fonts in your A2UI application: + +- Web fonts (Google Fonts, etc.) +- Self-hosted fonts +- Platform-specific font loading + +TODO: Add custom font examples. + +## Best Practices + +### 1. Use Semantic Hints, Not Visual Properties + +Agents should provide semantic hints (`usageHint`), never visual styles: + +```json +// ✅ Good: Semantic hint +{ + "component": { + "Text": { + "text": {"literalString": "Welcome"}, + "usageHint": "h1" + } + } +} + +// ❌ Bad: Visual properties (not supported) +{ + "component": { + "Text": { + "text": {"literalString": "Welcome"}, + "fontSize": 24, + "color": "#FF0000" + } + } +} +``` + +### 2. Maintain Accessibility + +- Ensure sufficient color contrast (WCAG AA: 4.5:1 for normal text, 3:1 for large text) +- Test with screen readers +- Support keyboard navigation +- Test in both light and dark modes + +### 3. Use Design Tokens + +Define reusable design tokens (colors, spacing, etc.) and reference them throughout your styles for consistency. + +### 4. Test Across Platforms + +- Test your theming on all target platforms (web, mobile, desktop) +- Verify both light and dark modes +- Check different screen sizes and orientations +- Ensure consistent brand experience across platforms + +## Next Steps + +- **[Custom Components](custom-components.md)**: Build custom components with your styling +- **[Component Reference](../reference/components.md)**: See styling options for all components +- **[Client Setup](client-setup.md)**: Set up the renderer in your app diff --git a/docs/index.md b/docs/index.md index 5dc5dcbc..b357ba2a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,67 +1,157 @@ --- hide: - - navigation - toc --- -
+
A2UI Logo A2UI Logo -# The Future of UI is LLM-Generated +# A Protocol for Agent-Driven Interfaces -

-A new open source UI Toolkit to facilitate LLM-generated UIs. A2UI is built with A2A protocol and allows an A2A agent to send interactive components instead of just text, using a high level framework-agnostic format that can be rendered natively on any surface (starting with examples for web and mobile). +

+A2UI enables AI agents to generate rich, interactive user interfaces that render natively across web, mobile, and desktop—without executing arbitrary code.

-[Join the Waitlist](https://goo.gle/a2ui-form){ .md-button .md-button--primary style="padding: 0.6rem 2rem; font-size: 1.1rem;" } -
-
- -
- -
+!!! warning "️Status: Early Stage Public Preview" + A2UI is currently in **v0.8 (Public Preview)**. The specification and + implementations are functional but are still evolving. We are opening the project to + foster collaboration, gather feedback, and solicit contributions (e.g., on client renderers). + Expect changes. -
- -
-
+## At a Glance + +A2UI is currently [v0.8](specification/v0.8-a2ui.md), +Apache 2.0 licensed, +created by Google with contributions from CopilotKit and the open source community, +and is in active development [on GitHub](https://github.com/google/A2UI). + +The problem A2UI solves is: **how can AI agents safely send rich UIs across trust boundaries?** + +Instead of text-only responses or risky code execution, A2UI lets agents send **declarative component descriptions** that clients render using their own native widgets. It's like having agents speak a universal UI language. + +In this repo you will find +[A2UI specifications](specification/v0.8-a2ui.md) +and implementations for +[renderers](renderers.md) (eg: Angular, Flutter, etc.) on the client side, +and [transports](/transports.md) (eg: A2A, etc.) which communicate A2UI messages between agents and clients. + +
+ +- :material-shield-check: **Secure by Design** + + --- + + Declarative data format, not executable code. Agents can only use pre-approved components from your catalog—no UI injection attacks. + +- :material-rocket-launch: **LLM-Friendly** + + --- + + Flat, streaming JSON structure designed for easy generation. LLMs can build UIs incrementally without perfect JSON in one shot. + +- :material-devices: **Framework-Agnostic** + + --- + + One agent response works everywhere. Render the same UI on Angular, Flutter, React, or native mobile with your own styled components. + +- :material-chart-timeline: **Progressive Rendering** + + --- -## A New Paradigm for UI Development + Stream UI updates as they're generated. Users see the interface building in real-time instead of waiting for complete responses. -A2UI's core philosophy enables the creation of dynamic, and adaptable user interfaces driven by AI. +
+ +## Get Started in 5 Minutes
-- :material-shield-lock: **Secure & Performant Transport** +- :material-clock-fast:{ .lg .middle } **[Quickstart Guide](quickstart.md)** --- - Built on the [Agent2Agent (A2A) protocol](https://a2a-protocol.org), A2UI inherits a secure transport layer, while mitigating risks like UI injection through a clean separation of structure and data. + Run the restaurant finder demo and see A2UI in action with Gemini-powered agents. + + [:octicons-arrow-right-24: Get started](quickstart.md) -- :material-code-json: **LLM-Friendly Format** +- :material-book-open-variant:{ .lg .middle } **[Core Concepts](concepts/overview.md)** --- - A2UI uses a streamable JSON Lines (JSONL) format designed for generative models. Transported over the A2A protocol, it enables progressive rendering and real-time UI updates. + Understand surfaces, components, data binding, and the adjacency list model. + + [:octicons-arrow-right-24: Learn concepts](concepts/overview.md) + +- :material-code-braces:{ .lg .middle } **[Developer Guides](guides/client-setup.md)** + + --- + + Integrate A2UI renderers into your app or build agents that generate UIs. + + [:octicons-arrow-right-24: Start building](guides/client-setup.md) -- :material-devices: **Truly Framework-Agnostic** +- :material-file-document:{ .lg .middle } **[Protocol Reference](specification/v0.8-a2ui.md)** --- - Built for maximum portability. Render components on any platform, with initial clients for JavaScript Web Components, Flutter, and more to come. + Dive into the complete technical specification and message types. + + [:octicons-arrow-right-24: Read the spec](specification/v0.8-a2ui.md)
+ +## How It Works + +1. **User sends a message** to an AI agent +2. **Agent generates A2UI messages** describing the UI (structure + data) +3. **Messages stream** to the client application +4. **Client renders** using native components (Angular, Flutter, React, etc.) +5. **User interacts** with the UI, sending actions back to the agent +6. **Agent responds** with updated A2UI messages + +![End-to-End Data Flow](assets/end-to-end-data-flow.png) + +## A2UI in Action + +### Landscape Architect Demo + +
+
+ +
+

+ Watch an agent generate all of the interfaces for a landscape architect application. The user uploads a photo; the agent uses Gemini to understand it and generate a custom form for landscaping needs. +

+
+ +### Custom Components: Interactive Charts & Maps + +
+
+ +
+

+ Watch an agent chose to respond with a chart component to answer a numberical summary quesiton. Then the agent chooses a Google Map component to answer a location question. Both are custom components offered by the client. +

+
+ +### A2UI Composer + +CopilotKit has a public [A2UI Widget Builder](https://go.copilotkit.ai/A2UI-widget-builder) to try out as well. + +[![A2UI Composer](assets/A2UI-widget-builder.png)](https://go.copilotkit.ai/A2UI-widget-builder) diff --git a/docs/introduction/agent-ui-ecosystem.md b/docs/introduction/agent-ui-ecosystem.md new file mode 100644 index 00000000..fa0c7fcc --- /dev/null +++ b/docs/introduction/agent-ui-ecosystem.md @@ -0,0 +1,36 @@ +# A2UI in the Agent Ecosystem + +The space for agentic UI is evolving rapidly, with excellent tools emerging to solve different parts of the stack. A2UI is not a replacement for these frameworks—it's a specialized protocol that solves the specific problem of **interoperable, cross-platform, generative or template-based UI responses.** + +## At a glance + +The A2UI approach is to send JSON as a message to the client, which then uses a renderer to convert it into native UI components. LLMs can generate the component layout on the fly or you can use a template. + +!!! tip "" + **This makes it secure like data, and expressive like code.** + +This rest of this page will help you understand A2UI in relationship to other options. + +## Navigating the Agentic UI Ecosystem + +### 1. Building the "Host" Application UI + +If you're building a full-stack application (the "host" UI that the user interacts with), in addition to building the actual UI, you may also utilize a framework **(AG UI / CopilotKit, Vercel AI SDK, GenUI SDK for Flutter which already uses A2UI under the covers)** to handle the "pipes": state synchronization, chat history, and input handling. + +**Where A2UI fits:** A2UI is complementary. If you connect your host application using AG UI, it can use A2UI as the data format for rendering responses from the host agent and also from third-party or remote agents. This gives you the best of both worlds: a rich, stateful host app that can safely render content from external agents it doesn't control. + +- **A2UI with A2A:** You can send via A2A directly to a client front end. +- **A2UI with AG UI:** You can send via AG UI directly to a client front end. +- A2UI with REST, SSE, WebSockets and other transports are feasible but not yet available. + +### 2. UI as a "Resource" (MCP Apps) + +The **Model Context Protocol (MCP)** has [recently introduced **MCP Apps**](https://blog.modelcontextprotocol.io/posts/2025-11-21-mcp-apps/), a new standard consolidating the great work from MCP-UI and OpenAI to enable servers to provide interactive interfaces. This approach treats UI as a resource (accessed via a `ui://` URI) that tools can return, typically rendering pre-built HTML content within a sandboxed `iframe` to ensure isolation and security. + +**How A2UI is different:** A2UI takes a "native-first" approach that is distinct from the resource-fetching model of MCP Apps. Instead of retrieving an opaque payload to display in a sandbox, an A2UI agent sends a blueprint of native components. This allows the UI to inherit the host app's styling and accessibility features perfectly. In a multi-agent system, an orchestrator agent can easily understand the lightweight A2UI message content from a subagent, allowing for more fluid collaboration between agents. + +### 3. Platform-Specific Ecosystems (OpenAI ChatKit) + +Tools like **ChatKit** offer a highly integrated, optimized experience for deploying agents specifically within the OpenAI ecosystem. + +**How A2UI is different:** A2UI is designed for developers building their own agentic surfaces across Web, Flutter, and native mobile, or for enterprise meshes (like **A2A**) where agents need to communicate across trust boundaries. A2UI gives the client more control over styling at the expense of the agent, in order to allow for greater visual consistency with the host client application. diff --git a/docs/introduction/how-to-use.md b/docs/introduction/how-to-use.md new file mode 100644 index 00000000..ac052b16 --- /dev/null +++ b/docs/introduction/how-to-use.md @@ -0,0 +1,53 @@ +# How Can I Use A2UI? + +Choose the integration path that matches your role and use case. + +## Three Paths + +### Path 1: Building a Host Application (Frontend) + +Integrate A2UI rendering into your existing app or build a new agent-powered frontend. + +**Choose a renderer:** + +- **Web:** Lit, Angular +- **Mobile/Desktop:** Flutter GenUI SDK +- **React:** Coming Q1 2026 + +**Quick setup:** + +If we are using an Angular app, we can add the Angular renderer: + +```bash +npm install @a2ui/angular +``` + +Connect to agent messages (SSE, WebSockets, or A2A) and customize styling to match your brand. + +**Next:** [Client Setup Guide](../guides/client-setup.md) | [Theming](../guides/theming.md) + +--- + +### Path 2: Building an Agent (Backend) + +Create an agent that generates A2UI responses for any compatible client. + +**Choose your framework:** + +- **Python:** Google ADK, LangChain, custom +- **Node.js:** A2A SDK, Vercel AI SDK, custom + +Include the A2UI schema in your LLM prompts, generate JSONL messages, and stream to clients over SSE, WebSockets, or A2A. + +**Next:** [Agent Development Guide](../guides/agent-development.md) + +--- + +### Path 3: Using an Existing Framework + +Use A2UI through frameworks with built-in support: + +- **[AG UI / CopilotKit](https://ag-ui.com/)** - Full-stack React framework with A2UI rendering +- **[Flutter GenUI SDK](https://docs.flutter.dev/ai/genui)** - Cross-platform generative UI (uses A2UI internally) + +**Next:** [Agent UI Ecosystem](agent-ui-ecosystem.md) | [Where is A2UI Used?](where-is-it-used.md) diff --git a/docs/introduction/what-is-a2ui.md b/docs/introduction/what-is-a2ui.md new file mode 100644 index 00000000..ed3d68e5 --- /dev/null +++ b/docs/introduction/what-is-a2ui.md @@ -0,0 +1,95 @@ +# What is A2UI? + +**A2UI (Agent to UI) is a declarative UI protocol for agent-driven interfaces.** AI agents generate rich, interactive UIs that render natively across platforms (web, mobile, desktop) without executing arbitrary code. + +## The Problem + +**Text-only agent interactions are inefficient:** + +``` +User: "Book a table for 2 tomorrow at 7pm" +Agent: "Okay, for what day?" +User: "Tomorrow" +Agent: "What time?" +... +``` + +**Better:** Agent generates a form with date picker, time selector, and submit button. Users interact with UI, not text. + +## The Challenge + +In multi-agent systems, agents often run remotely (different servers, organizations). They can't directly manipulate your UI—they must send messages. + +**Traditional approach:** Send HTML/JavaScript in iframes + +- Heavy, visually disjointed +- Security complexity +- Doesn't match app styling + +**Need:** Transmit UI that's safe like data, expressive like code. + +## The Solution + +A2UI: JSON messages describing UI that: + +- LLMs generate as structured output +- Travel over any transport (A2A, AG UI, SSE, WebSockets) +- Client renders using its own native components + +**Result:** Client controls security and styling, agent-generated UI feels native. + +### Example + +```json +{"surfaceUpdate": {"surfaceId": "booking", "components": [ + {"id": "title", "component": {"Text": {"text": {"literalString": "Book Your Table"}, "usageHint": "h1"}}}, + {"id": "datetime", "component": {"DateTimeInput": {"value": {"path": "/booking/date"}, "enableDate": true}}}, + {"id": "submit-text", "component": {"Text": {"text": {"literalString": "Confirm"}}}}, + {"id": "submit-btn", "component": {"Button": {"child": "submit-text", "action": {"name": "confirm_booking"}}}} +]}} +``` + +```json +{"dataModelUpdate": {"surfaceId": "booking", "contents": [ + {"key": "booking", "valueMap": [{"key": "date", "valueString": "2025-12-16T19:00:00Z"}]} +]}} +``` + +```json +{"beginRendering": {"surfaceId": "booking", "root": "title"}} +``` + +Client renders these messages as native components (Angular, Flutter, React, etc.). + +## Core Value + +**1. Security:** Declarative data, not code. Agent requests components from client's trusted catalog. No code execution risk. + +**2. Native Feel:** No iframes. Client renders with its own UI framework. Inherits app styling, accessibility, performance. + +**3. Portability:** One agent response works everywhere. Same JSON renders on web (Lit/Angular/React), mobile (Flutter/SwiftUI/Jetpack Compose), desktop. + +## Design Principles + +**1. LLM-Friendly:** Flat component list with ID references. Easy to generate incrementally, correct mistakes, stream. + +**2. Framework-Agnostic:** Agent sends abstract component tree. Client maps to native widgets (web/mobile/desktop). + +**3. Separation of Concerns:** Three layers—UI structure, application state, client rendering. Enables data binding, reactive updates, clean architecture. + +## What A2UI Is NOT + +- Not a framework (it's a protocol) +- Not a replacement for HTML (for agent-generated UIs, not static sites) +- Not a robust styling system (client controls styling with limited serverside styling support) +- Not limited to web (works on mobile and desktop) + +## Key Concepts + +- **Surface**: Canvas for components (dialog, sidebar, main view) +- **Component**: UI element (Button, TextField, Card, etc.) +- **Data Model**: Application state, components bind to it +- **Catalog**: Available component types +- **Message**: JSON object (`surfaceUpdate`, `dataModelUpdate`, `beginRendering`, etc.) + +For a comparison of similar projects, see [Agent UI Ecosystem](agent-ui-ecosystem.md). diff --git a/docs/introduction/where-is-it-used.md b/docs/introduction/where-is-it-used.md new file mode 100644 index 00000000..e3f30645 --- /dev/null +++ b/docs/introduction/where-is-it-used.md @@ -0,0 +1,150 @@ +# Where is A2UI Used? + +A2UI is being adopted by teams at Google and partner organizations to build the next generation of agent-driven applications. Here are real-world examples of where A2UI is making an impact. + +## Production Deployments + +### Google Opal: AI Mini-Apps for Everyone + +[Opal](http://opal.google) enables hundreds of thousands of people to build, edit, and share AI mini-apps using natural language—no coding required. + +**How Opal uses A2UI:** + +The Opal team at Google has been a **core contributor to A2UI** from the beginning. They use A2UI to power the dynamic, generative UI system that makes Opal's AI mini-apps possible. + +- **Rapid prototyping**: Build and test new UI patterns quickly +- **User-generated apps**: Anyone can create apps with custom UIs +- **Dynamic interfaces**: UIs adapt to each use case automatically + +> "A2UI is foundational to our work. It gives us the flexibility to let the AI drive the user experience in novel ways, without being constrained by a fixed front-end. Its declarative nature and focus on security allow us to experiment quickly and safely." +> +> **— Dimitri Glazkov**, Principal Engineer, Opal Team + +**Learn more:** [opal.google](http://opal.google) + +--- + +### Gemini Enterprise: Custom Agents for Business + +Gemini Enterprise enables businesses to build powerful, custom AI agents tailored to their specific workflows and data. + +**How Gemini Enterprise uses A2UI:** + +A2UI is being integrated to allow enterprise agents to render **rich, interactive UIs** within business applications—going beyond simple text responses to guide employees through complex workflows. + +- **Data entry forms**: AI-generated forms for structured data collection +- **Approval dashboards**: Dynamic UIs for review and approval processes +- **Workflow automation**: Step-by-step interfaces for complex tasks +- **Custom enterprise UIs**: Tailored interfaces for industry-specific needs + +> "Our customers need their agents to do more than just answer questions; they need them to guide employees through complex workflows. A2UI will allow developers building on Gemini Enterprise to have their agents generate the dynamic, custom UIs needed for any task, from data entry forms to approval dashboards, dramatically accelerating workflow automation." +> +> **— Fred Jabbour**, Product Manager, Gemini Enterprise + +**Learn more:** [Gemini Enterprise](https://cloud.google.com/gemini) + +--- + +### Flutter GenUI SDK: Generative UI for Mobile + +The [Flutter GenUI SDK](https://docs.flutter.dev/ai/genui) brings dynamic, AI-generated UIs to Flutter applications across mobile, desktop, and web. + +**How GenUI uses A2UI:** + +GenUI SDK uses **A2UI as the underlying protocol** for communication between server-side agents and Flutter applications. When you use GenUI, you're using A2UI under the covers. + +- **Cross-platform support**: Same agent works on iOS, Android, web, desktop +- **Native performance**: Flutter widgets rendered natively on each platform +- **Brand consistency**: UIs match your app's design system +- **Server-driven UI**: Agents control what's shown without app updates + +> "Our developers choose Flutter because it lets them quickly create expressive, brand-rich, custom design systems that feel great on every platform. A2UI was a great fit for Flutter's GenUI SDK because it ensures that every user, on every platform, gets a high quality native feeling experience." +> +> **— Vijay Menon**, Engineering Director, Dart & Flutter + +**Try it:** +- [GenUI Documentation](https://docs.flutter.dev/ai/genui) +- [Getting Started Video](https://www.youtube.com/watch?v=nWr6eZKM6no) +- [Verdure Example](https://github.com/flutter/genui/tree/main/examples/verdure) (client-server A2UI sample) + +--- + +## Partner Integrations + +### AG UI / CopilotKit: Full-Stack Agentic Framework + +[AG UI](https://ag-ui.com/) and [CopilotKit](https://www.copilotkit.ai/) provide a comprehensive framework for building agentic applications, with **day-zero A2UI compatibility**. + +**How they work together:** + +AG UI excels at creating high-bandwidth connections between custom frontends and their dedicated agents. By adding A2UI support, developers get the best of both worlds: + +- **State synchronization**: AG UI handles app state and chat history +- **A2UI rendering**: Render dynamic UIs from third-party agents +- **Multi-agent support**: Coordinate UIs from multiple agents +- **React integration**: Seamless integration with React applications + +> "AG UI excels at creating a high-bandwidth connection between a custom-built front-end and its dedicated agent. By adding support for A2UI, we're giving developers the best of both worlds. They can now build rich, state-synced applications that can also render dynamic UIs from third-party agents via A2UI. It's a perfect match for a multi-agent world." +> +> **— Atai Barkai**, Founder of CopilotKit and AG UI + +**Learn more:** +- [AG UI](https://ag-ui.com/) +- [CopilotKit](https://www.copilotkit.ai/) + +--- + +### Google's AI-Powered Products + +As Google adopts AI across the company, A2UI provides a **standardized way for AI agents to exchange user interfaces**, not just text. + +**Internal agent adoption:** + +- **Multi-agent workflows**: Multiple agents contribute to the same surface +- **Remote agent support**: Agents running on different services can provide UI +- **Standardization**: Common protocol across teams reduces integration overhead +- **External exposure**: Internal agents can be easily exposed externally (e.g., Gemini Enterprise) + +> "Much like A2A lets any agent talk to another agent regardless of platform, A2UI standardizes the user interface layer and supports remote agent use cases through an orchestrator. This has been incredibly powerful for internal teams, allowing them to rapidly develop agents where rich user interfaces are the norm, not the exception. As Google pushes further into generative UI, A2UI provides a perfect platform for server-driven UI that renders on any client." +> +> **— James Wren**, Senior Staff Engineer, AI Powered Google + +--- + +## Community Projects + +The A2UI community is building exciting projects: + +### Open Source Examples + +- **Restaurant Finder** ([samples/agent/adk/restaurant_finder](https://github.com/google/A2UI/tree/main/samples/agent/adk/restaurant_finder)) + - Table reservation with dynamic forms + - Gemini-powered agent + - Full source code available + +- **Contact Lookup** ([samples/agent/adk/contact_lookup](https://github.com/google/A2UI/tree/main/samples/agent/adk/contact_lookup)) + - Search interface with results list + - A2A agent example + - Demonstrates data binding + +- **Component Gallery** ([samples/client/angular - gallery mode](https://github.com/google/A2UI/tree/main/samples/client/angular)) + - Interactive showcase of all components + - Live examples with code + - Great for learning + +### Community Contributions + +Have you built something with A2UI? [Share it with the community!](../community.md) + +--- + +## Next Steps + +- [Quickstart Guide](../quickstart.md) - Try the demo +- [Agent Development](../guides/agent-development.md) - Build an agent +- [Client Setup](../guides/client-setup.md) - Integrate a renderer +- [Community](../community.md) - Join the community + +--- + +**Using A2UI in production?** Share your story on [GitHub Discussions](https://github.com/google/A2UI/discussions). diff --git a/docs/introduction/who-is-it-for.md b/docs/introduction/who-is-it-for.md new file mode 100644 index 00000000..b75c8862 --- /dev/null +++ b/docs/introduction/who-is-it-for.md @@ -0,0 +1,66 @@ +# Who is A2UI For? + +Developers building AI agents with rich, interactive UIs. + +## Three Audiences + +### 1. Host App Developers (Frontend) + +Build multi-agent platforms, enterprise assistants, or cross-platform apps where agents generate UI. + +**Why A2UI:** + +- Brand control: client owns styling and design system +- Multi-agent: support local, remote, and third-party agents +- Secure: declarative data, no code execution +- Cross-platform: web, mobile, desktop +- Interoperable: open source, same spec with multiple renderers + +**Get started:** [Client Setup](../guides/client-setup.md) | [Theming](../guides/theming.md) | [Custom Components](../guides/custom-components.md) + +### 2. Agent Developers (Backend/AI) + +Build agents that generate forms, dashboards, and interactive workflows. + +**Why A2UI:** + +- LLM-friendly: flat structure, easy to generate incrementally +- Rich interactions: beyond text (forms, tables, visualizations) +- Generations not tools: UI as part of the generated output from the agent +- Portable: one agent response works across all A2UI clients +- Streamable: progressive rendering as you generate + +**Get started:** [Agent Development](../guides/agent-development.md) + +### 3. Platform Builders (SDK Creators) + +Build agent orchestration platforms, frameworks, or UI integrations. + +Do you bring remote agents into your app? + +Do you ship your agent into other apps you don't necissarily control? + +**Why A2UI:** + +- Standard protocol: interoperable with A2A and other transports +- Extensible: custom component catalogs +- Open source (Apache 2.0) + +**Get started:** [Community](../community.md) | [Roadmap](../roadmap.md) + +--- + +## When to Use A2UI + +✅ **Agent-generated UI** - Core purpose +✅ **Multi-agent systems** - Standard protocol across trust boundaries +✅ **Cross-platform apps** - One agent, many renderers (web/mobile/desktop) +✅ **Security critical** - Declarative data, no code execution +✅ **Brand consistency** - Client controls styling + +❌ **Static websites** - Use HTML/CSS +❌ **Simple text-only chat** - Use Markdown +❌ **Remote widgets not integrated with client** - Use iframes, like MCP Apps + +❌ **Rapid UI + Agent app built together** - Use AG UI / CopilotKit + diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 00000000..9ae3e076 --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,270 @@ +# Quickstart: Run A2UI in 5 Minutes + +Get hands-on with A2UI by running the restaurant finder demo. This guide will have you experiencing agent-generated UI in less than 5 minutes. + +## What You'll Build + +By the end of this quickstart, you'll have: + +- ✅ A running web app with A2UI Lit renderer +- ✅ A Gemini-powered agent that generates dynamic UIs +- ✅ An interactive restaurant finder with form generation, time selection, and confirmation flows +- ✅ Understanding of how A2UI messages flow from agent to UI + +## Prerequisites + +Before you begin, make sure you have: + +- **Node.js** (v18 or later) - [Download here](https://nodejs.org/) +- **A Gemini API key** - [Get one free from Google AI Studio](https://aistudio.google.com/apikey) + +!!! warning "Security Notice" + This demo runs an A2A agent that uses Gemini to generate A2UI responses. The agent has access to your API key and will make requests to Google's Gemini API. Always review agent code before running it in production environments. + +## Step 1: Clone the Repository + +```bash +git clone https://github.com/google/a2ui.git +cd a2ui +``` + +## Step 2: Set Your API Key + +Export your Gemini API key as an environment variable: + +```bash +export GEMINI_API_KEY="your_gemini_api_key_here" +``` + +## Step 3: Navigate to the Lit Client + +```bash +cd samples/client/lit +``` + +## Step 4: Install and Run + +Run the one-command demo launcher: + +```bash +npm install +npm run demo:all +``` + +This command will: + +1. Install all dependencies +2. Build the A2UI renderer +3. Start the A2A restaurant finder agent (Python backend) +4. Launch the development server +5. Open your browser to `http://localhost:5173` + +!!! success "Demo Running" + If everything worked, you should see the web app in your browser. The agent is now ready to generate UI! + +## Step 5: Try It Out + +In the web app, try these prompts: + +1. **"Book a table for 2"** - Watch the agent generate a reservation form +2. **"Find Italian restaurants near me"** - See dynamic search results +3. **"What are your hours?"** - Experience different UI layouts for different intents + +### What's Happening Behind the Scenes + +``` +┌─────────────┐ ┌──────────────┐ ┌────────────────┐ +│ You Type │────────>│ A2A Agent │────────>│ Gemini API │ +│ a Message │ │ (Python) │ │ (LLM) │ +└─────────────┘ └──────────────┘ └────────────────┘ + │ │ + │ Generates A2UI JSON │ + │<────────────────────────┘ + │ + │ Streams JSONL messages + v + ┌──────────────┐ + │ Web App │ + │ (A2UI Lit │ + │ Renderer) │ + └──────────────┘ + │ + │ Renders native components + v + ┌──────────────┐ + │ Your UI │ + └──────────────┘ +``` + +1. **You send a message** via the web UI +2. **The A2A agent** receives it and sends the conversation to Gemini +3. **Gemini generates** A2UI JSON messages describing the UI +4. **The A2A agent streams** these messages back to the web app +5. **The A2UI renderer** converts them into native web components +6. **You see the UI** rendered in your browser + +## Anatomy of an A2UI Message + +Let's peek at what the agent is sending. Here's a simplified example of the JSON messages: + +### Defining the UI + +```json +{ + "surfaceUpdate": { + "surfaceId": "main", + "components": [ + { + "id": "header", + "component": { + "Text": { + "text": {"literalString": "Book Your Table"}, + "usageHint": "h1" + } + } + }, + { + "id": "date-picker", + "component": { + "DateTimeInput": { + "label": {"literalString": "Select Date"}, + "value": {"path": "/reservation/date"}, + "enableDate": true + } + } + }, + { + "id": "submit-btn", + "component": { + "Button": { + "child": "submit-text", + "action": {"name": "confirm_booking"} + } + } + }, + { + "id": "submit-text", + "component": { + "Text": {"text": {"literalString": "Confirm Reservation"}} + } + } + ] + } +} +``` + +This defines the UI components for the surface: a text header, a date picker, and a button. + +### Populating Data + +```json +{ + "dataModelUpdate": { + "surfaceId": "main", + "contents": [ + { + "key": "reservation", + "valueMap": [ + {"key": "date", "valueString": "2025-12-15"}, + {"key": "time", "valueString": "19:00"}, + {"key": "guests", "valueInt": 2} + ] + } + ] + } +} +``` + +This populates the data model that components can bind to. + +### Signaling Render + +```json +{"beginRendering": {"surfaceId": "main", "root": "header"}} +``` + +This tells the client it has enough information to render the UI. + +!!! tip "It's Just JSON" + Notice how readable and structured this is? LLMs can generate this easily, and it's safe to transmit and render—no code execution required. + +## Exploring Other Demos + +The repository includes several other demos: + +### Component Gallery (No Agent Required) + +See all available A2UI components: + +```bash +npm start -- gallery +``` + +This runs a client-only demo showcasing every standard component (Card, Button, TextField, Timeline, etc.) with live examples and code samples. + +### Contact Lookup Demo + +Try a different agent use case: + +```bash +npm run demo:contact +``` + +This demonstrates a contact lookup agent that generates search forms and result lists. + +## What's Next? + +Now that you've seen A2UI in action, you're ready to: + +- **[Learn Core Concepts](concepts/overview.md)**: Understand surfaces, components, and data binding +- **[Set Up Your Own Client](guides/client-setup.md)**: Integrate A2UI into your own app +- **[Build an Agent](guides/agent-development.md)**: Create agents that generate A2UI responses +- **[Explore the Protocol](reference/messages.md)**: Dive into the technical specification + +## Troubleshooting + +### Port Already in Use + +If port 5173 is already in use, the dev server will automatically try the next available port. Check the terminal output for the actual URL. + +### API Key Issues + +If you see errors about missing API keys: + +1. Verify the key is exported: `echo $GEMINI_API_KEY` +2. Make sure it's a valid Gemini API key from [Google AI Studio](https://aistudio.google.com/apikey) +3. Try re-exporting: `export GEMINI_API_KEY="your_key"` + +### Python Dependencies + +The demo uses Python for the A2A agent. If you encounter Python errors: + +```bash +# Make sure Python 3.10+ is installed +python3 --version + +# The demo should auto-install dependencies via the npm script +# If not, manually install them: +cd ../../agent/adk/restaurant_finder +pip install -r requirements.txt +``` + +### Still Having Issues? + +- Check the [GitHub Issues](https://github.com/google/a2ui/issues) +- Review the [samples/client/lit/README.md](https://github.com/google/a2ui/tree/main/samples/client/lit) +- Join the community discussions + +## Understanding the Demo Code + +Want to see how it works? Check out: + +- **Agent Code**: `samples/agent/adk/restaurant_finder/` - The Python A2A agent +- **Client Code**: `samples/client/lit/` - The Lit web client with A2UI renderer +- **A2UI Renderer**: `web-lib/` - The web renderer implementation + +Each directory has its own README with detailed documentation. + +--- + +**Congratulations!** You've successfully run your first A2UI application. You've seen how an AI agent can generate rich, interactive UIs that render natively in a web application—all through safe, declarative JSON messages. diff --git a/docs/reference/components.md b/docs/reference/components.md new file mode 100644 index 00000000..e51de6af --- /dev/null +++ b/docs/reference/components.md @@ -0,0 +1,272 @@ +# Component Gallery + +This page showcases all standard A2UI components with examples and usage patterns. For the complete technical specification, see the [Standard Catalog Definition](https://github.com/google/A2UI/blob/main/specification/0.8/json/standard_catalog_definition.json). + +## Layout Components + +### Row + +Horizontal layout container. Children are arranged left-to-right. + +```json +{ + "id": "toolbar", + "component": { + "Row": { + "children": {"explicitList": ["btn1", "btn2", "btn3"]}, + "alignment": "center" + } + } +} +``` + +**Properties:** + +- `children`: Static array (`explicitList`) or dynamic `template` +- `distribution`: Horizontal distribution of children (`start`, `center`, `end`, `spaceBetween`, `spaceAround`, `spaceEvenly`) +- `alignment`: Vertical alignment (`start`, `center`, `end`, `stretch`) + +### Column + +Vertical layout container. Children are arranged top-to-bottom. + +```json +{ + "id": "content", + "component": { + "Column": { + "children": {"explicitList": ["header", "body", "footer"]} + } + } +} +``` + +**Properties:** + +- `children`: Static array (`explicitList`) or dynamic `template` +- `distribution`: Vertical distribution of children (`start`, `center`, `end`, `spaceBetween`, `spaceAround`, `spaceEvenly`) +- `alignment`: Horizontal alignment (`start`, `center`, `end`, `stretch`) + +## Display Components + +### Text + +Display text content with optional styling. + +```json +{ + "id": "title", + "component": { + "Text": { + "text": {"literalString": "Welcome to A2UI"}, + "usageHint": "h1" + } + } +} +``` + +**`usageHint` values:** `h1`, `h2`, `h3`, `h4`, `h5`, `caption`, `body` + +### Image + +Display images from URLs. + +```json +{ + "id": "logo", + "component": { + "Image": { + "url": {"literalString": "https://example.com/logo.png"} + } + } +} +``` + +### Icon + +Display icons using Material Icons or custom icon sets. + +```json +{ + "id": "check-icon", + "component": { + "Icon": { + "name": {"literalString": "check_circle"} + } + } +} +``` + +### Divider + +Visual separator line. + +```json +{ + "id": "separator", + "component": { + "Divider": { + "axis": "horizontal" + } + } +} +``` + +## Interactive Components + +### Button + +Clickable button with action support. + +```json +{ + "id": "submit-btn-text", + "component": { + "Text": { + "text": { "literalString": "Submit" } + } + } +} +{ + "id": "submit-btn", + "component": { + "Button": { + "child": "submit-btn-text", + "primary": true, + "action": {"name": "submit_form"} + } + } +} +``` + +**Properties:** +- `child`: The ID of the component to display in the button (e.g., a Text or Icon). +- `primary`: Boolean indicating if this is a primary action. +- `action`: The action to perform on click. + +### TextField + +Text input field. + +```json +{ + "id": "email-input", + "component": { + "TextField": { + "label": {"literalString": "Email Address"}, + "text": {"path": "/user/email"}, + "textFieldType": "shortText" + } + } +} +``` + +**`textFieldType` values:** `date`, `longText`, `number`, `shortText`, `obscured` + +Boolean toggle. + +```json +{ + "id": "terms-checkbox", + "component": { + "Checkbox": { + "label": {"literalString": "I agree to the terms"}, + "value": {"path": "/form/agreedToTerms"} + } + } +} +``` + +## Container Components + +### Card + +Container with elevation/border and padding. + +```json +{ + "id": "info-card", + "component": { + "Card": { + "child": "card-content" + } + } +} +``` + +### Modal + +Overlay dialog. + +```json +{ + "id": "confirmation-modal", + "component": { + "Modal": { + "entryPointChild": "open-modal-btn", + "contentChild": "modal-content" + } + } +} +``` + +### Tabs + +Tabbed interface. + +```json +{ + "id": "settings-tabs", + "component": { + "Tabs": { + "tabItems": [ + {"title": {"literalString": "General"}, "child": "general-settings"}, + {"title": {"literalString": "Privacy"}, "child": "privacy-settings"}, + {"title": {"literalString": "Advanced"}, "child": "advanced-settings"} + ] + } + } +} +``` + +Scrollable list of items. + +```json +{ + "id": "message-list", + "component": { + "List": { + "children": { + "template": { + "dataBinding": "/messages", + "componentId": "message-item" + } + } + } + } +} +``` + +## Common Properties + +Most components support these common properties: + +- `id` (required): Unique identifier for the component instance. +- `weight`: Flex-grow value when the component is a direct child of a Row or Column. This property is specified alongside `id` and `component`. + +## Live Examples + +To see all components in action, run the component gallery demo: + +```bash +cd samples/client/angular +npm start -- gallery +``` + +This launches a live gallery with all components, their variations, and interactive examples. + +## Further Reading + +- **[Standard Catalog Definition](../../specification/0.9/json/standard_catalog_definition.json)**: Complete technical specification +- **[Custom Components Guide](../guides/custom-components.md)**: Build your own components +- **[Theming Guide](../guides/theming.md)**: Style components to match your brand diff --git a/docs/reference/messages.md b/docs/reference/messages.md new file mode 100644 index 00000000..d122cd7a --- /dev/null +++ b/docs/reference/messages.md @@ -0,0 +1,396 @@ +# Message Types + +This reference provides detailed documentation for all A2UI message types. + +## Message Format + +All A2UI messages are JSON objects sent as JSON Lines (JSONL). Each line contains exactly one message, and each message contains exactly one of these four keys: + +- `beginRendering` +- `surfaceUpdate` +- `dataModelUpdate` +- `deleteSurface` + +## beginRendering + +Signals the client that it has enough information to perform the initial render of a surface. + +### Schema + +```typescript +{ + beginRendering: { + surfaceId: string; // Required: Unique surface identifier + root: string; // Required: The ID of the root component to render + catalogId?: string; // Optional: URL of component catalog + styles?: object; // Optional: Styling information + } +} +``` + +### Properties + +| Property | Type | Required | Description | +| ----------- | ------ | -------- | --------------------------------------------------------------------------------------- | +| `surfaceId` | string | ✅ | Unique identifier for this surface. | +| `root` | string | ✅ | The `id` of the component that should be the root of the UI tree for this surface. | +| `catalogId` | string | ❌ | Identifier for the component catalog. Defaults to the v0.8 standard catalog if omitted. | +| `styles` | object | ❌ | Styling information for the UI, as defined by the catalog. | + +### Examples + +**Basic render signal:** + +```json +{ + "beginRendering": { + "surfaceId": "main", + "root": "root-component" + } +} +``` + +**With a custom catalog:** + +```json +{ + "beginRendering": { + "surfaceId": "custom-ui", + "root": "root-custom", + "catalogId": "https://my-company.com/a2ui/v0.8/my_custom_catalog.json" + } +} +``` + +### Usage Notes + +- Must be sent after the client has received the component definitions for the root component and its initial children. +- The client should buffer `surfaceUpdate` and `dataModelUpdate` messages and only render the UI for a surface after receiving its corresponding `beginRendering` message. + +--- + +## surfaceUpdate + +Add or update components within a surface. + +### Schema + +```typescript +{ + surfaceUpdate: { + surfaceId: string; // Required: Target surface + components: Array<{ // Required: List of components + id: string; // Required: Component ID + component: { // Required: Wrapper for component data + [ComponentType]: { // Required: Exactly one component type + ...properties // Component-specific properties + } + } + }> + } +} +``` + +### Properties + +| Property | Type | Required | Description | +| ------------ | ------ | -------- | ------------------------------ | +| `surfaceId` | string | ✅ | ID of the surface to update | +| `components` | array | ✅ | Array of component definitions | + +### Component Object + +Each object in the `components` array must have: + +- `id` (string, required): Unique identifier within the surface +- `component` (object, required): A wrapper object that contains exactly one key, which is the component type (e.g., `Text`, `Button`). + +### Examples + +**Single component:** + +```json +{ + "surfaceUpdate": { + "surfaceId": "main", + "components": [ + { + "id": "greeting", + "component": { + "Text": { + "text": {"literalString": "Hello, World!"}, + "usageHint": "h1" + } + } + } + ] + } +} +``` + +**Multiple components (adjacency list):** + +```json +{ + "surfaceUpdate": { + "surfaceId": "main", + "components": [ + { + "id": "root", + "component": { + "Column": { + "children": {"explicitList": ["header", "body"]} + } + } + }, + { + "id": "header", + "component": { + "Text": { + "text": {"literalString": "Welcome"} + } + } + }, + { + "id": "body", + "component": { + "Card": { + "child": "content" + } + } + }, + { + "id": "content", + "component": { + "Text": { + "text": {"path": "/message"} + } + } + } + ] + } +} +``` + +**Updating existing component:** + +```json +{ + "surfaceUpdate": { + "surfaceId": "main", + "components": [ + { + "id": "greeting", + "component": { + "Text": { + "text": {"literalString": "Hello, Alice!"}, + "usageHint": "h1" + } + } + } + ] + } +} +``` + +The component with `id: "greeting"` is updated (not duplicated). + +### Usage Notes + +- One component must be designated as the `root` in the `beginRendering` message to serve as the tree root. +- Components form an adjacency list (flat structure with ID references). +- Sending a component with an existing ID updates that component. +- Children are referenced by ID. +- Components can be added incrementally (streaming). + +### Errors + +| Error | Cause | Solution | +| ---------------------- | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| Surface not found | `surfaceId` does not exist | Ensure a unique `surfaceId` is used consistently for a given surface. Surfaces are implicitly created on first update. | +| Invalid component type | Unknown component type | Check component type exists in the negotiated catalog. | +| Invalid property | Property doesn't exist for this type | Verify against catalog schema. | +| Circular reference | Component references itself as a child | Fix component hierarchy. | + +--- + +## dataModelUpdate + +Update the data model that components bind to. + +### Schema + +```typescript +{ + dataModelUpdate: { + surfaceId: string; // Required: Target surface + path?: string; // Optional: Path to a location in the model + contents: Array<{ // Required: Data entries + key: string; + valueString?: string; + valueNumber?: number; + valueBoolean?: boolean; + valueMap?: Array<{...}>; + }> + } +} +``` + +### Properties + +| Property | Type | Required | Description | +| ----------- | ------ | -------- | ---------------------------------------------------------------------------------------------------- | +| `surfaceId` | string | ✅ | ID of the surface to update. | +| `path` | string | ❌ | Path to a location within the data model (e.g., 'user'). If omitted, the update applies to the root. | +| `contents` | array | ✅ | An array of data entries as an adjacency list. Each entry has a `key` and a typed `value*` property. | + +### The `contents` Adjacency List + +The `contents` array is a list of key-value pairs. Each object in the array must have a `key` and exactly one `value*` property (`valueString`, `valueNumber`, `valueBoolean`, or `valueMap`). This structure is LLM-friendly and avoids issues with inferring types from a generic `value` field. + +### Examples + +**Initialize entire model:** + +If `path` is omitted, `contents` replaces the entire data model for the surface. + +```json +{ + "dataModelUpdate": { + "surfaceId": "main", + "contents": [ + { + "key": "user", + "valueMap": [ + { "key": "name", "valueString": "Alice" }, + { "key": "email", "valueString": "alice@example.com" } + ] + }, + { "key": "items", "valueMap": [] } + ] + } +} +``` + +**Update nested property:** + +If `path` is provided, `contents` updates the data at that location. + +```json +{ + "dataModelUpdate": { + "surfaceId": "main", + "path": "user", + "contents": [ + { "key": "email", "valueString": "alice@newdomain.com" } + ] + } +} +``` + +This will change `/user/email` without affecting `/user/name`. + +### Usage Notes + +- Data model is per-surface. +- Components automatically re-render when their bound data changes. +- Prefer granular updates to specific paths over replacing the entire model. +- Data model is a plain JSON object. +- Any data transformation (e.g., formatting a date) must be done by the server before sending the `dataModelUpdate` message. + +--- + +## deleteSurface + +Remove a surface and all its components and data. + +### Schema + +```typescript +{ + deleteSurface: { + surfaceId: string; // Required: Surface to delete + } +} +``` + +### Properties + +| Property | Type | Required | Description | +| ----------- | ------ | -------- | --------------------------- | +| `surfaceId` | string | ✅ | ID of the surface to delete | + +### Examples + +**Delete a surface:** + +```json +{ + "deleteSurface": { + "surfaceId": "modal" + } +} +``` + +**Delete multiple surfaces:** + +```json +{"deleteSurface": {"surfaceId": "sidebar"}} +{"deleteSurface": {"surfaceId": "content"}} +``` + +### Usage Notes + +- Removes all components associated with the surface +- Clears the data model for the surface +- Client should remove the surface from the UI +- Safe to delete non-existent surface (no-op) +- Use when closing modals, dialogs, or navigating away + +### Errors + +| Error | Cause | Solution | +| ------------------------------- | ----- | -------- | +| (None - deletes are idempotent) | | | + +--- + +## Message Ordering + +### Requirements + +1. `beginRendering` must come after the initial `surfaceUpdate` messages for that surface. +2. `surfaceUpdate` can come before or after `dataModelUpdate`. +3. Messages for different surfaces are independent. +4. Multiple messages can update the same surface incrementally. + +### Recommended Order + +```jsonl +{"surfaceUpdate": {"surfaceId": "main", "components": [...]}} +{"dataModelUpdate": {"surfaceId": "main", "contents": {...}}} +{"beginRendering": {"surfaceId": "main", "root": "root-id"}} +``` + +### Progressive Building + +```jsonl +{"surfaceUpdate": {"surfaceId": "main", "components": [...]}} // Header +{"surfaceUpdate": {"surfaceId": "main", "components": [...]}} // Body +{"beginRendering": {"surfaceId": "main", "root": "root-id"}} // Initial render +{"surfaceUpdate": {"surfaceId": "main", "components": [...]}} // Footer (after initial render) +{"dataModelUpdate": {"surfaceId": "main", "contents": {...}}} // Populate data +``` + +## Validation + +All messages should be validated against: + +- **[server_to_client.json](https://github.com/google/A2UI/blob/main/specification/0.8/json/server_to_client.json)**: Message envelope schema +- **[standard_catalog_definition.json](https://github.com/google/A2UI/blob/main/specification/0.8/json/standard_catalog_definition.json)**: Component schemas + +## Further Reading + +- **[Component Gallery](components.md)**: All available component types +- **[Data Binding Guide](../concepts/data-binding.md)**: How data binding works +- **[Agent Development Guide](../guides/agent-development.md)**: Generate valid messages diff --git a/docs/renderers.md b/docs/renderers.md new file mode 100644 index 00000000..f0bfd38b --- /dev/null +++ b/docs/renderers.md @@ -0,0 +1,87 @@ +# Renderers (Client Libraries) + +Renderers convert A2UI JSON messages into native UI components for different platforms. + +The [agents](agents.md) are responsible for generating the A2UI messages, +and the [transports](transports.md) are responsible for delivering the messages to the client. +The client renderer library must buffer and handle A2UI messages, implement the A2UI lifecycle, and render surfaces (widgets). + +You have a lot of flexibility, to bring custom comonents to a renderer, or build your own renderer to support your UI component framework. + +## Available Renderers + +| Renderer | Platform | Status | Links | +|----------|----------|--------|-------| +| **Lit (Web Components)** | Web | ✅ Stable | [Code](https://github.com/google/A2UI/tree/main/renderers/lit) | +| **Angular** | Web | ✅ Stable | [Code](https://github.com/google/A2UI/tree/main/renderers/angular) | +| **Flutter (GenUI SDK)** | Mobile/Desktop/Web | ✅ Stable | [Docs](https://docs.flutter.dev/ai/genui) · [Code](https://github.com/flutter/genui) | +| **React** | Web | 🚧 In Progress | Coming Q1 2026 | + +Check the [Roadmap](roadmap.md) for more. + +## How Renderers Work + +``` +A2UI JSON → Renderer → Native Components → Your App +``` + +1. **Receive** A2UI messages from the transport +2. **Parse** the JSON and validate against the schema +3. **Render** using platform-native components +4. **Style** according to your app's theme + +## Quick Start + +**Web Components (Lit):** + +```bash +npm install @a2ui/lit +``` + +TODO: Add a quickstart guide + +**Angular:** + +```bash +npm install @a2ui/angular +``` + +TODO: Add a quickstart guide + +**Flutter:** + +```bash +flutter pub add flutter_genui +``` + +TODO: Add a quickstart guide + +## Adding custom components to a renderer + +TODO: Add a guide + +## Theming or styling a renderer + +TODO: Add a guide + +## Building a Renderer + +Want to build a renderer for your platform? + +- See the [Roadmap](roadmap.md) for planned frameworks. +- Review existing renderers for patterns. + +### Key requirements: + +- Parse A2UI JSON messages, specifically the adjacency list format +- Map A2UI components to native widgets +- Handle data binding, lifecycle events +- Process a sequence of incremental A2UI messages to build and update the UI +- Support server initiated updates +- Support user actions + +### Next Steps + +- **[Client Setup Guide](guides/client-setup.md)**: Integration instructions +- **[Quickstart](quickstart.md)**: Try the Lit renderer +- **[Component Reference](reference/components.md)**: What components to support diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 00000000..95c89b69 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,229 @@ +# Roadmap + +This roadmap outlines the current state and future plans for the A2UI project. The project is under active development, and priorities may shift based on community feedback and emerging use cases. + +## Current Status + +### Protocol + +| Version | Status | Notes | +|---------|--------|-------| +| **v0.8** | ✅ Stable | Initial public release | +| **v0.9** | 🚧 In Progress | Draft specification improvements | + +Key features: + +- ✅ Streaming JSONL message format +- ✅ Four core message types (`surfaceUpdate`, `dataModelUpdate`, `beginRendering`, `deleteSurface`) +- ✅ Adjacency list component model +- ✅ JSON Pointer-based data binding +- ✅ Separation of structure and state + +### Renderers + +| Client libraries | Status | Platform | Notes | +|-----------------|--------|----------|-------| +| **Web Components (Lit)** | ✅ Stable | Web | Framework-agnostic, works anywhere | +| **Angular** | ✅ Stable | Web | Full Angular integration | +| **Flutter (GenUI SDK)** | ✅ Stable | Multi-platform | Works on mobile, web, desktop | +| **React** | 🚧 In Progress | Web | Coming Q1 2026 | +| **SwiftUI** | 📋 Planned | iOS/macOS | Planned for Q2 2026 | +| **Jetpack Compose** | 📋 Planned | Android | Planned for Q2 2026 | +| **Vue** | 💡 Proposed | Web | Community interest | +| **ShadCN (React)** | 💡 Proposed | Web | Community interest | + +### Transports + +| Transport | Status | Notes | +|-------------|--------|-------| +| **A2A Protocol** | ✅ Complete | Native A2A transport | +| **AG UI** | ✅ Complete | Day-zero compatibility | +| **REST API** | 📋 Planned | Bidirectional communication | +| **WebSockets** | 💡 Proposed | Bidirectional communication | +| **SSE (Server-Sent Events)** | 💡 Proposed | Web streaming | +| **MCP (Model Context Protocol)** | 💡 Proposed | Community interest | + +### Agent UI toolkits + +| Agent UI toolkit | Status | Notes | +|-------------|--------|-------| +| **CopilotKit** | ✅ Complete | Day-zero compatibility thanks to AG UI | +| **Open AI ChatKit** | 💡 Proposed | Community interest | +| **Vecel AI SDK UI** | 💡 Proposed | Community interest | + +### Agent frameworks + +| Integration | Status | Notes | +|-------------|--------|-------| +| **Any agent with A2A support** | ✅ Complete | Day-zero compatibility thanks to A2A protocol | +| **ADK** | 📋 Planned | Still designing developer ergonomics, see [samples](https://github.com/google/A2UI/tree/main/samples/agent/adk) | +| **Genkit** | 💡 Proposed | Community interest | +| **LangGraph** | 💡 Proposed | Community interest | +| **CrewAI** | 💡 Proposed | Community interest | +| **AG2** | 💡 Proposed | Community interest | +| **Claude Agent SDK** | 💡 Proposed | Community interest | +| **OpenAI Agent SDK** | 💡 Proposed | Community interest | +| **Microsoft Agent Framework** | 💡 Proposed | Community interest | +| **AWS Strands Agent SDK** | 💡 Proposed | Community interest | + +## Recent Milestones + +### Q2 2025 + +Many research projects across multiple Google teams, including integration into internal products and agents. + +### Q4 2025 + +- v0.8.0 spec released +- A2A extension (thanks Google A2A team! teased at [a2asummit.ai](https://a2asummit.ai)) +- Flutter renderer (thanks Flutter team!) +- Angular renderer (thanks Angular team!) +- Web components (Lit) renderer (thanks Opal team & friends!) +- AG UI / CopilotKit integration (thanks CopilotKit team!) +- Github public release (Apache 2.0) + +## Upcoming Milestones + +### Q1 2026 + +#### A2UI v0.9 + +- Release candidate for spec 0.9 +- Improve theming support for renderers (complete) +- Improve server side theming support for agents (minimal) +- Improve developer ergonomics + +#### React Renderer + +A native React renderer with hooks-based API and full TypeScript support. + +- React support for common widgets +- React support for custom components +- `useA2UI` hook for message handling +- React support for theming + +### Q2 2026 + +#### Native Mobile Renderers + +Native renderers for iOS and Android platforms. + +**SwiftUI Renderer (iOS/macOS):** + +- Native SwiftUI components +- iOS design language support +- macOS compatibility + +**Jetpack Compose Renderer (Android):** + +- Native Compose UI components +- Material Design 3 support +- Android platform integration + +#### Performance Optimizations + +- Renderer performance benchmarks +- Lazy loading for large component trees +- Virtual scrolling for lists +- Component memoization strategies + +### Q4 2026 + +#### Protocol v1.0 + +Finalize v1.0 of the protocol with: + +- Stability guarantees +- Migration path from v0.9 +- Comprehensive test suite +- Certification program for renderers + +## Long-Term Vision + +### Multi-Agent Coordination + +Enhanced support for multiple agents contributing to the same UI: + +- Recommended agent composition patterns +- Conflict resolution strategies +- Shared surface management + +### Accessibility Features + +First-class accessibility support: + +- ARIA attribute generation +- Screen reader optimization +- Keyboard navigation standards +- Contrast and color guidance + +### Advanced UI Patterns + +Support for more complex UI interactions: + +- Drag and drop +- Gestures and animations +- 3D rendering +- AR/VR interfaces (exploratory) + +### Ecosystem Growth + +- More framework integrations +- Third-party component libraries +- Agent marketplace integration +- Enterprise features and support + +## Community Requests + +Features requested by the community (in no particular order): + +- **More renderer integrations**: Map from your client library to A2UI +- **More agent frameworks**: Map from your agent framework to A2UI +- **More transports**: Map from your transport to A2UI +- **Community component library**: Share custom components with the community +- **Community samples**: Share custom samples with the community +- **Community evaluations**: Generative UI evaluation scenarios and labeled datasets +- **Developer Ergonomics**: If you can build a better A2UI experience, share it with the community + +## How to Influence the Roadmap + +We welcome community input on priorities: + +1. **Vote on Issues**: Give 👍 to GitHub issues you care about +2. **Propose Features**: Open a discussion on GitHub (search for existing discussions first) +3. **Submit PRs**: Build the features you need (search for existing PRs first) +4. **Join Discussions**: Share your use cases and requirements (search for existing discussions first) + +## Release Cycle + +- **Major versions** (1.0, 2.0): Annual or when significant breaking changes are needed +- **Minor versions** (1.1, 1.2): Quarterly with new features +- **Patch versions** (1.1.1, 1.1.2): As needed for bug fixes + +## Versioning Policy + +A2UI follows [Semantic Versioning](https://semver.org/): + +- **MAJOR**: Incompatible protocol changes +- **MINOR**: Backward-compatible functionality additions +- **PATCH**: Backward-compatible bug fixes + +## Get Involved + +Want to contribute to the roadmap? + +- **Propose features** in [GitHub Discussions](https://github.com/google/A2UI/discussions) +- **Build prototypes** and share them with the community +- **Join the conversation** on GitHub Issues + +## Stay Updated + +- Watch the [GitHub repository](https://github.com/google/A2UI) for updates +- Star the repo to show your support +- Follow releases to get notified of new versions + +--- + +**Last Updated:** December 2025 + +Have questions about the roadmap? [Start a discussion on GitHub](https://github.com/google/A2UI/discussions). diff --git a/docs/specification/v0.8-a2a-extension.md b/docs/specification/v0.8-a2a-extension.md new file mode 100644 index 00000000..c5aae221 --- /dev/null +++ b/docs/specification/v0.8-a2a-extension.md @@ -0,0 +1,15 @@ +# A2UI Extension for A2A Protocol (v0.8) + +!!! info "Living Document" + This specification is automatically included from `specification/0.8/docs/a2ui_extension_specification.md`. Any updates to the specification will automatically appear here. + +!!! note "Version Compatibility" + This extension specification applies to A2UI v0.8 and the A2A Protocol. For the base A2UI protocol, see [v0.8 Protocol Specification](v0.8-a2ui.md). + +**Related Documentation:** +- [A2UI Protocol v0.8](v0.8-a2ui.md) (Stable) +- [A2A Protocol Documentation](https://a2a-protocol.org) + +--- + +--8<-- "specification/0.8/docs/a2ui_extension_specification.md" diff --git a/docs/specification/v0.8-a2ui.md b/docs/specification/v0.8-a2ui.md new file mode 100644 index 00000000..3299dcea --- /dev/null +++ b/docs/specification/v0.8-a2ui.md @@ -0,0 +1,16 @@ +# A2UI Protocol v0.8 (Stable) + +!!! success "Stable Release" + Version 0.8 is the current stable release, recommended for production use. + +!!! info "Living Document" + This specification is automatically included from `specification/0.8/docs/a2ui_protocol.md`. Any updates to the specification will automatically appear here. + +**See also:** +- [v0.9 Protocol Specification](v0.9-a2ui.md) (Draft) +- [Evolution Guide: v0.8 → v0.9](v0.9-evolution-guide.md) +- [A2A Extension Specification](v0.8-a2a-extension.md) (for v0.8) + +--- + +--8<-- "specification/0.8/docs/a2ui_protocol.md" diff --git a/docs/specification/v0.9-a2ui.md b/docs/specification/v0.9-a2ui.md new file mode 100644 index 00000000..d8896797 --- /dev/null +++ b/docs/specification/v0.9-a2ui.md @@ -0,0 +1,15 @@ +# A2UI Protocol v0.9 (Draft) + +!!! info "Living Document" + This specification is automatically included from `specification/0.9/docs/a2ui_protocol.md`. Any updates to the specification will automatically appear here. + +!!! warning "Draft Status" + Version 0.9 is currently in draft status. For production use, consider [v0.8 (Stable)](v0.8-a2ui.md). + +**See also:** +- [v0.8 Protocol Specification](v0.8-a2ui.md) (Stable) +- [Evolution Guide: v0.8 → v0.9](v0.9-evolution-guide.md) + +--- + +--8<-- "specification/0.9/docs/a2ui_protocol.md" diff --git a/docs/specification/v0.9-evolution-guide.md b/docs/specification/v0.9-evolution-guide.md new file mode 100644 index 00000000..30319f4f --- /dev/null +++ b/docs/specification/v0.9-evolution-guide.md @@ -0,0 +1,12 @@ +# Evolution Guide: v0.8 → v0.9 + +!!! info "Living Document" + This guide is automatically included from `specification/0.9/docs/evolution_guide.md`. Any updates will automatically appear here. + +**Related Documentation:** +- [A2UI Protocol v0.8](v0.8-a2ui.md) (Stable - what you're migrating from) +- [A2UI Protocol v0.9](v0.9-a2ui.md) (Draft - what you're migrating to) + +--- + +--8<-- "specification/0.9/docs/evolution_guide.md" diff --git a/docs/transports.md b/docs/transports.md new file mode 100644 index 00000000..992de634 --- /dev/null +++ b/docs/transports.md @@ -0,0 +1,79 @@ +# Transports (Message Passing) + +Transports deliver A2UI messages from agents to clients. A2UI is transport-agnostic—use any method that can send JSON. + +The actual component rendering is done by the [renderer](renderers.md), +and the [agents](agents.md) are responsible for generating the A2UI messages. +Getting the messages from the agent to the client is the job of the transport. + +## How It Works + +``` +Agent → Transport → Client Renderer +``` + +A2UI defines a sequence of JSON messages. The transport layer is responsible for delivering this sequence from the agent to the client. A common transport mechanism is a stream using a format like JSON Lines (JSONL), where each line is a single A2UI message. + +## Available Transports + +| Transport | Status | Use Case | +|-----------|--------|----------| +| **A2A Protocol** | ✅ Stable | Multi-agent systems, enterprise meshes | +| **AG UI** | ✅ Stable | Full-stack React applications | +| **REST API** | 📋 Planned | Simple HTTP endpoints | +| **WebSockets** | 💡 Proposed | Real-time bidirectional | +| **SSE (Server-Sent Events)** | 💡 Proposed | Web streaming | + +## A2A Protocol + +The [Agent2Agent (A2A) protocol](https://a2a-protocol.org) provides secure, +standardized agent communication. An A2A extension provides easy integration with A2UI. + +**Benefits:** + +- Security and authentication built-in +- Bindings for many message formats, auth, and transport protocols +- Clean separation of concerns + +If you are using A2A, this should be nearly automatic. + +TODO: Add a detailed guide. + +**See:** [A2A Extension Specification](specification/v0.8-a2a-extension.md) + +## AG UI + +[AG UI](https://ag-ui.com/) translates from A2UI messages to AG UI messages, and handles transport and state sync automatically. + +If you are using AG UI, this should be automatic. + +TODO: Add a detailed guide. + +## Custom Transports + +You can use any transport that sends JSON: + +**HTTP/REST:** + +```javascript +// TODO: Add an example +``` + +**WebSockets:** + +```javascript +// TODO: Add an example +``` + +**Server-Sent Events:** + +```javascript +// TODO: Add an example +``` + +``` + +## Next Steps + +- **[A2A Protocol Docs](https://a2a-protocol.org)**: Learn about A2A +- **[A2A Extension Spec](specification/v0.8-a2a-extension.md)**: A2UI + A2A details \ No newline at end of file diff --git a/mkdocs.yaml b/mkdocs.yaml index 8ed23c52..06b29435 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -13,11 +13,10 @@ # limitations under the License. site_name: A2UI -site_url: https://google.github.io/A2UI/ -site_description: Official Sign-up for A2UI, a JSONL-based, streaming UI protocol designed to be easily generated by Large Language Models (LLMs). +site_url: https://a2ui.org/ +site_description: A2UI, a streaming protocol for Agent-Driven User Interfaces site_author: Google site_dir: site -# edit_uri: edit/main/docs/ extra: analytics: @@ -34,10 +33,43 @@ extra: # Navigation nav: - Home: index.md + - Introduction & FAQ: + - What is A2UI?: introduction/what-is-a2ui.md + - Who is it For?: introduction/who-is-it-for.md + - How Can I Use It?: introduction/how-to-use.md + - Where is it Used?: introduction/where-is-it-used.md + - Agent UI Ecosystem: introduction/agent-ui-ecosystem.md + - Quickstart: quickstart.md + - A2UI Composer ⭐: composer.md + - Developer Guides: + - Client Setup: guides/client-setup.md + - Agent Development: guides/agent-development.md + - Custom Components: guides/custom-components.md + - Theming & Styling: guides/theming.md + - Core Concepts: + - Overview: concepts/overview.md + - Data Flow: concepts/data-flow.md + - Components & Structure: concepts/components.md + - Data Binding: concepts/data-binding.md + - Specifications: + - v0.8 (Stable): + - A2UI Specification: specification/v0.8-a2ui.md + - A2A Extension: specification/v0.8-a2a-extension.md + - v0.9 (Draft): + - A2UI Specification: specification/v0.9-a2ui.md + - Evolution Guide: specification/v0.9-evolution-guide.md + - Renderers (Clients): renderers.md + - Transports (Message Passing): transports.md + - Agents (Server-side): agents.md + - Community: community.md + - Roadmap: roadmap.md + - Reference: + - Component Reference: reference/components.md + - Message Reference: reference/messages.md # Repository -# repo_name: A2UI -# repo_url: https://github.com/google/A2UI +repo_name: google/A2UI +repo_url: https://github.com/google/A2UI # Copyright copyright: Copyright Google 2025  |  Terms  |  Privacy  |  Manage cookies @@ -47,7 +79,6 @@ extra_css: - stylesheets/custom.css - # Configuration theme: name: material diff --git a/requirements-docs.txt b/requirements-docs.txt index b2dc7a9c..573152f2 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,6 +1,9 @@ -mkdocs-material==9.6.22 -mkdocs-redirects==1.2.2 -mkdocs-macros-plugin==1.4.0 -mkdocs-llmstxt==0.4.0 -mkdocs-include-markdown-plugin==7.2.0 -mkdocs-mermaid2-plugin==1.1.0 +mkdocs-material +mkdocs-redirects +mkdocs-macros-plugin +mkdocs-llmstxt +mkdocs-include-markdown-plugin +mkdocs-mermaid2-plugin +sphinx +furo +myst-parser diff --git a/samples/agent/adk/contact_lookup/a2ui_examples.py b/samples/agent/adk/contact_lookup/a2ui_examples.py index 0e59b4a5..dcf74210 100644 --- a/samples/agent/adk/contact_lookup/a2ui_examples.py +++ b/samples/agent/adk/contact_lookup/a2ui_examples.py @@ -160,4 +160,3 @@ ] ---END FOLLOW_SUCCESS_EXAMPLE--- """ - diff --git a/specification/0.8/docs/a2ui_protocol.md b/specification/0.8/docs/a2ui_protocol.md index fedb4ad2..693a1bc2 100644 --- a/specification/0.8/docs/a2ui_protocol.md +++ b/specification/0.8/docs/a2ui_protocol.md @@ -151,12 +151,9 @@ The following is a complete, minimal example of a JSONL stream that renders a us {"surfaceUpdate": {"components": [{"id": "card_content", "component": {"Column": {"children": {"explicitList": ["header_row", "bio_text"]}}}}]}} {"surfaceUpdate": {"components": [{"id": "header_row", "component": {"Row": {"alignment": "center", "children": {"explicitList": ["avatar", "name_column"]}}}}]}} {"surfaceUpdate": {"components": [{"id": "avatar", "component": {"Image": {"url": {"literalString": "https://www.example.com/profile.jpg"}}}}]}} -{"surfaceUpdate": {"components": [{"id": "avatar", "component": {"Image": {"url": {"literalString": "https://www.example.com/profile.jpg"}}}}]}} {"surfaceUpdate": {"components": [{"id": "name_column", "component": {"Column": {"alignment": "start", "children": {"explicitList": ["name_text", "handle_text"]}}}}]}} {"surfaceUpdate": {"components": [{"id": "name_text", "component": {"Text": {"usageHint": "h3", "text": {"literalString": "A2A Fan"}}}}]}} {"surfaceUpdate": {"components": [{"id": "handle_text", "component": {"Text": {"text": {"literalString": "@a2a_fan"}}}}]}} -{"surfaceUpdate": {"components": [{"id": "name_text", "component": {"Text": {"usageHint": "h3", "text": {"literalString": "A2A Fan"}}}}]}} -{"surfaceUpdate": {"components": [{"id": "handle_text", "component": {"Text": {"text": {"literalString": "@a2a_fan"}}}}]}} {"surfaceUpdate": {"components": [{"id": "bio_text", "component": {"Text": {"text": {"literalString": "Building beautiful apps from a single codebase."}}}}]}} {"dataModelUpdate": {"contents": {}}} {"beginRendering": {"root": "root"}}