A2UI Angular Renderer Development Skill
Tech Stack: Angular 21+, A2UI Protocol v0.8+, TailwindCSS 4.x, daisyUI 5.5.5
What is A2UI?
A2UI (Agent-to-User Interface) is a declarative protocol by Google that lets AI agents describe rich, interactive UIs as structured JSON data instead of generating executable code. The agent sends a JSON blueprint; the client app renders it using its own native components.
Key principle: UI-as-data, not UI-as-code. Agents never generate HTML/JS — they describe intent via a flat component adjacency list. The client validates against an approved component catalog and renders with native framework components.
Iron Law
A2UI PAYLOADS ARE UNTRUSTED. VALIDATE COMPONENT TYPES AGAINST THE CATALOG ALLOWLIST BEFORE RENDERING. NEVER EXECUTE AGENT-PROVIDED CODE.
Every component from an agent must be validated against the client's approved catalog. Rendering any component type the agent sends, or executing agent-provided scripts, exposes the application to XSS, code injection, and data theft. The catalog allowlist is the security boundary.
Conventions & Structure
For Angular coding conventions, read the angular-spa skill's reference/angular-conventions.md
For A2UI-specific patterns, read reference/a2ui-protocol.md
Documentation Sources
| Source |
URL / Tool |
Purpose |
| A2UI Spec |
https://a2ui.org/ |
Protocol specification, component format |
| A2UI GitHub |
https://github.com/google/A2UI |
Reference implementations, samples |
| A2A Extension |
https://a2ui.org/a2a-extension/a2ui/v0.8 |
A2A protocol integration (Python ADK) |
| A2UI Composer |
https://a2ui.org/composer/ |
Visual widget builder — prototype before wiring |
| @a2ui/angular |
npm install @a2ui/angular |
Official Angular renderer SDK |
| Angular v21 |
angular-cli MCP |
Workspace-aware help, schematics |
| daisyUI v5 |
https://daisyui.com/llms.txt |
Component reference for rendering |
| TailwindCSS |
Context7 MCP |
Utility classes for layout |
Before Writing Any A2UI Code
- Read
reference/a2ui-protocol.md — protocol structure, JSON format, adjacency list, action model
- Read
reference/a2ui-renderer-patterns.md — Angular renderer architecture, catalog service, recursive rendering
- Read
reference/a2ui-security.md — allowlist enforcement, injection prevention, input sanitization
- Read
reference/a2ui-component-catalog.md — standard component types, property schemas, action definitions
- Verify Angular APIs — Use
angular-cli MCP or Context7 MCP before using any Angular API
Process
- Understand Requirements — Clarify which A2UI component types to support, agent transport (REST/WebSocket/SSE), and action handling needs
- Define Component Catalog — Create the allowlist of approved A2UI component types with their property schemas
- Build Renderer — Create the recursive
A2UIRendererComponent that maps A2UI types to Angular/daisyUI components
- Implement Agent Service — Create the service that communicates with the AI agent and receives A2UI payloads
- Add Action Handling — Wire user interactions (clicks, form submits) back to the agent as A2UI actions
- Enable Streaming — Support progressive rendering via SSE or WebSocket for real-time UI updates
- Write Tests — Unit tests for catalog validation, renderer component, and action dispatch
- Verify Build — Run
ng build to ensure no compilation errors
Reference Files
Detailed patterns are in reference/:
A2UI Protocol
a2ui-protocol.md — Protocol specification, JSON format, adjacency list structure, message types, userAction
a2ui-protocol-advanced.md — Action model, streaming (JSONL/SSE/WebSocket/REST/A2A), A2A integration, versioning
a2ui-security.md — Allowlist enforcement, injection prevention, untrusted payload handling
a2ui-component-catalog.md — Layout (Row, Column) + Display (Text, Image, Icon, Divider) + Interactive (Button, TextField, Checkbox, DateTimeInput) component schemas
a2ui-component-containers.md — Container types (Card, Modal, Tabs, List), extended catalog (ChoicePicker, Slider, AudioPlayer, Video), how to add new types
a2ui-functions.md — Full functions reference: validation (required, regex, email), formatting (formatCurrency, formatDate, pluralize), logical (and, or, not), navigation (openUrl) — A2UIFunctionService implementation
Angular Implementation
a2ui-renderer-patterns.md — Architecture overview, file structure, TypeScript models, catalog service, sanitizer service, renderer key patterns
a2ui-renderer-template.md — Full A2UIRendererComponent implementation (all 12 @case branches, computed signals, action dispatch)
a2ui-chat-template.md — Chat page component, streaming variant (SSE + JSONL), wire format reference with JSON examples
a2ui-renderer-services.md — Official @a2ui/angular SDK setup (A2uiRendererService, SurfaceComponent, A2UI_RENDERER_CONFIG), A2UIAgentService (REST + SSE), unit test template
a2ui-production-architecture.md — Production stack, Domain DSL, Custom Catalog patterns (BoundProperty, BasicCatalogBase, FunctionImplementation), Charts/Dashboard, Testing patterns, Observability metrics
a2ui-client-integration.md — agUiResource service pattern, registerHandlers, widget template, demo-only vs production action handler warning, rate limits (surfaces/session, actions/sec, payload size)
Anti-Patterns — What to Avoid
// ❌ FORBIDDEN: Rendering arbitrary component types from agent
@switch (comp.type) {
@default {
<div [innerHTML]="comp.properties['html']"></div> // XSS vector!
}
}
// ✅ REQUIRED: Validate against catalog, skip unknown types
@switch (comp.type) {
@default {
<!-- Unknown A2UI type silently skipped — not in catalog -->
}
}
// ❌ FORBIDDEN: Executing agent-provided code
eval(comp.properties['script']);
new Function(comp.properties['handler'])();
// ✅ REQUIRED: Declarative action dispatch (v0.8 format)
onAction(comp: A2UIComponent): void {
const action = comp['action'] as { name: string; context?: Array<{ key: string; value: unknown }> };
if (!action?.name) return;
this.actionTriggered.emit({ name: action.name, context: action.context ?? [] });
}
// ❌ FORBIDDEN: Deeply nested JSON tree from agent
{ "children": [{ "children": [{ "children": [...] }] }] }
// ✅ REQUIRED: surfaceUpdate with components as array, root field (A2UI v0.8 protocol)
{
"surfaceUpdate": {
"surfaceId": "main",
"components": [
{ "id": "root", "component": { "type": "Column", "children": {"explicitList": ["btn-1"]} } },
{ "id": "btn-1", "component": { "type": "Button", "primary": true, "action": {"name": "submit"} } }
],
"root": "root"
}
}
// ✅ REQUIRED: userAction — 5th message type, client → agent
{
"userAction": {
"name": "book_hotel",
"surfaceId": "main",
"sourceComponentId": "btn-book",
"timestamp": "2026-03-10T12:00:00Z",
"context": { "hotelId": "H-456" }
}
}
Error Handling
- If agent returns an unknown component type → skip it silently (log warning), render remaining components
- If agent payload is malformed JSON → show error state to user, log full error
- If agent connection drops mid-stream → render what was received so far, show reconnect option
- If action dispatch fails → show error toast, do NOT silently swallow
Common Commands
# Generate A2UI feature module
mkdir -p src/app/features/a2ui-chat/{components,services,models}
# Run tests
npx ng test --watch=false
# Build
npx ng build
1---2name: a2ui-angular3description: A2UI (Agent-to-User Interface) renderer development for Angular 21.x. Use when building A2UI component renderers, agent-driven UIs, A2UI catalogs, action handlers, or streaming A2UI payloads. Covers protocol implementation, security validation, component mapping, and agent integration.4---56# A2UI Angular Renderer Development Skill78> **Tech Stack**: Angular 21+, A2UI Protocol v0.8+, TailwindCSS 4.x, daisyUI 5.5.5910## What is A2UI?1112A2UI (Agent-to-User Interface) is a **declarative protocol by Google** that lets AI agents describe rich, interactive UIs as structured JSON data instead of generating executable code. The agent sends a JSON blueprint; the client app renders it using its own native components.1314**Key principle:** UI-as-data, not UI-as-code. Agents never generate HTML/JS — they describe intent via a flat component adjacency list. The client validates against an approved component catalog and renders with native framework components.1516## Iron Law1718**A2UI PAYLOADS ARE UNTRUSTED. VALIDATE COMPONENT TYPES AGAINST THE CATALOG ALLOWLIST BEFORE RENDERING. NEVER EXECUTE AGENT-PROVIDED CODE.**1920Every component from an agent must be validated against the client's approved catalog. Rendering any component type the agent sends, or executing agent-provided scripts, exposes the application to XSS, code injection, and data theft. The catalog allowlist is the security boundary.2122## Conventions & Structure2324> For Angular coding conventions, read the `angular-spa` skill's `reference/angular-conventions.md`25> For A2UI-specific patterns, read `reference/a2ui-protocol.md`2627## Documentation Sources2829| Source | URL / Tool | Purpose |30|--------|-----------|---------|31| A2UI Spec | `https://a2ui.org/` | Protocol specification, component format |32| A2UI GitHub | `https://github.com/google/A2UI` | Reference implementations, samples |33| A2A Extension | `https://a2ui.org/a2a-extension/a2ui/v0.8` | A2A protocol integration (Python ADK) |34| A2UI Composer | `https://a2ui.org/composer/` | Visual widget builder — prototype before wiring |35| @a2ui/angular | `npm install @a2ui/angular` | Official Angular renderer SDK |36| Angular v21 | `angular-cli` MCP | Workspace-aware help, schematics |37| daisyUI v5 | `https://daisyui.com/llms.txt` | Component reference for rendering |38| TailwindCSS | `Context7` MCP | Utility classes for layout |3940## Before Writing Any A2UI Code41421. **Read `reference/a2ui-protocol.md`** — protocol structure, JSON format, adjacency list, action model432. **Read `reference/a2ui-renderer-patterns.md`** — Angular renderer architecture, catalog service, recursive rendering443. **Read `reference/a2ui-security.md`** — allowlist enforcement, injection prevention, input sanitization454. **Read `reference/a2ui-component-catalog.md`** — standard component types, property schemas, action definitions465. **Verify Angular APIs** — Use `angular-cli` MCP or Context7 MCP before using any Angular API4748## Process49501. **Understand Requirements** — Clarify which A2UI component types to support, agent transport (REST/WebSocket/SSE), and action handling needs512. **Define Component Catalog** — Create the allowlist of approved A2UI component types with their property schemas523. **Build Renderer** — Create the recursive `A2UIRendererComponent` that maps A2UI types to Angular/daisyUI components534. **Implement Agent Service** — Create the service that communicates with the AI agent and receives A2UI payloads545. **Add Action Handling** — Wire user interactions (clicks, form submits) back to the agent as A2UI actions556. **Enable Streaming** — Support progressive rendering via SSE or WebSocket for real-time UI updates567. **Write Tests** — Unit tests for catalog validation, renderer component, and action dispatch578. **Verify Build** — Run `ng build` to ensure no compilation errors5859## Reference Files6061Detailed patterns are in `reference/`:6263### A2UI Protocol64- `a2ui-protocol.md` — Protocol specification, JSON format, adjacency list structure, message types, userAction65- `a2ui-protocol-advanced.md` — Action model, streaming (JSONL/SSE/WebSocket/REST/A2A), A2A integration, versioning66- `a2ui-security.md` — Allowlist enforcement, injection prevention, untrusted payload handling67- `a2ui-component-catalog.md` — Layout (Row, Column) + Display (Text, Image, Icon, Divider) + Interactive (Button, TextField, Checkbox, DateTimeInput) component schemas68- `a2ui-component-containers.md` — Container types (Card, Modal, Tabs, List), extended catalog (ChoicePicker, Slider, AudioPlayer, Video), how to add new types69- `a2ui-functions.md` — Full functions reference: validation (required, regex, email), formatting (formatCurrency, formatDate, pluralize), logical (and, or, not), navigation (openUrl) — `A2UIFunctionService` implementation7071### Angular Implementation72- `a2ui-renderer-patterns.md` — Architecture overview, file structure, TypeScript models, catalog service, sanitizer service, renderer key patterns73- `a2ui-renderer-template.md` — Full A2UIRendererComponent implementation (all 12 @case branches, computed signals, action dispatch)74- `a2ui-chat-template.md` — Chat page component, streaming variant (SSE + JSONL), wire format reference with JSON examples75- `a2ui-renderer-services.md` — Official `@a2ui/angular` SDK setup (A2uiRendererService, SurfaceComponent, A2UI_RENDERER_CONFIG), A2UIAgentService (REST + SSE), unit test template76- `a2ui-production-architecture.md` — Production stack, Domain DSL, Custom Catalog patterns (BoundProperty, BasicCatalogBase, FunctionImplementation), Charts/Dashboard, Testing patterns, Observability metrics77- `a2ui-client-integration.md` — `agUiResource` service pattern, `registerHandlers`, widget template, **demo-only vs production action handler warning**, rate limits (surfaces/session, actions/sec, payload size)7879## Anti-Patterns — What to Avoid8081```typescript82// ❌ FORBIDDEN: Rendering arbitrary component types from agent83@switch (comp.type) {84 @default {85 <div [innerHTML]="comp.properties['html']"></div> // XSS vector!86 }87}8889// ✅ REQUIRED: Validate against catalog, skip unknown types90@switch (comp.type) {91 @default {92 <!-- Unknown A2UI type silently skipped — not in catalog -->93 }94}95```9697```typescript98// ❌ FORBIDDEN: Executing agent-provided code99eval(comp.properties['script']);100new Function(comp.properties['handler'])();101102// ✅ REQUIRED: Declarative action dispatch (v0.8 format)103onAction(comp: A2UIComponent): void {104 const action = comp['action'] as { name: string; context?: Array<{ key: string; value: unknown }> };105 if (!action?.name) return;106 this.actionTriggered.emit({ name: action.name, context: action.context ?? [] });107}108```109110```typescript111// ❌ FORBIDDEN: Deeply nested JSON tree from agent112{ "children": [{ "children": [{ "children": [...] }] }] }113114// ✅ REQUIRED: surfaceUpdate with components as array, root field (A2UI v0.8 protocol)115{116 "surfaceUpdate": {117 "surfaceId": "main",118 "components": [119 { "id": "root", "component": { "type": "Column", "children": {"explicitList": ["btn-1"]} } },120 { "id": "btn-1", "component": { "type": "Button", "primary": true, "action": {"name": "submit"} } }121 ],122 "root": "root"123 }124}125126// ✅ REQUIRED: userAction — 5th message type, client → agent127{128 "userAction": {129 "name": "book_hotel",130 "surfaceId": "main",131 "sourceComponentId": "btn-book",132 "timestamp": "2026-03-10T12:00:00Z",133 "context": { "hotelId": "H-456" }134 }135}136```137138## Error Handling139140- If agent returns an unknown component type → skip it silently (log warning), render remaining components141- If agent payload is malformed JSON → show error state to user, log full error142- If agent connection drops mid-stream → render what was received so far, show reconnect option143- If action dispatch fails → show error toast, do NOT silently swallow144145## Common Commands146147```bash148# Generate A2UI feature module149mkdir -p src/app/features/a2ui-chat/{components,services,models}150151# Run tests152npx ng test --watch=false153154# Build155npx ng build156```