Features

Interactive surfaces (A2UI)

A2UI lets an agent ask for structured input โ€” a form, a choice, a date โ€” by describing what it needs, not by writing markup. The platform renders it as a real interactive card inside the chat thread, and the person's answer comes back as the tool's result.

Why declarative, not HTML

An agent that emitted raw markup would be a security hole and a rendering lottery. Instead it emits a blueprint โ€” a small, declarative description validated against a trusted component catalog before anything is stored or shown. An off-catalog component is refused with a per-field error the model can correct, so the set of things that can appear on screen is fixed and known.

The turn, end to end

  1. The agent calls render_ui with a blueprint.
  2. The blueprint is validated against the catalog; invalid ones are refused before storage.
  3. The run parks awaiting_input โ€” the same machinery a plain ask_user uses.
  4. The surface rides to the client as a message part and renders as a card.
  5. The person answers; POST /runs/{id}/ui-action resumes the run with their input as the tool result.
The surface id is authorization, not a label A run parks on exactly one surface. Answering any other id is a conflict, so a stale card cannot answer a live question and a double-submit is a no-op.

Governance still applies

DLP runs both ways: the labels an agent writes are delivered content and are redacted on the way out; the values a person types are user input and are redacted on the way in. Files attached through a surface ride the existing conversation-document path โ€” the data model sees ids, never bytes.

The catalog

The catalog types every component and its properties โ€” text, a choice picker, text and date fields, buttons, and (in the Trellaris catalog) a file upload. The validator is forgiving at the edge and strict at the core: it repairs the shapes models naturally get wrong (addressing a child by object instead of id, a stray required) and drops an unknown property rather than refusing the whole form, but it still refuses an off-catalog component type, an unresolvable child, or a button with no action. Every repair is recorded on the run's trace.