2c3cfdbedc
- Fix a2ui-format.md schema to match renderer: rename 'options' → 'filters' in
filters block, replace 'active: boolean' with 'value: string' in filter options,
update form select options from string[] to {label, value}[] objects (Critical #1)
- Fix 3 failing tests in test_researcher_agent.sh to use @mention paths without .md
extension (Important #2)
- Complete pop-out feature in VisualBlock.handlePopOut() by posting render message
to popup window after 500ms initialization delay (Important #3)
- Update test_context_files.sh to match new a2ui-format.md schema (filters array
key check, value field check)
150 lines
4.3 KiB
Markdown
150 lines
4.3 KiB
Markdown
# A2UI Block Format
|
|
|
|
A2UI (AI-to-UI) lets you generate interactive UI controls directly in the chat. The
|
|
frontend parses `a2ui` code blocks and renders them as Tabler components — filter
|
|
toggles, sortable tables, card grids, and forms — without any page reload.
|
|
|
|
## How to Generate
|
|
|
|
Wrap a JSON object in a fenced code block with the language tag `a2ui`:
|
|
|
|
````
|
|
```a2ui
|
|
{ "type": "...", ... }
|
|
```
|
|
````
|
|
|
|
The JSON must be a single object with a `type` field. The frontend selects the
|
|
renderer based on `type` and passes the remaining fields as props.
|
|
|
|
---
|
|
|
|
## Block Types
|
|
|
|
### filters
|
|
|
|
Renders a row of toggle chips. Use for quick category or attribute filtering.
|
|
|
|
```a2ui
|
|
{
|
|
"type": "filters",
|
|
"filters": [
|
|
{ "label": "Toyota", "value": "toyota" },
|
|
{ "label": "Honda", "value": "honda" },
|
|
{ "label": "Hyundai", "value": "hyundai" },
|
|
{ "label": "Under $5K", "value": "under_5k" }
|
|
]
|
|
}
|
|
```
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `filters` | array | List of filter chips |
|
|
| `filters[].label` | string | Display text for the chip |
|
|
| `filters[].value` | string | Machine-readable identifier for the chip |
|
|
|
|
---
|
|
|
|
### table
|
|
|
|
Renders a sortable data table. Use for structured comparisons across multiple items.
|
|
|
|
```a2ui
|
|
{
|
|
"type": "table",
|
|
"headers": ["Make/Model", "Year", "Price", "MPG", "Mileage"],
|
|
"rows": [
|
|
["Toyota Prius", "2019", "$8,500", "52 mpg", "61,000 mi"],
|
|
["Honda Insight", "2018", "$9,200", "49 mpg", "55,000 mi"],
|
|
["Hyundai Ioniq", "2019", "$8,900", "55 mpg", "48,000 mi"],
|
|
["Toyota Camry Hybrid", "2017", "$7,800", "46 mpg", "72,000 mi"],
|
|
["Ford Fusion Hybrid", "2018", "$7,200", "42 mpg", "68,000 mi"]
|
|
]
|
|
}
|
|
```
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `headers` | string[] | Column header labels |
|
|
| `rows` | string[][] | Data rows; each row must match header count |
|
|
|
|
---
|
|
|
|
### cards
|
|
|
|
Renders a card grid. Use for item listings where each result deserves its own tile.
|
|
|
|
```a2ui
|
|
{
|
|
"type": "cards",
|
|
"items": [
|
|
{
|
|
"title": "2019 Toyota Prius LE",
|
|
"description": "61,000 miles · Hybrid · Clean title · Seattle, WA",
|
|
"price": "$8,500",
|
|
"url": "https://www.cargurus.com/Cars/listings/prius-example"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `items` | array | List of card objects |
|
|
| `items[].title` | string | Card heading |
|
|
| `items[].description` | string | Supporting detail text |
|
|
| `items[].price` | string | Price label (formatted string, e.g. `"$8,500"`) |
|
|
| `items[].url` | string | Link destination for the card action |
|
|
|
|
---
|
|
|
|
### form
|
|
|
|
Renders a data-collection form. Use when you need user input to refine a search or
|
|
configure a follow-up action.
|
|
|
|
```a2ui
|
|
{
|
|
"type": "form",
|
|
"fields": [
|
|
{ "name": "max_price", "type": "number", "label": "Max Price ($)", "value": 10000 },
|
|
{ "name": "radius", "type": "number", "label": "Search Radius (miles)", "value": 25 },
|
|
{
|
|
"name": "fuel_type",
|
|
"type": "select",
|
|
"label": "Fuel Type",
|
|
"options": [
|
|
{ "label": "Hybrid", "value": "hybrid" },
|
|
{ "label": "Electric", "value": "electric" },
|
|
{ "label": "Any", "value": "any" }
|
|
]
|
|
}
|
|
],
|
|
"submitLabel": "Search"
|
|
}
|
|
```
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `fields` | array | Ordered list of form fields |
|
|
| `fields[].name` | string | Field identifier (sent on submit) |
|
|
| `fields[].type` | string | `"number"`, `"text"`, `"select"` |
|
|
| `fields[].label` | string | Human-readable label |
|
|
| `fields[].value` | any | Default value (for `number`/`text` fields) |
|
|
| `fields[].options` | `{label, value}[]` | Choice list (for `select` fields); each item has a display `label` and machine-readable `value` |
|
|
| `submitLabel` | string | Text on the submit button |
|
|
|
|
---
|
|
|
|
## Rules
|
|
|
|
- **Always use the `a2ui` language tag.** Any other tag (e.g. `json`) will render as
|
|
plain code; the frontend will not parse it.
|
|
- **JSON must be a single object with a `type` field.** Arrays and multi-root
|
|
documents are not supported.
|
|
- **Generate A2UI when the user benefits from interactive controls.** Filter chips,
|
|
sortable tables, card grids, and forms add real value when the user is comparing
|
|
options or needs to refine results.
|
|
- **Don't overuse.** Plain markdown lists and tables are fine for simple answers. Use
|
|
A2UI only when interactivity meaningfully improves the experience.
|