Skip to content

A2UI in Flow-Like

Flow-Like uses an Agent-to-UI (A2UI) component model for interfaces that can be authored visually, generated with FlowPilot, rendered safely, and updated by a running workflow.

An A2UI surface is data, not executable frontend code. It contains allowlisted component types, a data model, styling, and actions. The Flow-Like renderer turns that description into native React components.

The A2UI authoring and runtime architecture in Flow-Like

Authoring pathBest forWhat it changes
Visual BuilderPrecise composition and inspectionThe surface’s components, styles, actions, and canvas settings
FlowPilotGenerating a first draft or revising a selected areaThe same surface model used by the builder
CombinedFast iteration with human reviewFlowPilot proposes changes; you inspect, apply, and refine them

Because both paths work on the same model, a generated surface can be opened in the builder and a manually authored surface can be given back to FlowPilot as context.

A surface has a stable ID, a root component, a flat component graph, and optional data and canvas settings. Parent components refer to their children by ID.

This is a minimal rendering message in the current Flow-Like format:

{
"type": "beginRendering",
"surfaceId": "sales-dashboard",
"rootComponentId": "root",
"components": [
{
"id": "root",
"component": {
"type": "column",
"gap": { "literalString": "16px" },
"children": { "explicitList": ["title"] }
}
},
{
"id": "title",
"component": {
"type": "text",
"content": { "literalString": "Revenue" },
"variant": { "literalString": "heading" }
}
}
],
"dataModel": []
}

The flat graph matters for both humans and agents:

  • A component can be updated by ID without replacing the whole surface.
  • Components can arrive incrementally while a workflow is running.
  • The hierarchy remains explicit and inspectable.
  • Values can be literal or resolved from a data-model path.

The renderer handles a broader set of messages, but these are the core surface operations:

MessagePurpose
beginRenderingCreate a surface with its root, components, and initial data
surfaceUpdateAdd or replace components on an existing surface
dataModelUpdateAdd or replace data entries
setCanvasSettingsUpdate the surface background, padding, or custom CSS
createElement / removeElementChange the component graph incrementally
deleteSurfaceRemove a surface

Navigation, dialogs, global/page state, and query-parameter updates are represented as explicit messages too. They are handled by the host rather than executed as arbitrary code.

Flow-Like only renders registered component types. The current catalog includes:

CategoryExamples
LayoutRow, Column, Stack, Grid, Scroll Area, Box, Center, Spacer
DisplayText, Image, Markdown, Table, charts, Calendar, Gantt, Geo Map
InteractiveButton, Text Field, Select, Checkbox, File Input, Voice Input, Link
ContainerCard, Modal, Tabs, Accordion, Drawer, Tooltip, Popover
SpecializedFile Preview, Diff View, image annotation, 2D and 3D scene components

The palette in the Visual Builder is the practical reference for the components currently available to authors. The renderer registry is the source of truth for what a client can display.

Pages and Widgets both store A2UI components, but they have different lifecycles.

ConceptScopeRuntime role
PageAn app experience, usually connected to a flowRendered when an app event targets the page
WidgetA reusable UI blockInserted into a Page or another surface as a widget instance

A Page can also define load, unload, and interval events. A Widget can define named actions that a host instance maps to workflow bindings.

The current action handler recognizes exact built-in action names:

ActionRequired contextBehavior
workflow_eventnodeId; the builder also stores appId and boardIdExecutes the selected workflow Event
widget_eventactionIdResolves that Widget action through the instance’s workflow binding
navigate_pageroute; optional queryParamsNavigates within the app
external_linkurlOpens an external URL in a new tab

workflow_event is not an arbitrary event label: context.nodeId identifies the Event node. Likewise, a Widget component always uses the literal widget_event name and selects its declared Widget action through context.actionId.

Unknown action names may be forwarded as a structured userAction message to an optional host callback, including the name, surface/source component IDs, timestamp, and context. That fallback does not execute a workflow by itself.

For workflow actions, the handler invokes the board with element values, input values, action context, and navigation state. During the run, Flow-Like can stream A2UI updates, state changes, navigation, progress, and logs back to the client.

This keeps the boundary explicit:

  1. A component declares one of the supported action contracts.
  2. The handler validates its required routing context.
  3. Flow-Like resolves the Event or Widget binding and runs it.
  4. The workflow returns declarative updates.
  • Pages — create and configure app Pages
  • Widgets — build reusable UI blocks
  • Visual Builder — use the current builder interface
  • Routes — map URL paths to app events