The generative UI concept
When an agent completes a task or needs user input, it should be able to generate a fully interactive UI widget directly in the feed whether that be an approval button to merge a PR, an email form pre-filled with context, a calendar event list.
The agent decides what interface to render based on the conversation context, and the user can act on it without leaving the feed.
The key design challenge here was making it feel native to the feed, so the card animates smoothly as content streams in using measure-based height animation, the easing has a subtle bounce animation, and it auto-resizes as you interact with items inside.
There are four widget types:
- Card: displays markdown content
- Form: collects structured input
- List: browsable items with expandable detail views
- Tool call approval — cancel/approve buttons for consequential actions
Engineering the widget schema system
Widgets are powered by a schema system. Each widget type is defined by a schema that describes its structure such as what fields it has, what actions it supports, and how it should render. When a Cobot decides to generate a widget, it produces a JSON payload conforming to the schema, and the frontend renders it as an interactive component.
What was important here was that all widgets share the same <WidgetCard/> container, the same visual language such as border-radius, shadow system, theme-aware styling so they feel native to the environment.
Schema definition and validation
Each schema defines the widget’s fields, their types, and the available actions. For example, the Tool Call Approval widget schema defines a title, description, an optional link, and two actions (Cancel and Approve) with distinct visual styles:
const toolCallApprovalSchema = {
type: "tool-call-approval",
fields: {
title: { type: "string", required: true },
description: { type: "string" },
link: { type: "url", label: "View PR" },
},
actions: [
{ id: "cancel", label: "Cancel", variant: "secondary" },
{ id: "approve", label: "Approve", variant: "primary" },
],
};
The schema drives both the rendering and the action handling. When a user clicks “Approve,” the widget dispatches the action ID back to the Cobot, which then executes the corresponding tool call (in this case, merging the PR via the GitHub API).