Integrate A2UI with Your Frontend

Connect any UI to PraisonAI agents via the A2UI tool output contract

Use this guide when building your own chat app, dashboard, or canvas — not only PraisonAIUI.

python
from praisonaiagents import Agent
from praisonaiagents.tools.a2ui_tools import send_a2ui_messages

agent = Agent(
    name="A2UI Builder",
    instructions="When the user asks for UI, call send_a2ui_messages with valid A2UI JSON.",
    tools=[send_a2ui_messages],
)

agent.start("Show a three-field signup form")

The user chats in your app; the agent emits A2UI payloads your frontend renders.

Diagram

🤖 Agent

📤 send_a2ui_messages

🖥️ Your Frontend

A2UI Renderer

How It Works

Diagram
Integrate A2UI with Your FrontendAgentUserIntegrate A2UI with Your FrontendAgentUserRequestProcess requestResult Agent–>>User: Response

Integrate A2UI with Your Frontend

PraisonAI core emits A2UI via the agent tool send_a2ui_messages. Your frontend detects the payload and renders with Google A2UI renderers or a custom mapper.

Prerequisites

bash
pip install praisonaiagents[a2ui]

Optional React renderer:

bash
npm install @a2ui/react @a2ui/web_core

Quick Start

  1. Install and add the A2UI tool
    bash
    pip install praisonaiagents[a2ui]
    python
    from praisonaiagents import Agent
    from praisonaiagents.tools.a2ui_tools import send_a2ui_messages
    
    agent = Agent(
        name="assistant",
        instructions="When the user asks for UI, call send_a2ui_messages with valid A2UI v0.9 JSON.",
        tools=[send_a2ui_messages],
    )
  2. Detect A2UI in your frontend
    python
    def handle_tool_result(result):
        if isinstance(result, dict) and result.get("mime_type") == "application/json+a2ui":
            return result["messages"]
        return None

Four-step contract

1. Agent with the A2UI tool

python
from praisonaiagents import Agent
from praisonaiagents.tools.a2ui_tools import send_a2ui_messages

agent = Agent(
    name="assistant",
    instructions=(
        "When the user asks for UI, call send_a2ui_messages with valid A2UI v0.9 JSON."
    ),
    tools=[send_a2ui_messages],
)

2. Tool output shape (integrator contract)

send_a2ui_messages returns:

python
{
    "mime_type": "application/json+a2ui",
    "messages": [  # A2UI v0.9 message list
        {"createSurface": {"surfaceId": "main", "catalogId": "basic"}, ...}
    ],
    "a2ui_part": ...  # A2A-wrapped payload
}

Type hint in core (zero runtime cost):

python
from praisonaiagents.ui.a2ui import A2UI_MIME_TYPE, A2UIToolResultProtocol
from praisonaiagents.ui.protocols import A2UI_MIME_TYPE  # same constant

3. Detect in your UI (minimum)

python
def handle_tool_result(result):
    if isinstance(result, dict) and result.get("mime_type") == "application/json+a2ui":
        messages = result["messages"]
        # → pass to @a2ui/react or your renderer
        return messages
    return None

For richer normalisation (surface id, version fields), use PraisonAIUI a2ui_utils.py as a reference — copy or vendor that file in your UI layer.

4. Render and handle user actions

React (Google renderer):

tsx
import { A2uiSurface, basicCatalog } from '@a2ui/react/v0_9'
// Process messages with MessageProcessor, render A2uiSurface

Wire button clicks back to your agent (POST user action → new agent turn).

Transport options

TransportEntry pointA2UI delivery
Tool result JSONYour WebSocket/SSEParse mime_type on TOOL_CALL_COMPLETED
AG-UIAGUI(agent).get_router() → POST /aguiTOOL_CALL_RESULT (JSON string) + CUSTOM event name: "a2ui"
A2AA2A(agent) → POST /a2acreate_a2ui_part() / is_a2ui_part()
PraisonAIUIaiui run app.pyReference impl — surfaces, canvas, chat preview

AG-UI CUSTOM event

When a tool returns A2UI, the AG-UI bridge emits an additive event:

json
{
  "type": "CUSTOM",
  "name": "a2ui",
  "value": {
    "mime_type": "application/json+a2ui",
    "messages": [...],
    "surface_id": "main"
  }
}

The existing TOOL_CALL_RESULT with stringified JSON is unchanged for backward compatibility.

Tiers (pick the simplest)

See Generative UI for the full tier list:

TierUse when
0Markdown streaming only
1Your frontend owns component mapping (output_pydantic)
2CopilotKit / AG-UI client
3Cross-platform A2UI catalog (this guide)

Reference implementation

PraisonAIUI example 29 — A2UI canvas demonstrates chat + live surface preview.

Best Practices

Choose the right UI tier

Start at tier 0 (Markdown) and move up only when you need structured or generative surfaces.

Own the component mapping at tier 1

Map output_pydantic types to your design system — do not hard-code PraisonAI defaults in production UIs.

Test with the reference example

Use the PraisonAIUI example 29 canvas to validate message flow before custom frontends.

Keep A2UI payloads small

Stream incremental surface updates instead of resending full component trees each turn.

Related