Display-only

Register React components that your agent can render in the chat for Agno.


Configure session storage

Agno must store the paused run before a frontend tool can return its result. Configure a database on the Agent that owns the external tool.

Install the SQLite dependency:

pip install sqlalchemy

Use a project-relative SQLite file for local development:

from agno.agent import Agent
from agno.db.sqlite import SqliteDb

db = SqliteDb(db_file="tmp/agno.db")

agent = Agent(
    # ...
    db=db,
)

The deployed showcase uses /tmp/agno.db because its application directory is read-only to the runtime user.

For production, use durable shared storage such as PgDb. An ephemeral container file cannot resume a run on another instance.

What is this?#

useComponent lets you register a React component as a tool your agent can invoke. When the agent calls the tool, CopilotKit renders your component directly in the chat with the tool's arguments as props.

This is the simplest form of Generative UI — your agent decides when to show a component, and CopilotKit renders it. No handler logic, no user interaction required.

When should I use this?#

Use useComponent when you want to:

  • Display rich UI (cards, charts, tables) inline in the chat
  • Show structured data from agent responses
  • Render previews, status indicators, or visual feedback
  • Let the agent present information beyond plain text

For components that need user interaction, see the Interactive or Interrupt-based guides.

Register a component#

Use the useComponent hook to register a React component. The agent will be able to call it by name, and CopilotKit will render it with the tool arguments as props.

app/page.tsx
import { useComponent } from "@copilotkit/react-core/v2"; 
import { z } from "zod";

const weatherSchema = z.object({
  city: z.string().describe("City name"),
  temperature: z.number().describe("Temperature in Fahrenheit"),
  condition: z.string().describe("Weather condition"),
});

function WeatherCard({
  city,
  temperature,
  condition,
}: z.infer<typeof weatherSchema>) {
  return (
    <div className="rounded-lg border p-4">
      <h3 className="font-semibold">{city}</h3>
      <p className="text-2xl">{temperature}°F</p>
      <p className="text-sm text-gray-500">{condition}</p>
    </div>
  );
}

function YourMainContent() {
  useComponent({
    name: "showWeather",
    description: "Display a weather card for a city.",
    parameters: weatherSchema,
    render: WeatherCard,
  });

  return <div>{/* ... */}</div>;
}

Without parameters#

For simple components that don't need typed parameters:

useComponent({
  name: "showGreeting",
  render: ({ message }: { message: string }) => (
    <div className="rounded border p-3 bg-blue-50">
      <p>{message}</p>
    </div>
  ),
});

Scoping to an agent#

In multi-agent setups, scope a component to a specific agent:

useComponent({
  name: "renderProfile",
  parameters: z.object({ userId: z.string() }),
  render: ProfileCard,
  agentId: "support-agent",
});