Interactive engineering lab

A2UI return form: catalogs, data binding and unknown components

Compare an A2UI return form with plain text turns: turns to collect three fields, bytes sent, and what strict, lenient and permissive renderers do with an injected unknown component.

By Sandeep Belgavi · Published 2026-11-02

Synthetic fixtures; deterministic local model. No production system is contacted.

Experiment inputs

Complete-run results

Decision trace

    What this experiment demonstrates

    Geetha wants to return a damaged paperback to Belgavi's Book Store, help-desk case CASE-2041. The agent needs three fields: the order id, the reason and a photo. She first types the order id as 1042 instead of BBS-1042. The agent describes a form as A2UI v0.9.1 messages (createSurface, updateComponents, updateDataModel), and the client renders it from the catalog it advertised: the store catalog with a PhotoUpload component, or the basic catalog, which has no file input.

    This is a deterministic model. No renderer or model runs. Byte counts are the UTF-8 length of the JSON messages the model builds, without the A2A envelope, and a turn is one agent prompt that Geetha answers. The permissive renderer is an anti-pattern included to show what the catalog rule protects against.

    Run controlled comparisons

    Start with the defaults: the store catalog, bound fields and a regex check on the order id. All three fields arrive in 1 turn, in 4 A2UI messages and 1,840 bytes.

    Now change one thing at a time. Switch the client to text only: with a budget of 3 turns the photo is still missing when the case goes to a person, and 174 bytes were sent; raise the budget to 4 and all three fields arrive in 4 turns and 210 bytes. Back on A2UI, choose the basic catalog: 2 turns, because the photo needs a text turn. Turn the client checks off: 2 turns, because the bad id goes to the agent and comes back. Send the whole surface on every change instead: still 1 turn at the defaults but 3,102 bytes, and 4,040 bytes with checks off against 1,837 incremental. Turn data binding off: the submit carries nothing, the agent falls back to text, and after 3 turns only 1 field is collected. Finally, turn on the injected component: strict mode rejects it and reports VALIDATION_FAILED, the lenient renderer shows an inert placeholder, and the permissive renderer renders it, which counts as 1 unsafe component.

    Inspect the trace and keep evidence

    The table lists every message between the agent and the client: direction, message type, bytes and what the renderer did with it. A rejected or placeholder component is amber, an unsafe one red. Start trace, Next step, Show all and the slider control how much of the decision trace is visible; the metrics always describe the whole run. Reset restores the defaults and Export JSON downloads the inputs, metrics and trace.

    Limits and production translation

    Real forms have more fields, renderers differ in what they implement, and a language model sometimes produces invalid JSON that has to be repaired. The model treats turns as equal in cost and does not include A2A envelopes, model latency or the upload of the photo itself. What carries over: the catalog the client advertises decides what the agent may send, inputs only reach the agent through bound paths and actions, client-side checks save round trips, incremental updates cost fewer bytes than resending the surface, and an unknown component must never become executable markup.

    Views are my own and do not represent any employer, past or present.