Skip to content

shadcn.io is an independent project built on shadcn/ui

Components

Free

Agent for Radix UI

An agent's setup on one card: its name and model, its instructions, and tools that open into their schemas. For React with Radix UI, before it runs.

One card says what an agent is: its name and model, the instructions it runs on, the tools it can call and what it returns.

Use it where people build, review or pick agents: a settings page, a team of agents side by side, the docs for an agent you ship. Each tool is a row that opens into its input schema, and the schemas show in a Code Block. Agent shows the setup before anything runs; Subagent shows a run that already happened, its tool calls and what it found. In React, Radix UI runs the tool list, so its rows open from the keyboard.

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

The install adds Accordion for the tools, Badge for the model, and Code Block with its highlighter for the schemas.

Anatomy

Agent anatomy: root, header, instructions, tools, tool, output
Agent
โ”œโ”€โ”€ AgentHeader (its name and model)
โ””โ”€โ”€ AgentContent
    โ”œโ”€โ”€ AgentInstructions
    โ”œโ”€โ”€ AgentTools
    โ”‚   โ””โ”€โ”€ AgentTool (one per tool, opens into its schema)
    โ””โ”€โ”€ AgentOutput

Usage

import {
  Agent, AgentContent, AgentHeader, AgentInstructions, AgentOutput,
  AgentTool, AgentTools,
} from "@/components/ui/agent";
<Agent>
  <AgentHeader model="gpt-4o" name="Research Assistant" />
  <AgentContent>
    <AgentInstructions>Search the web and cite every source.</AgentInstructions>
    <AgentTools>
      <AgentTool
        tool={{
          description: "Search the web",
          jsonSchema: { properties: { query: { type: "string" } }, type: "object" },
        }}
        value="search"
      />
    </AgentTools>
    <AgentOutput schema="interface Result { answer: string }" />
  </AgentContent>
</Agent>

Accessibility

Tab
Moves focus to the next tool's row, then into an open schema and its copy button.
Enter
Opens or closes the focused tool.
Space
Opens or closes the focused tool.
  • Each tool's row is a button with aria-expanded, and its description is the button's name.
  • A schema scrolls inside its block, and the block can take focus, so a long schema scrolls from the keyboard. Its copy button shows on focus as well as on hover.
  • Schemas always read left to right. The card itself follows the page direction.
  • The bot icon is hidden from assistive tech: the name says which agent it is.

Demos

Controlled

Three tools of a support agent, one open, with an Expand all button in the header. AgentTools takes the props of Radix UI's accordion, so the demo keeps which tools are open and sets them all at once. Whatever you pass as children to AgentHeader goes after the name, here the button. Open a tool from code when the reader came to see that one, from a link or a failed call.

Preview width

Team

Three agents in a column, each with its model and the number of tools it has. A card without AgentTools or AgentOutput shows only what it has, here the instructions. Use it to compare agents that share a task, such as a researcher, a writer and a reviewer. Keep each one's instructions short enough to read in the card.

Preview width

AI SDK Tools

Two tools written the way the AI SDK writes them, description and an inputSchema wrapped by jsonSchema(), and an output schema in JSON. AgentTool reads jsonSchema, then inputSchema, and unwraps the helper's wrapper, so a tools record renders as it is. language on AgentOutput sets its highlighting: TypeScript by default, json here.

Preview width

AI SDK

A tool from the AI SDK's tool() is a description and an input schema, which is what AgentTool takes. Map the record you hand the model, keyed by name:

import { jsonSchema, tool } from "ai";

const tools = {
  getWeather: tool({
    description: "Get the current weather for a city",
    inputSchema: jsonSchema<{ city: string }>({
      properties: { city: { type: "string" } },
      required: ["city"],
      type: "object",
    }),
  }),
};

export function WeatherAgentTools() {
  return (
    <AgentTools>
      {Object.entries(tools).map(([name, definition]) => (
        <AgentTool key={name} tool={definition} value={name} />
      ))}
    </AgentTools>
  );
}

A Zod schema isn't JSON Schema yet: convert it first, with z.toJSONSchema(schema) in Zod 4, and pass the result as jsonSchema. Show the model id you pass to the provider in AgentHeader's model, and the system prompt in AgentInstructions.

Migrating from AI SDK Elements

If you added Agent from AI SDK Elements (opens in a new tab), your project has components/ai-elements/agent.tsx. Install Agent from this page, change the imports from @/components/ai-elements/agent to @/components/ui/agent, and delete the old file. The parts keep their names and props. What changes:

  • tool takes any object with a description and a jsonSchema or inputSchema, so the AI SDK's Tool still fits, and the file no longer imports ai.
  • Schemas show in Code Block, highlighted, with a copy button. AgentOutput takes language, TypeScript by default.
  • AgentInstructions, AgentTools and AgentOutput take label for their headings, and AgentHeader renders its children after the model.

AgentTools is Radix's Accordion: type is "multiple" unless you pass "single", so type="multiple" can stay or go.

FAQ

How do I list an agent's tools in React?

Put one AgentTool per tool inside AgentTools, each with a unique value and a tool object. The row shows the tool's description, or No description, and opens into its input schema as JSON in a Code Block. Several tools can be open at once. AgentTool reads jsonSchema first, then inputSchema.

Can I pass AI SDK tools to Agent?

Yes. A tool made with the AI SDK's tool() has a description and an inputSchema, which is what AgentTool reads, and the wrapper that jsonSchema() adds is unwrapped for you. A Zod schema has to become JSON Schema first, with z.toJSONSchema in Zod 4, or the block shows Zod's internals instead of the fields.

What is the difference between Agent and Subagent?

Agent is the setup: the model, the instructions, the tools it may call and what it returns, before it runs. Subagent is a run: one line in a reply that opens into the calls a subagent made and what it found. Show Agent in settings and docs, and Subagent in the conversation.

How do I show what an agent returns?

Pass the schema as text to AgentOutput's schema prop: a TypeScript interface, a JSON Schema, or the source of a Zod schema. It's highlighted as TypeScript unless you set language, such as json. A long schema scrolls inside its block, and the copy button copies all of it.

How do I open a tool from code?

Control AgentTools as an accordion: pass value, the open tools' values, and update it from onValueChange, as the Controlled demo does.

Open the tool a link points at, or the one whose call failed, rather than all of them.

How do I style an Agent with Radix UI?

Edit the agent file under components/ui. Every part has its own data-slot, from agent and agent-header to agent-tool and agent-output, and the model badge is agent-model. The tool rows are your accordion, and the schemas are Code Blocks, so their styles come from those files. Pass className to any part for a one-off change.

How do I install Agent in React?

Run the command in the Installation section on this page. It adds the agent file, Accordion, Badge, Code Block and the highlighter the schemas use, so the demos work as soon as they're pasted. The command uses the shadcn CLI.

API Reference

Agent

<div> data-slot="agent"

PropType
className?string

Merged with the part's classes.

AgentHeader

<div> data-slot="agent-header"

PropType
namestring

The agent's name.

model?string

The model it runs on, shown as a badge after its name.

className?string

Merged with the part's classes.

AgentContent

<div> data-slot="agent-content"

PropType
className?string

Merged with the part's classes.

AgentInstructions

<div> data-slot="agent-instructions"

PropType
childrenstring

The system prompt.

label?string

The heading above it.

Default
"Instructions"
className?string

Merged with the part's classes.

AgentTools

<div> data-slot="agent-tools"

PropType
label?string

The heading above the list.

Default
"Tools"
type?"multiple"

"multiple" by default: any number of tools open at once.

className?string

Merged with the part's classes.

AgentTool

data-slot="agent-tool"

PropType
toolobject

The tool: its description is the row, its input schema the panel.

Type
{ description?: string; inputSchema?: unknown; jsonSchema?: unknown }
valuestring

A string value for the accordion item. All items within an accordion should use a unique value.

disabled?boolean

Whether or not an accordion item is disabled from user interaction.

asChild?boolean

Merge props onto the child element instead of rendering a host.

className?string

Merged with the part's classes.

AgentOutput

<div> data-slot="agent-output"

PropType
schemastring

What the agent returns: a type or a JSON Schema, as text.

label?string

The heading above it.

Default
"Output Schema"
language?string

The language the schema is highlighted in.

Default
"typescript"
className?string

Merged with the part's classes.