Concepts

Generative UI

How answers become native components instead of chat walls.

An assistant message is an ordered list of blocks. Each block is one component from a typed catalog with validated props and a required fallback_text used for accessibility and graceful degradation.

The catalog

Twenty-one components ship in the current catalog, and the Flutter SDK renders all twenty-one natively:

text · quick_replies · info_card · item_list · product_cards · confirm_card · form · datetime_slots · booking_card · stat_group · progress · chart · table · order_tracker · receipt · plan_comparison · media_gallery · status_banner · key_value · variant_picker · article_card

The component catalog has a page per block: props, a wire example, its interaction behaviour and its states.

confirm_card is special: it is synthesized by our servers from your action's template, never generated by the model. A hallucination cannot misrepresent what the user is approving.

Streaming

Text streams token by token. Components are block-atomic: the SDK draws a typed skeleton the moment a block is announced, then hydrates it in one step once the block validates. You get perceived speed without half-rendered widgets.

Screens that update in place

An answer does not have to be a new message. Two things let the screen keep up with the conversation instead of piling up beside it:

Forms (Flutter 0.28, web 0.6). When the copilot redraws a form the user has not sent yet, with the same form_id, the new form takes the old one's place. Every answer the user gave for a field that is still there stays; a field they changed themselves keeps their value whatever the copilot now proposes; a field the new form no longer has goes away. Each message also carries what is in the open forms, so "actually, refund it to store credit" reshapes the return form around the order and reason already chosen. A form that was sent is never replaced.

Any block, by surface (Flutter 0.29, web 0.7). The copilot can name something on screen that may change, a cart, a list being narrowed, an order's status, with a surface_id. A later block with the same id replaces it. The server numbers each redraw (revision), and the SDK keeps the newest: a retried or resumed stream that delivers an older version late cannot undo a newer one. A choice the user made on the old block (a size in a variant picker, a time slot) is kept if the new block still offers it. A conversation names at most eight surfaces.

Both are declared by the SDK in its handshake (form_update, surface_update), and the server tells the model about them only when they are. A build that predates them draws a redrawn block as a new block, as it always did.

Version safety

The SDK declares which components it can render on every request, and the server builds the model's toolset from the intersection. An older SDK in the field is never sent a component it cannot draw; unknown types render their fallback_text. Props are only ever added, never changed in place.

Grounding rule

The model is instructed to render only data it actually holds: action results, knowledge passages, app state. If it lacks data, it asks or calls a read action first. Blocks that fail validation degrade to text instead of shipping wrong UI.