The nine components
Each component is a tool. The agent calls it with a complete payload, and the widget renders the result.
Table columns carry a format —
text, number, currency, percent,
date, delta, status, boolean, link, badge or array — plus a
locale, so amounts and dates render correctly without the model formatting
them as strings. Percent formats declare whether the source value is a
fraction (0.12) or a unit (12), because guessing is wrong by a factor of
a hundred half the time.
The same provider also ships quickchart-tool, which returns a chart as an
image URL for surfaces that cannot render a live component.
They are tools
Components live under the platform providerrich-ui-components and are
assigned per agent like any other tool:
Component anchors
An agent does not emit a component where the tool call happens to fall. It gathers data, registers each component, then writes one continuous answer with a marker placing each visual exactly where it belongs:1
Call the rendering tool with the complete payload
showChart with id: "q3-bookings" and every data point. The tool call
is the registration — there is no other way to create a component.2
Wait for the result
A successful result means the component now exists. An error result means
the payload was rejected, with the reason named, and the agent fixes it and
calls again.
3
Write the answer, placing each tag where it belongs
<component id="q3-bookings"/> on its own line — double quotes,
self-closing, each id at most once. The tag is replaced by the rendered
component.The failure to know about
The tag is a pointer to a component created by a tool call in the same response. A tag whose id has no successful tool call behind it — the model did the placement half and skipped the registration — renders as a visible “Failed to show component” error. The agent is instructed never to write a tag before its call has succeeded, and if it slips, to make the call before the response ends. When you see that error in the wild, the fix is almost always a model that is too small for the number of tools it holds, or a prompt that asks it to “describe the chart” in a way that invites prose instead of a call. Two more rules the agent follows:- Only the first payload for an id renders. Calling the tool again with the same id in one response is refused with an error saying so; corrected content needs a new id.
- Ids do not carry across turns. To show a component again later, the agent calls the tool again in that response and anchors the new call.
Making agents actually use them
An agent that holds components is told which rendering tools it has and when to reach for them: tabular data, trends, KPIs, code, diffs, images and links go through the matching tool rather than markdown. It is also told that a component only exists through a real tool call — never a payload pasted as JSON, never<element> or {{id}} placeholders, never “see the chart below”.
You do not need to repeat any of this.
What is worth writing in your own prompt is domain guidance: “occupancy
questions get a line chart by month; rate comparisons get a table with one
row per room type.” Tell the agent which shape suits which question, and let
the platform handle the mechanics.
The last two model steps of a turn are reserved: on the second-to-last step
only rendering tools remain callable, and on the last step none are, so an
agent that has been fetching data is pushed to render and answer rather than
run out of steps mid-table.
Sizing
Tables default to their natural height (maxHeight is empty); set a CSS
height on the payload when a long table should scroll instead of growing.
Columns can be marked hideOnMobile or truncate, and given a priority,
so a wide table degrades gracefully on a phone. Component payloads are kept
in the thread history at a much higher cap than ordinary tool results, so a
large table still renders when the conversation is reopened.
In workflows
A workflow can render components too: add a rich-UI step fed from earlier steps, then place<component id="<stepId>"/> in the workflow’s
output_text. The result thread renders it exactly as chat would. See
User workflows.