# a2ui

> Compose, validate, persist, and render A2UI v0.9.1 surfaces for Harness sessions in chat and on an injectable Console page.

| field | value |
|-------|-------|
| version | 0.1.16 |
| type | binary |
| license | Apache-2.0 |
| repo | https://github.com/iii-hq/workers |
| supported_targets | aarch64-apple-darwin, x86_64-pc-windows-msvc, aarch64-pc-windows-msvc, x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-unknown-linux-musl, armv7-unknown-linux-gnueabihf |
| author | iii |

## installation

```sh
iii trigger compose::add worker=a2ui@0.1.16
```

## dependencies

- `configuration` @ `latest`
- `harness` @ `latest`
- `ide` @ `latest`
- `llm-router` @ `latest`
- `state` @ `latest`

## readme

# a2ui

The A2UI worker turns compact agent intent into validated A2UI v0.9.1 surfaces, stores them under the originating Harness conversation, renders them inline in chat and on an injectable Console page, and sends user actions back to the same conversation.

## Install

```bash
iii trigger compose::add worker=a2ui
```

## Quickstart

Call `a2ui::generate` from a Harness turn. The Harness hook supplies the authoritative session, and the worker reads that turn's routed model, so the agent only sends intent and data:

```json
{
  "description": "A deployment approval card with service, version, risk, and approve or reject actions.",
  "data": {
    "service": "payments-api",
    "version": "2026.08.20",
    "risk": "medium"
  },
  "surface_id": "deployment-approval"
}
```

The call returns a compact receipt such as `{ "surface_id": "deployment-approval", "revision": 3, "component_count": 11, "page": "a2ui" }`. `page` is the console page id: an agent opens it with `console::workspace::open { screen: "ext:a2ui" }`. The Console keeps that receipt visible in the chat feed and expands it into the full surface on selection, while the A2UI page keeps every surface in the active conversation live through an exact-session state subscription.

Patch an existing surface with another natural-language request. Supplying `expected_revision` prevents an older composition from overwriting a newer edit:

```json
{
  "surface_id": "deployment-approval",
  "instruction": "Add an owner field and make the risk more prominent.",
  "expected_revision": 3
}
```

Interactive surfaces automatically submit their complete bound data model with button actions, so form values are persisted and forwarded to the originating Harness turn. The page also supports bounded revision history and undo, pinning, duplication, JSON import/export, and a per-session template library.

`a2ui::binding::set` can bind an exact `state`, `stream`, or `shell::changed` event to a JSON Pointer in the surface data model. Browser events are deliberately excluded because Console-side registration would bypass Browser approval boundaries. Bindings are declarative and cannot invoke arbitrary functions.

The A2UI page does not replace or embed itself in Shell or Browser. Its workspace action materializes a complete runnable React project under `generated/a2ui/<surface>-r<revision>` in the active Harness working directory. Shell then shows the real source files and Git diffs for editing. Run the generated Vite app in Shell and open its local URL in the Browser worker for preview. The same runnable project is available as a React app ZIP through `a2ui::surface::export-code`; JSON exports remain portable through `a2ui::surface::import`.

## Configuration

The `configuration` worker stores this worker's live settings. An optional `--config` YAML file seeds them on first boot:

```yaml
composer_model: null          # inherit the Harness turn's model
composer_provider: null       # inherit its routed provider
max_output_tokens: 8192       # one composition or repair call
max_composer_input_bytes: 786432
repair_attempts: 1            # bounded validation correction
max_surfaces_per_session: 16
max_history_per_surface: 64
max_templates_per_session: 32
max_components_per_surface: 160
max_description_bytes: 32768
max_data_bytes: 524288
max_surface_bytes: 2097152     # current surface plus bounded history
max_session_bytes: 16777216    # surfaces, histories, and templates
forward_actions: true         # send Console actions to harness::send
```

The worker implements the stable A2UI v0.9.1 envelope with the safe `urn:iii:a2ui:console:v0.1` catalog. The catalog maps declarative components onto the running Console's shared React components and design tokens; it never executes model-provided HTML, JavaScript, or CSS.

## skills

This version ships 1 skill file for agents, also browsable on the worker page:

- [`SKILL.md`](https://workers.iii.dev/workers/a2ui?tab=skills&skill=SKILL.md&version=0.1.16)

### SKILL.md

# a2ui

Use `a2ui` when the result should be an interface the person can scan or act on. Describe the desired experience and supply the underlying data; the worker delegates composition through `llm-router`, validates A2UI v0.9.1, and returns a compact receipt while the Console renders the surface.

Surfaces belong to the current Harness session. The Harness pre-trigger hook stamps that identity authoritatively, and Console actions return to the same conversation as structured user interactions.

## When to Use

- Present a dashboard, status overview, comparison, form, approval, or decision surface.
- Keep a result live while later function calls update its components or data model.
- Let a person respond through buttons or bound inputs without asking them to author JSON.
- Revise an existing interface through a plain-language patch while preserving unspecified content.
- Export a finished surface as portable A2UI JSON for reuse outside the current conversation.
- Reuse, undo, pin, duplicate, import, or export a surface as a runnable React app or a data-serving iii worker template.
- Materialize the React app into the selected workspace when the person wants to inspect and edit its files in Shell, then preview it through Browser.
- Bind surface data to exact state, stream, or Shell change events when the UI should stay live.

## Boundaries

- Do not use A2UI for plain answers that are clearer as a short message.
- Generated surfaces use the fixed Console catalog; they cannot execute HTML, JavaScript, CSS, or arbitrary components.
- Use `canvas` for diagrams and freeform drawing, and use a domain worker directly when no visual surface is needed.
- `a2ui::action`, `a2ui::binding::apply`, `a2ui::stamp-session`, and `a2ui::on-config-change` are internal Console/Harness lifecycle functions, not agent tools.

## Functions

- `a2ui::generate` — compose and persist a complete surface from compact intent and optional data.
- `a2ui::surface::apply` — validate and atomically apply A2UI v0.9.1 messages to one surface.
- `a2ui::surface::get` — read one surface with its component graph and data model.
- `a2ui::surface::list` — list compact surface summaries for the current session.
- `a2ui::surface::delete` — remove a surface from the current session.
- `a2ui::surface::patch` — replace a surface from a natural-language change request with optional revision protection.
- `a2ui::surface::export` — return a session-free, replayable A2UI JSON package.
- `a2ui::surface::history`, `undo`, `duplicate`, and `pin` — manage the surface library and revisions.
- `a2ui::surface::import` and `export-code` — move surfaces between sessions or into source code.
- `a2ui::binding::set` and `delete` — manage safe declarative live-data bindings.
- `a2ui::template::*` — save, list, read, apply, and delete reusable session templates.
- `a2ui::action` — internal Console action ingress and optional Harness forwarding.
- `a2ui::stamp-session` — internal Harness hook that stamps authoritative turn context.
- `a2ui::on-config-change` — internal authoritative configuration reload handler.

## api reference

```json
{
  "functions": [
    {
      "description": "Generate a user interface from a short description and optional data. Renders a safe A2UI v0.9.1 surface in chat and on the A2UI page, returning a compact receipt.",
      "metadata": {},
      "name": "a2ui::generate",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "additionalProperties": false,
        "properties": {
          "data": {
            "default": null,
            "description": "Optional application data. The composer should bind components to this data instead of repeating it in the component graph."
          },
          "description": {
            "description": "Plain-language description of the interface to compose.",
            "type": "string"
          },
          "replace": {
            "default": true,
            "description": "Replace a surface with the same id. Defaults to true.",
            "type": "boolean"
          },
          "surface_id": {
            "default": null,
            "description": "Stable id to use for the generated surface. Omit for a generated id.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "default": null,
            "description": "Human-readable title shown in the Console sidebar.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "description"
        ],
        "title": "GenerateRequest",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "SurfaceStatus": {
            "enum": [
              "active",
              "deleted"
            ],
            "type": "string"
          }
        },
        "properties": {
          "catalog_id": {
            "type": "string"
          },
          "component_count": {
            "format": "uint",
            "minimum": 0,
            "type": "integer"
          },
          "page": {
            "type": "string"
          },
          "protocol_version": {
            "type": "string"
          },
          "revision": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "session_id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/definitions/SurfaceStatus"
          },
          "surface_id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          }
        },
        "required": [
          "catalog_id",
          "component_count",
          "page",
          "protocol_version",
          "revision",
          "session_id",
          "status",
          "surface_id",
          "title"
        ],
        "title": "SurfaceReceipt",
        "type": "object"
      }
    }
  ],
  "triggers": []
}
```
