关于 tool-ui
Tool UI 是一项帮助项目集成工具交互界面组件的技能,涵盖组件安装及接入 assistant-ui Toolkit,并说明前端与后端工具的实现方式。
主要功能
- 01包含 25 种界面组件的目录
- 02AI 辅助或 shadcn 安装
- 03assistant-ui Toolkit 配置
- 04前端与后端工具模式
适用场景
- 01为工具工作流添加进度和计划视图
- 02展示引用、代码或数据可视化
- 03收集用户选择或审批
- 04在助手界面中呈现媒体内容
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ assistant-ui/ tool-ui --skill tool-ui安装后在 Claude Code 中输入/tool-ui确认已加载。
详细介绍
工具 UI
使用此技能,可快速从需求推进到可用的工具 UI 集成。
如果项目没有现有的聊天 UI/运行时,优先使用 assistant-ui。如果应用已有可用的运行时,则 assistant-ui 为可选项。
第 1 步:兼容性与 Doctor
读取用户项目中的 components.json 并验证:
components.json存在。
第 2 步:安装组件
从项目根目录运行安装命令
首选(AI 辅助集成):
npx tool-agent "integrate the <component> component"
使用下方目录中的组件专属提示词(例如:integrate the plan component for step-by-step task workflows with status tracking)。
替代方案(直接使用注册表):
npx shadcn@latest add @tool-ui/<component-id>
多个组件:
npx tool-agent "integrate the plan, progress-tracker, and approval-card components for planning flows"
或通过 shadcn 安装:
npx shadcn@latest add @tool-ui/plan @tool-ui/progress-tracker @tool-ui/approval-card
完整组件目录
全部 25 个 Tool UI 组件及其工具 Agent 提示词和 shadcn 安装命令:
进度
| 组件 | 描述 | 工具 Agent 提示词 | shadcn |
|---|---|---|---|
plan | 带状态跟踪的分步任务工作流 | integrate the plan component for step-by-step task workflows with status tracking | npx shadcn@latest add @tool-ui/plan |
progress-tracker | 为多步骤操作提供实时状态反馈 | integrate the progress tracker component for real-time status feedback on multi-step operations | npx shadcn@latest add @tool-ui/progress-tracker |
输入
| 组件 | 描述 | 工具 Agent 提示词 | shadcn |
|---|---|---|---|
option-list | 让用户从多个选项中进行选择 | integrate the option list component to let users select from multiple choices | npx shadcn@latest add @tool-ui/option-list |
parameter-slider | 数值参数调节控件 | integrate the parameter slider component for numeric parameter adjustment controls | npx shadcn@latest add @tool-ui/parameter-slider |
preferences-panel | 用户偏好设置紧凑面板 | integrate the preferences panel component for compact user settings | npx shadcn@latest add @tool-ui/preferences-panel |
question-flow | 带分支的多步骤引导式问题 | integrate the question flow component for multi-step guided questions with branching | npx shadcn@latest add @tool-ui/question-flow |
展示
| Component | Description | tool-agent prompt | shadcn |
|---|---|---|---|
citation | 显示带有来源归属信息的引用 | integrate the citation component to display source references with attribution | npx shadcn@latest add @tool-ui/citation |
item-carousel | 用于浏览集合的水平轮播 | integrate the item carousel component for horizontal browsing of collections | npx shadcn@latest add @tool-ui/item-carousel |
link-preview | 带有 Open Graph 数据的丰富链接预览 | integrate the link preview component for rich link previews with Open Graph data | npx shadcn@latest add @tool-ui/link-preview |
stats-display | 以可视化网格展示关键指标和 KPI | integrate the stats display component for key metrics and KPIs in a visual grid | npx shadcn@latest add @tool-ui/stats-display |
terminal | 显示命令行输出和日志 | integrate the terminal component to show command-line output and logs | npx shadcn@latest add @tool-ui/terminal |
weather-widget | 显示天气预报和天气状况 | integrate the weather widget component for weather display with forecasts and conditions | npx shadcn@latest add @tool-ui/weather-widget |
制品
| Component | Description | tool-agent prompt | shadcn |
|---|---|---|---|
chart | 使用交互式图表可视化数据(需要 recharts) | integrate the chart component to visualize data with interactive charts | npx shadcn@latest add @tool-ui/chart |
code-block | 显示带语法高亮的代码片段 | integrate the code block component for syntax-highlighted code snippets | npx shadcn@latest add @tool-ui/code-block |
code-diff | 使用带语法高亮的差异比较代码变更(需要 @pierre/diffs) | integrate the code diff component to compare code changes with syntax-highlighted diffs | npx shadcn@latest add @tool-ui/code-diff |
data-table | 在可排序表格中展示结构化数据 | integrate the data table component to present structured data in sortable tables | npx shadcn@latest add @tool-ui/data-table |
message-draft | 在发送前审核并批准消息 | integrate the message draft component to review and approve messages before sending | npx shadcn@latest add @tool-ui/message-draft |
instagram-post | 呈现 Instagram 帖子预览 | integrate the instagram post component to render Instagram post previews | npx shadcn@latest add @tool-ui/instagram-post |
linkedin-post | 呈现 LinkedIn 帖子预览 | integrate the linkedin post component to render LinkedIn post previews | npx shadcn@latest add @tool-ui/linkedin-post |
x-post | 呈现 X 帖子预览 | integrate the x post component to render X/Twitter post previews | npx shadcn@latest add @tool-ui/x-post |
确认
| Component | Description | tool-agent prompt | shadcn |
|---|---|---|---|
approval-card | 对 Agent 操作进行二元确认 | integrate the approval card component for binary confirmation of agent actions | npx shadcn@latest add @tool-ui/approval-card |
order-summary | 显示包含逐项定价的购买信息 | integrate the order summary component to display purchases with itemized pricing | npx shadcn@latest add @tool-ui/order-summary |
媒体
| Component | 描述 | tool-agent prompt | shadcn |
|---|---|---|---|
audio | 带封面图和元数据的音频播放 | integrate the audio component for audio playback with artwork and metadata | npx shadcn@latest add @tool-ui/audio |
image | 显示带元数据和署名的图像 | integrate the image component to display images with metadata and attribution | npx shadcn@latest add @tool-ui/image |
image-gallery | 带全屏灯箱查看器的瀑布流网格 | integrate the image gallery component with masonry grid and lightbox viewer | npx shadcn@latest add @tool-ui/image-gallery |
video | 带控件和海报图的视频播放 | integrate the video component for video playback with controls and poster | npx shadcn@latest add @tool-ui/video |
展示(地理地图)
| Component | 描述 | tool-agent prompt | shadcn |
|---|---|---|---|
geo-map | 显示地理定位实体和车队位置 | integrate the geo map component to display geolocated entities and fleet positions | npx shadcn@latest add @tool-ui/geo-map |
按使用场景安装示例
tool-agent(推荐):
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(直接安装):
npx shadcn@latest add @tool-ui/plan @tool-ui/progress-tracker @tool-ui/approval-card
npx shadcn@latest add @tool-ui/citation @tool-ui/link-preview @tool-ui/code-block @tool-ui/code-diff
npx shadcn@latest add @tool-ui/data-table @tool-ui/chart @tool-ui/stats-display
# npm i recharts # peer for chart
npx shadcn@latest add @tool-ui/image @tool-ui/image-gallery @tool-ui/video @tool-ui/audio
在代码库中设置工具包
安装组件后,通过 Toolkit 将它们接入 assistant-ui。本节介绍完整的设置流程:提供方、运行时、工具包文件和 ID 处理。
1. 提供方和运行时
创建一个助手封装组件,提供运行时、传输层和工具:
"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>
);
};
要点:
useChatRuntime+AssistantChatTransport:连接到聊天 API。Tools({ toolkit }):将工具定义和渲染器转发给模型。sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls:工具调用后自动继续(可选,但常用于工具密集型流程)。
2. 工具包文件结构
创建一个 toolkit.ts(或 toolkit.tsx),导出一个 Toolkit 对象。每个键都是一个工具名称;每个值都包含 type、description、parameters 和 render。
工具描述 — 始终为每个工具添加 description。描述何时调用该工具以及它承担什么角色,而不是描述可见内容。Tool UI 组件已经会向用户呈现有效负载(选项、计划、图表等);重复描述这些内容会显得多余。优先提供面向模型的指导(例如“提供一个供用户遵循的计划”或“让用户选择一个选项”),而不是复述内容(例如“显示带有标签和描述的选项列表”)。
-前端工具与后端工具
| - | 前端 | 后端 | |
|---|---|---|---|
| - | 实现方式 | 在浏览器中运行;用户交互通过 addResult 提交 | 工具实现在服务端;模型返回结果 |
| - | execute | 必需 — 在客户端运行工具 UI 工作流 | 不需要 |
| - | parameters | 必需(模型参数的架构) | 不使用;如果后端 LLM 通过 aisdk 实现,则改用 inputSchema |
| - | render | 必需(用于参数、状态、结果和 addResult 的 UI) | 必需(用于 result 的 UI) |
后端工具(模型返回结果;不需要用户输入):
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} />;
},
},
};
前端工具(模型发送参数;用户交互通过 addResult 提交):
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 路由(AI SDK)
当聊天 API 使用 AI SDK(streamText)时,使用 ai 中的 tool() 定义后端工具:
- 使用
inputSchema - 后端工具在服务端使用
execute;结果会流式传输,并通过工具包的render函数渲染
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 AssistantChatTransport
const 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. 以操作为中心与复合组件
| 模式 | 组件 | 用法 |
|---|---|---|
| 以操作为中心 | OptionList、ParameterSlider、PreferencesPanel、ApprovalCard | 直接连接 onAction 或 onConfirm/onCancel;无需 ToolUI 包装器。传入 choice={result} 以设置回执状态。 |
| 复合式 | OrderSummary、DataTable 等 | 使用 ToolUI + ToolUI.Surface + ToolUI.Actions 包装;使用 DecisionActions 或 LocalActions。 |
以操作为中心的示例(OptionList):
return (
<OptionList
{...parsed}
onAction={async (actionId, selection) => {
if (actionId === "confirm" || actionId === "cancel") {
await addResult?.(selection);
}
}}
/>
);
复合式示例(搭配 DecisionActions 的 OrderSummary):
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 使用内嵌操作;直接连接 onConfirm/onCancel:
return (
<ApprovalCard
{...parsed}
choice={
result === "approved" || result === "denied" ? result : parsed.choice
}
onConfirm={async () => addResult?.("approved")}
onCancel={async () => addResult?.("denied")}
/>
);
操作模型
工具 UI 使用两个操作界面,它们作为复合兄弟组件渲染在显示组件之外:
ToolUI.LocalActions:非关键副作用(导出、复制、打开链接)。处理函数不得调用addResult(...)。ToolUI.DecisionActions:会产生后果的选择,通过createDecisionResult(...)生成DecisionResult封装。提交回调会调用addResult(...)。
包含操作的显示组件的复合包装模式:
<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>
有三个组件是以操作为中心的例外 — 它们保留内嵌操作属性,而不是使用兄弟界面。这三个组件共用一个统一接口:
actions:由组件渲染的操作按钮。onAction(actionId, state):操作执行后运行,并接收操作后的状态。onBeforeAction(actionId, state):在操作运行前进行评估的守卫函数。
| 组件 | 传递给处理函数的状态类型 |
|---|---|
OptionList | OptionListSelection |
ParameterSlider | SliderValue[] |
PreferencesPanel | PreferencesValue |
使用复合模式的组件:CodeBlock、CodeDiff、Terminal、ProgressTracker。
上下文通过 createContext + use() 共享(React 19)。如果在 Root 之外使用子组件,它们会抛出异常。
回执和选择约定
具有结果的组件使用 choice 属性来呈现已确认/已完成状态:
| 组件 | choice 类型 | 值/形状 |
|---|---|---|
ApprovalCard | "approved" | "denied" | 字符串字面量 |
OptionList | string | string[] | 所选选项 ID |
OrderSummary | OrderDecision | { action: "confirm", orderId?, confirmedAt? } |
ProgressTracker | ToolUIReceipt | { outcome, summary, identifiers?, at }(共享类型) |
存在 choice 时,组件会以回执模式呈现——只读且不包含操作。
操作规则
- 安装能够满足需求的最少组件。
- 每个工具都必须有
description;应针对模型编写,说明何时调用以及承担什么角色,避免重复组件将要呈现的内容。
注意: 前端工具需要 execute 函数 后端工具的实现位于服务端。 后端工具两者都不需要 忽略生成的文件 设置完成后:
- 确保已安装所需的包依赖,让更改完成后的首次运行体验顺畅无阻
- 如果未设置成功运行刚实现功能所需的环境变量,请通知用户;这些通常主要是 API 聊天端点所需的变量。