Chatbot Generative UI: Build Interactive Answers Safely

Use chatbot generative UI to turn text replies into safe cards, forms, and buttons with typed payloads, approval gates, fallbacks, and test cases.

Cover Image for Chatbot Generative UI: Build Interactive Answers Safely

Generative UI moved from a demo pattern into the agent-interface conversation this month. TLDR Dev's August 7 digest highlighted controlled, declarative, and open-ended approaches; TLDR AI followed on August 11 with the argument that agents are producing hybrid interfaces rather than eliminating screens.

For a website chatbot, the useful question is smaller: when should an answer become a card, form, chooser, or confirmation panel? Use this rule first: choose text for explanation, a controlled component for a repeatable task, a declarative component catalog for variable layouts, and open-ended generated code only inside a hardened sandbox for low-risk output. The decision table below is the asset to save before building anything.

Choose the Narrowest Useful Interface

A generative interface earns its place when it reduces ambiguity or prevents an error. A return-status card can expose the order, deadline, amount, and next action in one scan. A paragraph can technically contain the same facts, but it makes the customer hunt for them and leaves the action implicit.

Customer jobBest response modeExampleRelease gate
Understand a policyText with a source linkExplain the return windowCorrect citation and readable fallback
Pick from known optionsControlled componentShipping-method buttonsOnly server-provided options appear
Submit structured detailsControlled formWarranty claim formValidation, consent, and retry behavior pass
Review a variable result setDeclarative catalogOrders, invoices, or available appointmentsEvery component and field is allowlisted
Explore an unbounded artifactSandboxed open-ended UITemporary chart or diagramNo privileged data, network, or action access

Start in the highest-control row that can complete the job. Most support chatbots need cards, buttons, and forms drawn from a fixed catalog. They rarely need the model to invent HTML, JavaScript, event handlers, or navigation.

The distinction matters because "generated UI" can describe very different systems. Google's A2UI specification lets an agent describe native interface structure and data without sending executable code. AG-UI standardizes the event stream between an agent backend and a user-facing application. A team can adopt the underlying principles—a typed component catalog and a clear event contract—without adopting either protocol on day one.

Define the Answer Contract Before the Component

Do not ask the model to "make a helpful refund card" and treat the rendered result as the specification. Define a contract that separates five decisions:

  • Surface selection: which approved component fits the customer's current job?
  • Authoritative data: which service supplies status, price, eligibility, and deadlines?
  • Visible actions: which actions may this customer see in this state?
  • Commit boundary: which action requires confirmation, revalidation, or a person?
  • Fallback: what can the customer still understand or do if the component fails?

Version the contract. A stored conversation may reopen after the component schema changes, and an old mobile client may receive a new payload. A version field gives the renderer a clean way to reject an unsupported shape and show the fallback text.

Treat labels as data, too. If a tool returns an action label such as "Approve full refund," the client should map a stable action ID to approved copy rather than rendering arbitrary text as a trusted control. That keeps injected tool output from impersonating a safe button.

Worked Interaction: A Refund Status Card

Consider a customer who asks, "Can I return order 4817, and how much will I get back?" The chatbot retrieves the authenticated order and the current return policy. The service—not the language model—calculates eligibility, amount, destination, and deadline. The model may then select an approved refund-status-card surface.

{
  "surface": "refund-status-card",
  "version": 1,
  "data": {
    "orderId": "4817",
    "status": "eligible",
    "refundAmount": 79,
    "currency": "USD",
    "refundDestination": "Visa ending 2044",
    "returnBy": "2026-08-27"
  },
  "actions": [
    {
      "id": "start_return",
      "requiresConfirmation": true
    },
    {
      "id": "ask_question",
      "requiresConfirmation": false
    }
  ],
  "evidence": [
    {
      "label": "Return policy",
      "version": "2026-08-01"
    }
  ],
  "expiresAt": "2026-08-20T14:15:00Z",
  "fallbackText": "Order 4817 is eligible for a $79 refund to Visa ending 2044 if returned by August 27. Ask me to start the return or explain the policy."
}

The renderer owns layout, color, keyboard behavior, and responsive rules. It displays a summary and a Start return button, but clicking that button does not immediately issue the refund. The client sends the stable action ID and order reference to the server. The server reloads the order, checks identity and eligibility again, and returns a confirmation state with the exact amount and destination.

Only the confirmed request can create the return. Give that request an idempotency key so a double click, reconnect, or repeated event cannot create two returns. If the price, return deadline, or order state changed after the card was rendered, reject the stale action and issue a fresh status response.

This interaction stays useful in a client that cannot render cards. The fallback text preserves the facts and tells the customer what to ask next. It does not pretend that the return has already started.

Keep Generation on the Safe Side of the Boundary

Rich responses should increase clarity without expanding the model's authority.

Let the model choose among intents, not permissions. The server determines which surfaces and actions are allowed for the authenticated customer. A prompt instruction such as "never show refunds above $100" is weaker than an authorization check that omits the action entirely.

Bind facts to trusted tool output. Prices, balances, dates, inventory, and account state should arrive as typed fields from authoritative services. The model can explain them, but it should not calculate a refund amount from prose or infer eligibility from a general policy page.

Allowlist the component catalog. A declarative payload may choose order-card, date-picker, or confirmation-panel; it may not invent admin-override or attach a new event handler. Google's A2UI v0.9 announcement describes this separation as agents communicating UI intent through an existing component catalog.

Revalidate every consequential action. The data used to draw a card is a snapshot, not proof that an action remains valid. Authorization, current state, limits, and policy must be checked at commit time.

Record the evidence chain. Log the user request, selected surface, schema version, source versions, displayed fields, action events, confirmation, server result, and fallback. This is the interface equivalent of an action audit trail, and it makes a misleading card reproducible.

Design the Failure Path Before the Happy Path

Generative UI adds states that a text-only chatbot never had: partial payloads, unsupported components, interrupted streams, stale cards, failed actions, and client/server version drift. Write behavior for each one before polishing animation.

A component should mount only after its required fields validate. If a stream ends halfway through a surface definition, keep the previous stable message and offer retry; do not render a blank card with a live button. If an optional image or secondary field fails, the component can degrade without blocking the task.

Keep fallback text in the same event as the component payload so it cannot be lost during a second request. Screen readers, notification previews, transcript exports, search indexes, and older clients may depend on it even when the visual renderer works.

Give every action an explicit state: idle, submitting, succeeded, failed, or unknown. "Unknown" matters when the network disappears after submission. The client should query the action result using the idempotency key before it enables another attempt. Otherwise, a customer can see an error even though the return or booking succeeded and then submit it again.

Make Confirmation Describe the Commitment

A confirmation panel should answer four questions without requiring the customer to remember the conversation:

  • What exactly will happen?
  • Which object, account, or order will change?
  • What amount, date, destination, or audience is involved?
  • Can the action be undone, and what happens next?

Use direct verbs such as Cancel subscription, Submit warranty claim, or Send details to support. Avoid generic controls like Continue when the next event spends money, shares data, changes access, or contacts another person.

The confirmation must come from refreshed server data. Repeating model-generated prose from an earlier turn can preserve a stale amount with more confidence but no more authority. For higher-risk actions, add a human approval or a separate authenticated step. The chatbot approval workflow guide provides routing rules for deciding which commitments need that extra boundary.

Test the Interface as Behavior

Snapshot tests can confirm that a card still looks like a card. They cannot prove that it appears for the right customer, contains authoritative data, or commits the intended action. Build behavioral cases around selection, rendering, authorization, recovery, and accessibility.

Test caseFailure it should catch
Policy question with no action intentChatbot shows a transactional form unnecessarily
Tool omits a required amountRenderer mounts a misleading partial card
Customer lacks access to the orderCard leaks another customer's data or actions
Eligibility changes after renderingStale button completes a forbidden action
Submit event is delivered twiceDuplicate booking, claim, or refund
Client does not support the surface versionBlank response instead of useful fallback text
Tool text includes a fake action labelUntrusted copy renders as a privileged control
Keyboard-only and screen-reader useFocus, labels, status changes, or confirmation are inaccessible

Add contrast pairs to the selection tests. "What is your refund policy?" should usually receive an explanation; "Start a return for order 4817" may receive a transactional component after identity and order checks. The vocabulary overlaps, but the jobs differ.

Test the turn after failure as carefully as the failed turn. A rejected stale card should explain what changed and offer a safe next step. A timed-out API action should check its status before suggesting retry. A validation error should preserve the customer's other form fields.

Run adversarial prompts against the schema boundary as well as the prose. The chatbot brand-safety test set is a useful starting point for hostile user language; extend it with attempts to invent component names, reveal hidden fields, change action IDs, bypass confirmation, or render executable content.

Measure Whether the Interface Improved the Job

Do not declare success because customers clicked the new component. Track task completion, durable resolution, action failure, fallback use, correction, and duplicate-action prevention.

Suppose 1,000 return conversations previously used text replies. Five hundred customers found the return page, 420 submitted successfully, and 42 contacted support about the same return within 72 hours. The durable self-service result is 378 out of 1,000, or 37.8%.

After introducing a controlled status card, 680 customers start the flow, 620 complete it, 25 require a human handoff, and 35 reopen the same issue. Durable self-service rises to 585 out of 1,000, or 58.5%. That 20.7-point gain is useful only if policy defects, unauthorized actions, and duplicate returns remain within their hard gates. A higher click-through rate alone would hide all three risks.

Review fallback rate by client and surface version. A spike may mean an old embed, a schema rollout problem, or a component that fails validation on real data. Review action failures by reason rather than one total: permission denial, stale state, validation, dependency timeout, and unknown result need different fixes.

Start With the Components You Can Govern

Many website chatbots can capture most of the benefit without adopting a general-purpose generative UI protocol. A fixed button can narrow intent. A validated form can collect the fields a support team needs. A custom API action can retrieve live status or submit an approved request. The chatbot actions guide shows how to move from explanation to a bounded task.

Expand into a declarative catalog only when repeated workflows demand variable combinations of trusted components. Keep raw generated code away from customer accounts and consequential actions unless you can isolate its data, network, storage, and event capabilities inside a real sandbox.

The best chatbot interface is the smallest one that makes the customer's next decision clear and keeps authority on the server. Text remains excellent for explanation. Components earn their place when they structure input, expose live state, or make a commitment reviewable.

In Agentkit, custom buttons, forms, and API actions support the controlled-component pattern, while conversation logs provide evidence for reviewing how those interactions perform.

Build your chatbot for free →

No credit card required.

Gratis aan de slagGeen creditcard nodig