A2UI — Agent-to-User Interface
A2UI is a structured format for agents to request input from humans. Instead of plain text prompts, agents describe what they need as a JSON spec — fields, actions, validation rules, sensitivity flags — and the rendering surface decides how to present it. A2UI is transport-agnostic. The same spec renders as a React form in the dashboard, Slack buttons, an email summary, or raw JSON in a webhook payload.Why A2UI?
When an agent needs human input, the naive approach is to print a text message and hope the human knows what to do. That breaks down in production:- Approvals need structured responses. “Do you approve?” needs a yes/no button, not a free-text reply.
- Forms need validation. An agent asking for credentials needs a password field, not a plaintext input.
- Different channels have different capabilities. Slack can render buttons. Email can’t. The dashboard can render anything.
- Sensitive data needs protection. Credentials should never appear in Slack notifications or logs.
The Spec
An A2UI payload is a JSON object describing a set of components. Each component has a type and properties that tell the renderer what to display.Field Types
| Type | Renders As | Slack Support |
|---|---|---|
action | Buttons (approve/deny, custom actions) | Yes — buttons |
text | Text input | Yes — plain text input in modal |
select | Dropdown | Yes — static select (≤5 options) |
number | Numeric input | Partial — text input with hint |
password | Masked input (sensitive) | No — always links to dashboard |
textarea | Multi-line text | Partial — plain text input |
checkbox | Checkbox | No — links to dashboard |
date | Date picker | No — links to dashboard |
Sensitivity
Fields can be markedsensitive: true. Sensitive fields are:
- Never included in Slack messages, emails, or webhook payloads
- Only rendered in the dashboard or terminal (full A2UI clients)
- When a form contains sensitive fields, non-dashboard channels show a summary of the non-sensitive fields and a link: “This request contains sensitive fields — [complete it in the dashboard].”
Examples
Policy Approval (Simple)
When a policy guard blocks a tool invocation:Structured Input (Credentials)
When an agent needs login credentials:Multi-Field Form
When an agent needs structured data:How A2UI Payloads Flow
- Agent hits a blocking point — policy approval, tool confirmation, or explicit
request_user_inputcall - A2UI builder constructs the spec —
a2ui_approval_builder.tsora2ui_form_builder.tsin the mesh - Spec is embedded in the A2A task — as a
DataPartwith MIME typeapplication/json+a2ui - Message enters
input-required— the A2UI spec is persisted intask_data - Notification pipeline fires — renderers translate the spec for each configured channel
- Human responds — from dashboard, Slack, or webhook callback
- Resolution flows back — field values mapped back to the A2UI field IDs, forwarded to the mesh
- Agent continues — receives the response and resumes execution
Rendering Surfaces
| Surface | A2UI Support | Interactive | Sensitive Fields |
|---|---|---|---|
| Dashboard | Full | Yes — forms, buttons, inputs | Yes |
| Terminal (CLI) | Full | Yes — Ink components | Yes |
| Slack | Partial | Yes — buttons, selects, modals | No — links to dashboard |
| Summary only | No — links to dashboard | No | |
| Webhook | Full spec as JSON | Yes — receiving system interprets | Depends on receiver |
| Angular app | Full | Yes — @a2ui/angular | Yes |
Relationship to A2A
A2UI payloads travel inside A2A messages asDataPart objects:
application/json+a2ui MIME type tells the receiving client that this part contains a renderable A2UI spec rather than arbitrary data.
When the A2A task state is input-required and the task contains an A2UI DataPart, clients know they need to render a form and send the response back.
Relationship to ADK Tool Confirmation
ADK’srequire_confirmation and request_confirmation() produce tool confirmation events. Svantic maps these to A2UI specs:
| ADK Concept | A2UI Mapping |
|---|---|
Boolean confirmation (require_confirmation: true) | A2UI form with single action field (approve/deny) |
Advanced confirmation (request_confirmation(hint, payload)) | A2UI form with fields derived from the payload schema |
FunctionResponse with confirmed: true/false | Resolution with decision: approve/deny |
Further Reading
- Notifications & Approvals — the full notification pipeline
- Push Notifications — A2A-level async task updates
- Streaming & Events — how A2UI events flow in SSE streams
- Guardrails & Safety — policies that produce A2UI approval requests
- A2UI specification — the full A2UI component reference
