⚙️ [a2ui-blog-host]: ui/initialize ...
📡 [public-edge-worker]: InitializeResult (200 OK)
✅ [status]: STATUS_LIVE_ARTIFACT // NO_SERVER_COMPUTE_ENGAGED
Blog › Rich UI in Gemini Enterprise: A Field Report on A2A Agents and A2UI Primitives
using a2ui in Gemini Enterprise · Vol. 02 LIVE_ARTIFACT

Rich UI in Gemini Enterprise: A Field Report on A2A Agents and A2UI Primitives

2026-07-25 14 min read series using a2ui in Gemini Enterprise · Vol 2 build 4747130

Who this is for: A2A agent authors targeting Gemini Enterprise who need to know exactly which v0.8 primitives work, which have drifted from the docs, and how to compose them into real multi-step flows.

Previously on A2UI

A2UI is a declarative UI protocol created by Google, with real community contributions from teams at Flutter and CopilotKit — for the full spec and governance details, a2ui.org remains the authoritative source, not this post.

In short: A2UI equips an agent with a curated catalog of battle-tested UI components. Instead of a model freehanding raw markup, it composes interfaces from pre-approved primitives. Putting aside benefits like token efficiency for a moment, this guarantees that an agent's output becomes consistent, repeatable, and resilient (some level of reasoning is still needed from the model).

Google Cloud's Gemini Enterprise

Most AI platforms hand you a map to the boiler room and wish you luck — Agents, Agent Registries, routing logic, model selection. Gemini Enterprise is betting the everyday business user shouldn't need any of that. They showed up because someone promised this tool could make their workday easier, not to learn agent infrastructure.

The platform's job is to make complexity invisible, not merely documented.

For enterprise adoption to scale, we need resilient UIs that agents can drive with zero friction — or as I keep coming back to: "useful for humans, declarative for AI Agents."

It is a bold move for Google to dogfood the A2UI protocol and bake it directly into the Gemini Enterprise console. Supported by agent orchestration capabilities like A2A and enterprise controls like Model Armor, an agentic-ready UI surface is the missing piece. (Though at the time of writing, if you want to leverage A2UI with your own agent, you need to use an A2A-based agent — see a2ui.org's own A2A extension spec.)

What Is Under the Hood?

Gemini Enterprise ships a closed-source client renderer pinned to v0.8 — officially the Legacy tier on a2ui.org's own version table — of the A2UI protocol. Currently, the catalog of recognized primitives is a fixed set of 18 — effectively defining the agent's native UI capabilities (unchanged from that Legacy v0.8 through Stable v0.9, Current v0.9.1, and the v1.0 release Candidate).

Without A2UI, an agent in Gemini Enterprise has very limited UI capabilities (spoiler: it can't even display an image natively). With it, those 18 primitives unlock full interactive workflows — video, audio, sliders, and tabs that no chat card has ever had natively, and, as the two demos further down show, real server round-trips that compute, render, and write files back out.

I have been able to get all 18 primitives to render, and everything is interactive round-trips — buttons dispatch real actions, text fields two-way bind, tabs switch, modals open. The findings below are the recorded output from actual messages sent to a real Gemini Enterprise chat, against a live A2A agent — captured and pin-annotated automatically via Playwright.

One more thing worth knowing before the gallery: GE renders only the standard v0.8 catalog — point it at your own catalogId and you get Unknown element, the same flat rejection any unrecognised component gets.

A Fairly Quiet Space

While A2UI is in its infancy, public exploration remains sparse. Beyond a notable project by GDE Martin Hawksey — AppSheet2Agent, which uses Google's Antigravity SDK to generate custom agents that make AppSheet data conversational, complete with A2UI v0.8 cards, inside Gemini Enterprise's chat — there is very little focused material on UI execution inside the console.

You may have seen Google's impressive Google Maps demo showcasing restaurant findings inside an embedded frame. However, that demo offers a glimpse into the future: the customcatalog it depends on is not currently exposed in standard Gemini Enterprise tenants, drawing a blank if you attempt to reproduce it natively today.

Gotcha: GE runs the Legacy v0.8, but the docs you'll find default to the v1.0 Candidate

Fifteen primitives render on the obvious payload. The three that required non-obvious payloads — Tabs, Modal, MultipleChoice — all for the same reason: GE ships the Legacy v0.8 renderer, but the docs you hit first (a2ui.org) default to the v1.0 release Candidate, which changed exactly these components. Build to v1.0 and GE rejects or crashes on it with errors that point nowhere. The real spec is the v0.8 Zod schema: a2ui-project/a2ui → renderers/web_core/src/v0_8/schema/common-types.ts.

The specific traps:

  • It's MultipleChoice, not ChoicePicker (renamed in v1.0). Wrong name → a flat Unknown element.
  • tabItems (Tabs) and options (MultipleChoice) are bare arrays, not {"literalArray": …}-wrapped — even though container children is wrapped, in {"explicitList": …}. Guess wrong → an opaque `te`Tabs` crash.
  • Modal's fields are entryPointChild / contentChild, not trigger / content, and there's no open field.

The 18 primitives, one at a time

Each entry below is a real capture, pin-annotated — the technical fact (field name, real shape) and the plain-language read, side by side. Grouped by what they're for, not alphabetically: Containers, Actions & round-trips, Inputs, Navigation, Overlays, Media & display. Each card also carries a Chat Cards v2 equivalence badge: fully working the same way, ~ partial or with a quirk, no client-bound equivalent at all in Cards v2.

chat
chat

01Containers

Card

containerchat Chat Cards v2 ✓

A single-child container with card styling.

Card primitive rendering in Gemini Enterprise
i
ii
iii
iv
child: <id>i. Bare component-id, not a wrapped list — worth one child only (a Column, if the card needs more than one thing).
Text (title) + Text (body)ii. Two Text blocks doing different jobs by usageHint — the catalog's least glamorous primitive, load-bearing everywhere.
Card ⊂ Cardiii. A Card nested inside a Card — the depth GE actually renders, confirmed rather than assumed.
iv. Thumbs / copy / more — Gemini Enterprise's own turn chrome, not part of the A2UI payload.

Row

containerchat Chat Cards v2 ✓

Horizontal layout container.

Row primitive rendering in Gemini Enterprise
i
ii
iii
children: {explicitList: […]}i. Every button row in this agent's live decks — weather-city suggestions, the workspace refresh control — is a Row underneath.
First · Second · Thirdii. Even spacing across the full width is GE's own layout choice for Row's children, not a field the payload set explicitly.
children-list mutation — inferrediii. Column's own children list is confirmed live-mutable both ways (see Column below). Row shares the identical field shape but hasn't been separately re-tested — treat as likely, not confirmed, until checked.

Column

containerchat Chat Cards v2 ✓

Vertical layout container.

Column primitive rendering in Gemini Enterprise
i
ii
iii
children: {explicitList: […]}i. The single most-used primitive in this agent's codebase — every Card on this page wraps exactly one Column.
Top · Middle · Bottomii. Stacked top-to-bottom in declaration order — no separate 'align' field was needed for this simple case.
children-list mutation — confirmed both waysiii. The single biggest mechanical finding in this whole catalog: resending a Column's full children array on an OPEN surface can both ADD a new id (with a definition for that leaf) and REMOVE one — confirmed live, no stuck node, no error either direction. The safe default (declare the full tree up front, only patch leaf content afterward) is still right to reach for first — this just means it's no longer the only option.

List

containerchat Chat Cards v2 ✓

A scrollable list container.

List primitive rendering in Gemini Enterprise
i
ii
direction: verticali. Scrollable rather than paginated — for long children sets this is the one to reach for over Column.
children: {explicitList: […]}ii. Same convention as Column's children — no surprises versus what Card/Row/Column already taught.

02Actions & round-trips

Button

action · round-tripchat Chat Cards v2 ✓

A tappable button that dispatches an action to the agent.

Button primitive rendering in Gemini Enterprise
i
ii
userAction → agenti. Not just "renders" — a real click dispatches a userAction DataPart ({name, sourceComponentId, surfaceId, context}) back to the agent, confirmed round-trip.
Text ×2 (title, caption)ii. Same Text primitive from the Containers group, reused as heading and sub-caption — no separate "heading" primitive exists in the 18.

CheckBox

action · client-boundchat Chat Cards v2 ✓

A labelled checkbox bound to a boolean value.

CheckBox primitive rendering in Gemini Enterprise
i
ii
checked: {path: …}i. Native checkbox with its label as PART of the same primitive — not a separate Text block sitting next to it.
two-way boundii. Toggling flips client-side state immediately; nothing reaches the agent until the next Button tap carries it along in context.

TextField

action · round-tripchat Chat Cards v2 ✓

A text input, two-way bound to the data model.

TextField primitive rendering in Gemini Enterprise
i
ii
value: {path: …}i. Type a city, hit submit: the resolved value comes back on the following Button's action.context — real two-way binding, not a static field.
→ action.context on next Buttonii. The genuinely useful primitive of the whole catalog for an agent that takes typed input instead of only picking from suggested replies.

03Inputs

Slider

input · client-boundchat Chat Cards v2 ✗

Selects a numeric value within a min/max range.

Slider primitive rendering in Gemini Enterprise
i
ii
min / max / value: {path: …}i. Draggable thumb position; the numeric label underneath is a separate Text block GE doesn't merge onto the thumb itself.
value echoed as textii. The seeded value (95) shows both in the handle position and echoed underneath — a payload convenience, not automatic.

MultipleChoice

input · client-boundchat Chat Cards v2 ✓

One or more selections from a list.

MultipleChoice primitive rendering in Gemini Enterprise
i
ii
iii
options: [{label,value}] (bare array)i. The schema asks for a selectable list; GE's client chose the chip affordance here — a different host could legitimately render checkboxes instead.
selections: {path: …}ii. Note the field is selections, not value — resolves to an array of the selected option values, confirmed live with one chip selected.
variant: "chips" — required alongside typeiii. Undocumented anywhere else in this catalog: type:"chips" alone renders a collapsed dropdown ("N Selected" + chevron) that expands into a checkbox list, not flat pills. Both fields are needed for the chip look shown here — found by diffing against a working reference, not from any spec.

DateTimeInput

input · client-boundchat Chat Cards v2 ✓

A native date and/or time picker.

DateTimeInput primitive rendering in Gemini Enterprise
i
enableTime: false — not honoredi. Sent enableDate: true, enableTime: false for a date-only field; GE showed a full date-AND-time picker anyway. Functionally usable, just not what was asked for — a confirmed client quirk, not a guess.

04Navigation

Tabs

navigation · client-onlychat Chat Cards v2 ✗

Tabbed panels, one visible at a time.

Tabs primitive rendering in Gemini Enterprise
i
ii
iii
tabItems: [{title,child}] (bare array)i. The fiddliest primitive to land: wrapping tabItems in {literalArray:…} — the same wrapper children correctly uses — crashes with an opaque teTabs` exception. Bare array is the real v0.8 shape.
tabItems[1] · inactiveii. A tap here swaps the visible panel entirely client-side — confirmed no round trip is needed for the switch itself.
active panel · Textiii. Whatever the active tab's own child is — here, one more Text block.

05Overlays

06Media & display

Text

displaychat Chat Cards v2 ✓

Displays text with simple Markdown formatting.

Text primitive rendering in Gemini Enterprise
i
ii
markdown-lite: bold, italic, codei. No full Markdown — no links or lists inline here, just the three inline styles confirmed rendering.
usageHint: h1–h5 · body · captionii. The only primitive with a type-scale field — why it's the load-bearing one behind every other primitive's title/caption pairs.

Image

displaychat Chat Cards v2 ✓

Displays an image from a URL.

Image primitive rendering in Gemini Enterprise
i
ii
iii
url (literal or data-bound)i. sankey_flow here isn't a live chart primitive — it's a server-rendered PNG pushed through Image, since GE's client only recognises the 18 standard primitives.
static raster, no interactivityii. Every pixel is baked in ahead of time — no live values, no data-binding once it's an Image. The workaround that makes any custom atom displayable in GE today.
usageHint: real enum, no "hero"iii. The valid values are icon, avatar, smallFeature, mediumFeature, largeFeature, header — "hero" isn't one of them. GE tolerates the invalid value on a fetched-URL Image and just fails silently; on an inline data: URI Image it also fails silently, no error either way — the dangerous part is neither path tells you why the image vanished.

Icon

displaychat Chat Cards v2 ✓

A system icon (Material Symbols).

Icon primitive rendering in Gemini Enterprise
i
name: <material-symbol>i. Confirmed a real Material Symbols glyph, vector-rendered — NOT emoji substituted into a Text block, the distinction an earlier dedicated probe existed to settle.

Video

displaychat Chat Cards v2 ✗

A native video player from a URL.

Video primitive rendering in Gemini Enterprise
i
ii
controls: true (required)i. Listed as a rendering guideline, not a default — omit it and GE renders a silent player with no visible play button at all.
native <video>, scrubbing includedii. A real element, not a thumbnail-then-launch pattern — full timeline scrub confirmed.

AudioPlayer

displaychat Chat Cards v2 ✗

A native audio player from a URL.

AudioPlayer primitive rendering in Gemini Enterprise
i
same url shape as Video, no extra fieldsi. A real native audio element — duration (5:48) read straight from the file, GE isn't faking the control chrome.

Divider

display

A horizontal or vertical dividing line.

Divider primitive rendering in Gemini Enterprise
i
axis: horizontal | verticali. The simplest primitive in the catalog and it shows — this one rule IS the entire primitive; everything else on screen is surrounding Text blocks.

The Demo Agent/App: Wall-Building Configurator

To test the real-world limits of native A2UI execution, I built a working agent app with Claude: an agent-driven wall-building configurator. I like this category of use case — multi-input, looped interactions with artifacts that get exported straight to a Google Drive repository.

The workflow: tell the agent the wall's height and width, block type, bond pattern, load-bearing requirements, damp-proof course toggles, planned start date, and crew size. The agent calculates material requirements, total weight, and an illustrative crew-size build curve, then patches the live specification directly back into the existing card — in place, with no chat spam.

This served as a practical test of 18 primitives composed in unison — not 18 isolated probes stitched together afterward:

  • MultipleChoice for country, block, and pattern selection.
  • Slider and TextField bound together for physical dimensions.
  • CheckBox for structural toggles.
  • DateTimeInput for scheduling.
  • Nested Modals (explicitly testing whether GE's renderer supports modals inside modal content — it does).
  • Tabs splitting output across Drawing, Bill of Materials, Build Time, and Advisories.
  • Server-rendered SVG elevation delivered via the Image primitive.
  • Button actions that trigger a backend export to Google Drive, complete with a scannable QR code.
Confirmed In Isolation

Nested Modal-in-Modal wasn't just observed working inside this composite flow — it was retested afterward as its own isolated, single-purpose probe and confirmed live on its own, independent of Wall Builder's other state.

Click through the real flow below — the highlighted (filled, larger) pin on each screen is the one a real user would actually click next; every other pin just shows what primitive that piece of UI is and what's notable about it.

Wall Builder

Wall Builder — click through the real flow

interactive tourGitHub ↗

An agent-driven A2UI v0.8 demo (a2uicatalog-printer) — one surface, patched in place, from form to an exported spec in Google Drive. Only two clicks in the whole flow ever reach the agent; click the highlighted control on each screen to advance.

Wall builder agent's entry response in Gemini Enterprise, with a Start the wall builder button
i
Button — entryPointChildround tripi. Opens the outer Modal — the whole configurator lives inside it, including a Modal nested inside this Modal's own content (an explicit test of whether GE's client would allow that; it does).
Wall Builder Configurator
An agent-driven A2UI v0.8 demo running inside Gemini Enterprise — one surface, patched in place, from form to exported spec.
Demo 1 · Reference sheet
Surface a2uicatalog-printer (A2A agent)
Protocol A2UI v0.8 over A2A / SSE
Host Gemini Enterprise, Lit client
Scale n/a

Request flow — Fig. 1

Two real round-trips to the agent — everything else is the A2UI client binding fields locally.

User
Gemini Enterprise
Agent
Shared Drive
1UserGemini Enterprise  "wall builder"
2Gemini EnterpriseAgent  A2A message (SSE)
3AgentGemini Enterprise  beginRendering + surfaceUpdate (outer Modal, full form tree)
4Gemini EnterpriseUser  renders "Start the wall builder"
Slider · CheckBox · DateTimeInput · MultipleChoice bind client-side — no agent round-trip yet
5UserGemini Enterprise  click "Show me the specification"
6Gemini EnterpriseAgent  userAction DataPart (context = form values)
7AgentGemini Enterprise  bare surfaceUpdate, SAME surfaceId — patches modal-col in place
8Gemini EnterpriseUser  Drawing / Bill of materials / Build time / Advisory tabs
optUser exports the spec
9UserGemini Enterprise  click "Export specification to Drive"
10Gemini EnterpriseAgent  userAction DataPart
11AgentShared Drive  impersonated service account writes folder (elevation + BOM CSV)
12Shared DriveAgent  folder link
13AgentGemini Enterprise  patches exp-status + exp-qr
14Gemini EnterpriseUser  status line + scannable QR

Export identity chain — Fig. 2

The Drive write never runs as the Cloud Run service's own identity — it borrows a narrower one for exactly that call.

Stage by stage — Fig. 3

1
Openclient-rendered
The trigger phrase builds the entire form once, up front — including a Modal nested inside another Modal's content, an explicit test of whether the client would even allow it. It does. Primitives: Card, Column, Modal, Button, Text.
2
Configureno round-trip
Every input the user touches is a two-way data binding resolved entirely on the client. Nothing reaches the agent until the form is submitted. Primitives: MultipleChoice, Slider, TextField, CheckBox, DateTimeInput.
3
Calculateround-tripin-place patch
The Button click is the only primitive that reaches the agent. Its userAction carries the whole form as context; the agent computes units, weight, and a build-time curve, rasterizes a real SVG elevation, then replies with a surfaceUpdate that patches the already-open modal's content in place, on the same surfaceId. Primitives: Tabs, Image, Row, Divider, List, Icon.
4
Exportround-tripreal write
A second Button recomputes the same spec server-side and writes it out through the impersonation chain above. The reply patches two leaf ids with a status line and a scannable QR — never touching the container structure above them. Primitives: Button, Text, Image (QR).

Children-list mutation — resolved

💡 Design note — the safe path, now known not to be the only oneThis demo follows the safe convention: the full result tree — tabs and all — is declared once at open time as loading-state placeholders, and the calculate/export steps only ever patch LEAF content (text, image data, a status line), never a container's declared children set. That kept it strictly inside a mechanism already proven to work. Since first writing this, the open question has been resolved: a deliberately isolated probe confirmed GE does accept a children-list mutation on an open surface — redeclaring a Column with a brand-new child id (never present at open time) rendered live in GE's v0.8 client. So declaring the full shape up front was the safe path, not the only one. A future flow could grow a container additively across turns — appending a new tab, a new list row, a follow-up question, or a running gallery in the same open Modal — rather than only overwriting one fixed slot. (One confirmation, on Column, in GE v0.8; whether it holds for other container types, or for removing children, is still untested.)

D2 Architect

D2 Architect — click through the real flow

interactive tourGitHub ↗

A real Gemini Enterprise agent (d2-architect-agent) that turns a plain-language description into a rendered D2 diagram — click the highlighted control on each screen to advance, exactly as a real user would.

D2 Architect agent's entry banner in Gemini Enterprise, with an Open the D2 Architect button
i
Button — entryPointChildround tripi. Opens the Modal wrapping the whole flow. Its action name is literally noop — the established convention for a Button that only needs to reveal already-declared content: it still dispatches a real userAction (every Button must carry one), the agent just replies with a bare text ack instead of computing anything.
D2 Architect
A natural-language-to-diagram agent — plain descriptions in, real rendered D2 diagrams out, with independent multi-tab state.
Demo 2 · Reference sheet
Surface d2-architect-agent (A2A agent)
Protocol A2UI v0.8 over A2A / SSE
Host Gemini Enterprise, Lit client
Scale n/a

Request flow — Fig. 4

Four real round-trips to the agent — everything else is the A2UI client binding fields locally, same discipline as Wall Builder's Fig. 1.

User
Gemini Enterprise
Agent
Shared Drive
1UserGemini Enterprise  "d2 architect"
2Gemini EnterpriseAgent  A2A message (SSE)
3AgentGemini Enterprise  beginRendering + surfaceUpdate (form tree, Tab 1)
4Gemini EnterpriseUser  renders "Describe your diagram"
Diagram type · colour theme · sketch CheckBox bind client-side — no agent round-trip yet
5UserGemini Enterprise  click "Try an example"
6Gemini EnterpriseAgent  userAction DataPart (d2_try_example)
7AgentGemini Enterprise  surfaceUpdate, SAME surfaceId — patches description + diagram type
8Gemini EnterpriseUser  pre-filled example
9UserGemini Enterprise  click "Generate diagram"
10Gemini EnterpriseAgent  userAction DataPart (d2_generate)
11AgentGemini Enterprise  surfaceUpdate patches result panel with rendered D2 diagram
12Gemini EnterpriseUser  rendered diagram appears
optUser opens a second, independent tab
13UserGemini Enterprise  click "+ Add tab"
14Gemini EnterpriseAgent  userAction DataPart (d2_add_tab)
15AgentGemini Enterprise  surfaceUpdate adds Tab 2's own empty form state
16Gemini EnterpriseUser  new tab ready, Tab 1 untouched
optUser exports the diagram
17UserGemini Enterprise  click "Export to Drive"
18Gemini EnterpriseAgent  userAction DataPart (d2_export_drive)
19AgentShared Drive  writes the rendered diagram file
20Shared DriveAgent  file link
21AgentGemini Enterprise  patches export status + link
22Gemini EnterpriseUser  status line + link

Round-trips, by action name

Confirmed directly against the agent's own source (main.py) rather than guessed from behavior.

1
d2_add_tabround-trip
Adding a second diagram tab — unlike Wall Builder, where switching between already-open result tabs is client-only, HERE adding a new one needs the agent to set up that tab's own empty state server-side.
2
d2_try_exampleround-trip
Not a canned client-side fill — the agent picks the example description AND the matching diagram type together, in one reply.
3
d2_generateround-tripreal compute
Renders a fresh D2 diagram server-side from the description, diagram type, colour theme, and sketch flag — all bound client-side until this one click.
4
d2_export_driveround-tripreal write
Same round-trip-on-write discipline as Wall Builder's export.

A real, confirmed rendering bug

ℹ️ CheckBox label renders as literal "Invalid label"Confirmed live, screenshot evidence in hand: the Sketch-style CheckBox's label renders as the literal text "Invalid label" instead of the declared value, even though the agent's own source is unambiguously correct (label: {literalString: "Sketch style"}, verified directly). The checkbox itself still renders and binds correctly — this is specifically a label-text rendering defect on GE's client, not a declaration mistake. Worth contrasting with Wall Builder's tour above, where the same CheckBox primitive renders its labels correctly both times.

The Second Demo Agent: D2 Architect

Wall Builder tests composing 18 primitives into one looped, multi-input flow. The second demo agent, D2 Architect, tests a different shape entirely: natural-language-to-diagram generation, with independent, parallel state across multiple tabs.

The workflow: describe an architecture in plain language, pick a diagram type (Cloud Infrastructure / Network Topology, Sequence / Interaction Timeline, Entity Relationship), a colour theme, and whether to render it in a hand-drawn "sketch" style. The agent turns that into real D2 source, compiles it server-side, and returns the rendered SVG in place. Opening a second tab and generating a second, unrelated diagram there doesn't touch the first — switching back, tab one's diagram is exactly as it was left.

  • Modal opening the whole generator over the chat, MultipleChoice chips for diagram type and colour theme, CheckBox for the sketch toggle.
  • Tabs holding fully independent diagrams — each tab's own D2 source, own render, own Export-to-Drive action; nothing shared but the surface.
  • Server-rendered SVG delivered via the Image primitive, the same delivery mechanism the print-rendering workaround in Part 2 later builds on.
  • Button actions round-tripping to a real D2 compile step and a Drive export — the "D2 Architect's four round-trips" referenced below.

Two bugs surfaced and got fixed building this one, both worth knowing if you're generating D2 yourself: an LLM-authored shape: box meant "draw a rectangle," but D2 reserves box/arrow/triangle/cross/none/cf-* exclusively for arrowheads — a legal-shapes allow-list in the generation prompt closed that. And the same CheckBox "Invalid label" quirk from the primitive teardown above hit this agent's own sketch-style toggle first — fixed with the same defensive Text-sibling pattern.

Screen-recorded live, unedited — description in, form, generate, and the independent second-tab diagram, all in one take (and yes, that's "OAuth" misspelled as "Oauth" in my own typing — unedited means unedited):

Live screen recording of the D2 Architect demo in Gemini Enterprise

Both Demos Are Real, Downloadable Source

Both agents above are published as real source you can deploy yourself — wall-builder-agent and d2-architect-agent. One gotcha worth knowing before you register either one, confirmed live rather than assumed: the identity Gemini Enterprise actually calls your agent as is its Discovery Engine service agent (service-YOUR_PROJECT_NUMBER@gcp-sa-discoveryengine.iam.gserviceaccount.com), not a per-agent "reasoning engine" principal — granting the wrong one gets you a registered agent that's visible in the console and 403s the moment you actually message it. Both READMEs have the exact gcloud run services add-iam-policy-binding command; save yourself the debugging loop.

Key Takeaways & Wishlist

While custom catalogs aren't natively accessible in the console yet — likely a deliberate choice for stability and security governance while the initial paradigm is understood and feedback gathered — the power of these 18 primitives is undeniable. Both demos above share the same shape: declare the full result tree once as placeholders, bind every input client-side, and reach the agent on exactly the clicks that need real computation — never more. Wall Builder's two round-trips and D2 Architect's four are the entire server traffic for a multi-step, stateful-feeling app; everything else is the A2UI client doing what it was built to do.

The user interface footprint within Gemini Enterprise is intentionally constrained, but what you can orchestrate within that space is remarkably rich.

My Gemini Enterprise A2UI Wishlist

Developer Tooling & Spec Fidelity

Documented Support for Incremental Container Mutation — Through isolated testing, I confirmed GE's client renderer supports incremental updates: an agent can append a new child ID to an already-open Column across turns without wiping the existing slot. Confirmed for additive changes on Column; removal, and other container types, remain untested. Worth formally documenting rather than leaving developers to rediscover it blind.

A Native Dev/Debug Protocol Inspector — Right now, diagnosing A2UI behavior in GE requires "archaeology" — grepping backend agent logs to trace action names. A built-in developer inspector, or a simple "View Raw A2UI Wire Traffic" toggle inside the GE console, would let developers observe surfaceUpdate and userAction payloads in real time, dramatically speeding up development.

Field-Level Spec Fidelity & Conformance Suite — While GE's renderer executes the core 18 primitives well, there are subtle spec-drift bugs — such as DateTimeInput.enableTime: false being ignored, or CheckBox string literals rendering as "Invalid label." GE's client renderer needs a dedicated conformance test surface against its own documented A2UI spec contract, to ensure edge-case properties render reliably.

Enterprise UX & Platform Capabilities

Expanded UI Canvas / Workspace Mode — The current card footprint in GE is relatively narrow. A toggle to expand cards into a full-width canvas mode would give dense, multi-tabbed micro-apps — like spatial calculators or interactive diagram builders — the visual room they need to breathe.

Custom Catalog Extensions (catalogId Support) — While limiting the GE console to the core 18 primitives ensures stability today, allowing enterprise admins to register and inject organization-approved custom component catalogs (via catalogId) will be essential for deeper enterprise adoption.

Persistent UI State Across Session Resumes — Preserving interactive A2UI card states across chat session reloads, so returning users can resume interacting with dynamic cards without re-triggering agent execution turns.