Tool-based Generative UI
Let your agent render rich React components directly in the chat by calling them as tools.
What is this?#
Tool-based Generative UI is the simplest form of Generative UI: you register
a React component with useComponent, and CopilotKit exposes it to the
agent as a tool. When the agent calls the tool, CopilotKit renders your
component inline in the chat, passing the tool's arguments straight through
as typed props.
Unlike tool rendering, which wraps a real backend tool in a custom UI, tool-based GenUI is the component. There is no handler, no user interaction, no server-side execution. The agent decides when to show it, populates the data, and CopilotKit paints it.
When should I use this?#
Use useComponent when you want to:
- Display rich UI (cards, charts, tables, dashboards) inline in the chat
- Show structured data the agent has derived from its reasoning
- Render previews, status indicators, or visual summaries
- Let the agent present information beyond plain text
For components that need user interaction, see Human-in-the-loop. For operational transparency around a real backend tool, see Tool rendering.
How it works in code#
useComponent takes a name, a Zod schema for its props, and the component
to render. The runtime registers it as a frontend tool so the agent can
discover it, and Zod validates the LLM's arguments before they reach your
component.
import { useComponent } from "@copilotkit/react-core/v2";
import { z } from "zod";
// Stand-ins for the locally-authored bar chart component + its prop
// schema. In a real page, these live in the demo directory (e.g.
// `./bar-chart.tsx` exporting `BarChart` and `barChartPropsSchema`).
declare const BarChart: React.ComponentType<{
title: string;
data: { label: string; value: number }[];
}>;
declare const barChartPropsSchema: z.ZodSchema;
export function BarChartRenderer() {
useComponent({
name: "render_bar_chart",
description: "Display a bar chart with labeled numeric values.",
parameters: barChartPropsSchema,
render: BarChart,
});The component itself is ordinary React: it reads only its props and can stream in as the agent fills the payload. The example above uses Recharts for the bar chart; it doesn't know anything about CopilotKit.
The name you pass to useComponent is what the agent sees as the tool
name. Make it a verb like render_bar_chart or show_weather so the LLM
reliably picks it when the user asks for that visualization.
