Tool Ui

assistant-ui/tool-ui/packages/agent/plugin/skills/tool-ui

by assistant-ui49a870286facdbf28160cd647f0d337ebdc9b275No license779 starsListed Oct 9, 2026Updated Oct 9, 2026Repository updated 5 weeks ago

Find, install, configure, and integrate Tool UI components in React apps using shadcn registry entries, compatibility checks, scaffolded runtime wiring, toolkit setup with assistant-ui, and troubleshooting workflows. Use when developers ask to add one or more Tool UI components, choose components for a use case, verify compatibility, wire a toolkit in a codebase, or integrate Tool UI payloads into assistant-ui or an existing chat/runtime stack.

ArchivedInstructions onlySoftware DevelopmentAI & Agents
AI-generated overview

Installs and wires Tool UI React components into apps via shadcn registry and assistant-ui toolkits.

What it does
This skill guides an agent through selecting, installing, and integrating Tool UI components in React projects. It covers compatibility checks against components.json, shadcn registry install commands, and a catalog of 25 components with prompts and install commands. It also documents toolkit setup with assistant-ui, including provider/runtime wiring, frontend versus backend tools, action patterns, and receipt conventions.
When to use it
Use when a developer wants to add one or more Tool UI components, choose components for a use case, verify compatibility, wire a toolkit into a codebase, or integrate Tool UI payloads into assistant-ui or an existing chat runtime.
Requirements
Requires a React project with a components.json file and network access for npx commands (tool-agent or shadcn). Some components need peer packages such as recharts or @pierre/diffs, and assistant-ui integration uses @assistant-ui/react and @assistant-ui/react-ai-sdk. Chat features may need API endpoint environment variables. Ships no scripts; instructions only.

Tool UI

Use this skill to move from request to working Tool UI integration quickly.

Prefer assistant-ui when the project has no existing chat UI/runtime. Treat assistant-ui as optional when the app already has a working runtime.

Step 1: Compatibility and Doctor

Read components.json in the user's project and verify:

  • components.json exists.

Step 2: Install Components

Install command from project root

Preferred (AI-assisted integration):

bash
npx tool-agent "integrate the <component> component"

Use component-specific prompts from the catalog below (e.g. integrate the plan component for step-by-step task workflows with status tracking).

Alternative (direct registry):

bash
npx shadcn@latest add @tool-ui/<component-id>

Multiple components:

bash
npx tool-agent "integrate the plan, progress-tracker, and approval-card components for planning flows"

Or via shadcn:

bash
npx shadcn@latest add @tool-ui/plan @tool-ui/progress-tracker @tool-ui/approval-card

Complete component catalog

All 25 Tool UI components with tool-agent prompts and shadcn install commands:

Progress

ComponentDescriptiontool-agent promptshadcn
planStep-by-step task workflows with status trackingintegrate the plan component for step-by-step task workflows with status trackingnpx shadcn@latest add @tool-ui/plan
progress-trackerReal-time status feedback for multi-step operationsintegrate the progress tracker component for real-time status feedback on multi-step operationsnpx shadcn@latest add @tool-ui/progress-tracker

Input

ComponentDescriptiontool-agent promptshadcn
option-listLet users select from multiple choicesintegrate the option list component to let users select from multiple choicesnpx shadcn@latest add @tool-ui/option-list
parameter-sliderNumeric parameter adjustment controlsintegrate the parameter slider component for numeric parameter adjustment controlsnpx shadcn@latest add @tool-ui/parameter-slider
preferences-panelCompact settings panel for user preferencesintegrate the preferences panel component for compact user settingsnpx shadcn@latest add @tool-ui/preferences-panel
question-flowMulti-step guided questions with branchingintegrate the question flow component for multi-step guided questions with branchingnpx shadcn@latest add @tool-ui/question-flow

Display

ComponentDescriptiontool-agent promptshadcn
citationDisplay source references with attributionintegrate the citation component to display source references with attributionnpx shadcn@latest add @tool-ui/citation
item-carouselHorizontal carousel for browsing collectionsintegrate the item carousel component for horizontal browsing of collectionsnpx shadcn@latest add @tool-ui/item-carousel
link-previewRich link previews with Open Graph dataintegrate the link preview component for rich link previews with Open Graph datanpx shadcn@latest add @tool-ui/link-preview
stats-displayKey metrics and KPIs in a visual gridintegrate the stats display component for key metrics and KPIs in a visual gridnpx shadcn@latest add @tool-ui/stats-display
terminalShow command-line output and logsintegrate the terminal component to show command-line output and logsnpx shadcn@latest add @tool-ui/terminal
weather-widgetWeather display with forecasts and conditionsintegrate the weather widget component for weather display with forecasts and conditionsnpx shadcn@latest add @tool-ui/weather-widget

Artifacts

ComponentDescriptiontool-agent promptshadcn
chartVisualize data with interactive charts (needs recharts)integrate the chart component to visualize data with interactive chartsnpx shadcn@latest add @tool-ui/chart
code-blockDisplay syntax-highlighted code snippetsintegrate the code block component for syntax-highlighted code snippetsnpx shadcn@latest add @tool-ui/code-block
code-diffCompare code changes with syntax-highlighted diffs (needs @pierre/diffs)integrate the code diff component to compare code changes with syntax-highlighted diffsnpx shadcn@latest add @tool-ui/code-diff
data-tablePresent structured data in sortable tablesintegrate the data table component to present structured data in sortable tablesnpx shadcn@latest add @tool-ui/data-table
message-draftReview and approve messages before sendingintegrate the message draft component to review and approve messages before sendingnpx shadcn@latest add @tool-ui/message-draft
instagram-postRender Instagram post previewsintegrate the instagram post component to render Instagram post previewsnpx shadcn@latest add @tool-ui/instagram-post
linkedin-postRender LinkedIn post previewsintegrate the linkedin post component to render LinkedIn post previewsnpx shadcn@latest add @tool-ui/linkedin-post
x-postRender X post previewsintegrate the x post component to render X/Twitter post previewsnpx shadcn@latest add @tool-ui/x-post

Confirmation

ComponentDescriptiontool-agent promptshadcn
approval-cardBinary confirmation for agent actionsintegrate the approval card component for binary confirmation of agent actionsnpx shadcn@latest add @tool-ui/approval-card
order-summaryDisplay purchases with itemized pricingintegrate the order summary component to display purchases with itemized pricingnpx shadcn@latest add @tool-ui/order-summary

Media

ComponentDescriptiontool-agent promptshadcn
audioAudio playback with artwork and metadataintegrate the audio component for audio playback with artwork and metadatanpx shadcn@latest add @tool-ui/audio
imageDisplay images with metadata and attributionintegrate the image component to display images with metadata and attributionnpx shadcn@latest add @tool-ui/image
image-galleryMasonry grid with fullscreen lightbox viewerintegrate the image gallery component with masonry grid and lightbox viewernpx shadcn@latest add @tool-ui/image-gallery
videoVideo playback with controls and posterintegrate the video component for video playback with controls and posternpx shadcn@latest add @tool-ui/video

Display (Geo Map)

ComponentDescriptiontool-agent promptshadcn
geo-mapDisplay geolocated entities and fleet positionsintegrate the geo map component to display geolocated entities and fleet positionsnpx shadcn@latest add @tool-ui/geo-map

Example installs by use case

tool-agent (recommended):

bash
npx tool-agent "integrate the plan, progress-tracker, and approval-card components for planning flows"npx tool-agent "integrate citation, link-preview, code-block, and code-diff for research output"npx tool-agent "integrate data-table, chart, and stats-display for data visualization"npx tool-agent "integrate image, image-gallery, video, and audio for media display"

shadcn (direct):

bash
npx shadcn@latest add @tool-ui/plan @tool-ui/progress-tracker @tool-ui/approval-cardnpx shadcn@latest add @tool-ui/citation @tool-ui/link-preview @tool-ui/code-block @tool-ui/code-diffnpx shadcn@latest add @tool-ui/data-table @tool-ui/chart @tool-ui/stats-display# npm i recharts  # peer for chartnpx shadcn@latest add @tool-ui/image @tool-ui/image-gallery @tool-ui/video @tool-ui/audio

Toolkit setup in a codebase

After installing components, wire them into assistant-ui via a Toolkit. This section covers the full setup: provider, runtime, toolkit file, and ID handling.

1. Provider and runtime

Create an assistant wrapper that provides runtime, transport, and tools:

tsx
"use client";
import { lastAssistantMessageIsCompleteWithToolCalls } from "ai";import { AssistantRuntimeProvider, Tools, useAui } from "@assistant-ui/react";import {  AssistantChatTransport,  useChatRuntime,} from "@assistant-ui/react-ai-sdk";import { Thread } from "@/components/assistant-ui/thread";import { toolkit } from "@/components/toolkit";
export const Assistant = () => {  const runtime = useChatRuntime({    transport: new AssistantChatTransport({ api: "/api/chat" }),    sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,  });  const aui = useAui({ tools: Tools({ toolkit }) });
  return (    <AssistantRuntimeProvider runtime={runtime} aui={aui}>      <div className="h-dvh">        <Thread />      </div>    </AssistantRuntimeProvider>  );};

Key points:

  • useChatRuntime + AssistantChatTransport: connects to your chat API.
  • Tools({ toolkit }): forwards tool definitions and renderers to the model.
  • sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls: auto-continues after tool calls (optional but common for tool-heavy flows).
2. Toolkit file structure

Create a single toolkit.ts (or toolkit.tsx) that exports a Toolkit object. Each key is a tool name; each value has type, description, parameters, and render.

Tool descriptions — Always include a description on every tool. Describe when to call the tool and what role it plays, not the visible content. The Tool UI component already renders the payload (options, plan, chart, etc.) to the user; a description that repeats that content is redundant. Prefer model-oriented guidance (e.g. "Present a plan for the user to follow" or "Let the user pick one option") over content echo (e.g. "Shows a list of options with labels and descriptions").

-Frontend vs backend tools

-FrontendBackend
-ImplementationRuns in the browser; user interaction commits via addResultTool implementation lives on the server; model returns the result
-executeRequired — runs the tool UI flow client-sideNot needed
-parametersRequired (schema for model args)does not use, uses inputSchema instead if backend llm is done via aisdk
-renderRequired (UI for args, status, result, addResult)Required (UI for result)

Backend tools (model returns result; no user input):

tsx
import { type Toolkit } from "@assistant-ui/react";import { Plan } from "@/components/tool-ui/plan";import { safeParseSerializablePlan } from "@/components/tool-ui/plan/schema";
export const toolkit: Toolkit = {  showPlan: {    type: "backend",    render: ({ result }) => {      const parsed = safeParseSerializablePlan(result);      if (!parsed) return null;      return <Plan {...parsed} />;    },  },};

Frontend tools (model sends args; user interaction commits via addResult):

tsx
import { type Toolkit } from "@assistant-ui/react";import { OptionList } from "@/components/tool-ui/option-list";import {  SerializableOptionListSchema,  safeParseSerializableOptionList,} from "@/components/tool-ui/option-list/schema";
const optionListTool: Toolkit[string] = {  description: "Render selectable options with confirm and clear actions.",  parameters: SerializableOptionListSchema,  render: ({ args, toolCallId, result, addResult }) => {    const parsed = safeParseSerializableOptionList({      ...args,      id: args?.id ?? `option-list-${toolCallId}`,    });    if (!parsed) return null;
    if (result) {      return <OptionList {...parsed} choice={result} />;    }    return (      <OptionList        {...parsed}        onAction={async (actionId, selection) => {          if (actionId === "confirm" || actionId === "cancel") {            await addResult?.(selection);          }        }}      />    );  },};
export const toolkit: Toolkit = {  option_list: optionListTool,  approval_card: {    /* ... */  },};
3. API route (AI SDK)

When the chat API uses the AI SDK (streamText), define backend tools with tool() from ai:

  • Use inputSchema
  • Backend tools use execute on the server; the result is streamed and rendered via the toolkit render function
ts
import { streamText, tool, convertToModelMessages } from "ai";import { openai } from "@ai-sdk/openai";import { z } from "zod";
// With frontend tools: ...frontendTools(clientTools) — clientTools come from the request body via AssistantChatTransportconst result = streamText({  model: openai("gpt-4o"),  messages: await convertToModelMessages(messages),  tools: {    get_weather: tool({      description:        "Get the current weather and forecast for a location. Returns data to display in a weather widget.",      inputSchema: z.object({        location: z.string().describe("City name, e.g. 'San Francisco'"),        units: z          .enum(["celsius", "fahrenheit"])          .default("fahrenheit")          .describe("Temperature unit"),      }),      execute: async ({ location, units }) => {        // Fetch weather data, return shape matching your widget schema        return { location, units /* ... */ };      },    }),  },});
4. Action-centric vs compound components
PatternComponentsUsage
Action-centricOptionList, ParameterSlider, PreferencesPanel, ApprovalCardWire onAction or onConfirm/onCancel directly; no ToolUI wrapper. Pass choice={result} for receipt state.
CompoundOrderSummary, DataTable, etc.Wrap in ToolUI + ToolUI.Surface + ToolUI.Actions; use DecisionActions or LocalActions.

Action-centric example (OptionList):

tsx
return (  <OptionList    {...parsed}    onAction={async (actionId, selection) => {      if (actionId === "confirm" || actionId === "cancel") {        await addResult?.(selection);      }    }}  />);

Compound example (OrderSummary with DecisionActions):

tsx
return (  <ToolUI id={parsed.id}>    <ToolUI.Surface>      <OrderSummary {...parsed} />    </ToolUI.Surface>    <ToolUI.Actions>      <ToolUI.DecisionActions        actions={[          { id: "cancel", label: "Cancel", variant: "outline" },          { id: "confirm", label: "Purchase" },        ]}        onAction={(action) =>          createDecisionResult({ decisionId: parsed.id, action })        }        onCommit={(decision) => addResult?.(decision)}      />    </ToolUI.Actions>  </ToolUI>);

ApprovalCard uses embedded actions; wire onConfirm/onCancel directly:

tsx
return (  <ApprovalCard    {...parsed}    choice={      result === "approved" || result === "denied" ? result : parsed.choice    }    onConfirm={async () => addResult?.("approved")}    onCancel={async () => addResult?.("denied")}  />);

Action Model

Tool UI uses two action surfaces, rendered as compound siblings outside the display component:

  • ToolUI.LocalActions: non-consequential side effects (export, copy, open link). Handlers must not call addResult(...).
  • ToolUI.DecisionActions: consequential choices that produce a DecisionResult envelope via createDecisionResult(...). The commit callback calls addResult(...).

Compound wrapper pattern for display components with actions:

tsx
<ToolUI id={surfaceId}>  <ToolUI.Surface>    <DataTable {...props} />  </ToolUI.Surface>  <ToolUI.Actions>    <ToolUI.LocalActions      actions={[{ id: "export-csv", label: "Export CSV" }]}      onAction={(actionId) => {        /* side effects only */      }}    />  </ToolUI.Actions></ToolUI>

Three components are action-centric exceptions — they keep embedded action props instead of sibling surfaces. All three share a unified interface:

  • actions: action buttons rendered by the component.
  • onAction(actionId, state): runs after the action and receives post-action state.
  • onBeforeAction(actionId, state): guard evaluated before an action runs.
ComponentState type passed to handlers
OptionListOptionListSelection
ParameterSliderSliderValue[]
PreferencesPanelPreferencesValue

Components using the compound pattern: CodeBlock, CodeDiff, Terminal, ProgressTracker.

Context is shared via createContext + use() (React 19). Subcomponents throw if used outside their Root.

Receipt and Choice Convention

Components with outcomes use a choice prop to render confirmed/completed state:

Componentchoice typeValues / shape
ApprovalCard"approved" | "denied"String literal
OptionListstring | string[]Selected option ID(s)
OrderSummaryOrderDecision{ action: "confirm", orderId?, confirmedAt? }
ProgressTrackerToolUIReceipt{ outcome, summary, identifiers?, at } (shared type)

When choice is present, the component renders in receipt mode — read-only, no actions.

Operational Rules

  • Install the smallest set of components that solves the request.
  • Every tool must have a description; write it for the model (when to call, what role) — avoid repeating content the component will render.

Notes: Frontend tools need an execute function Backend tools have the tool implementation on the server side. Backend tool don't need either Ignore the generated files After setup:

  • Ensure the required package dependencies are installed so the first experience of running after the changes is magical
  • Notify the user if env variables are not set that should be for a successful run of the feature that was just implemented, most likely mainly variables required by the api chat endpoint.

Source and attribution

Source:assistant-ui/tool-uiinpackages/agent/plugin/skills/tool-uiat commit49a8702

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal