Tool Call UI

Tool Call UI 是前端展示 Agent 工具调用状态的组件,包括调用中、成功、失败、需要审批等状态的可视化。它让用户知道 Agent 正在做什么。

#type / concept #status / evergreen #tech / frontend #tech / ai

[!info] related notes

Tool Call UI

一句话定义

Tool Call UI 是前端展示 Agent 工具调用状态的组件。它不只是显示一行文字,而是要让用户清楚地看到:Agent 在调用什么工具、传了什么参数、执行了多久、结果是什么。

它解决什么问题

Agent 在执行过程中会调用各种工具(搜索、查询数据库、执行代码等)。如果 UI 不展示这些信息:

  • 用户不知道 Agent 在干什么(只看到一个 loading 动画)
  • 用户不知道 Agent 为什么做出某个决策
  • 工具执行失败时用户看不到原因
  • 需要审批时用户看不到具体操作内容

核心原理

工具调用的状态流转

tool_call_start → running → tool_call_result (成功)
                          → error (失败)
                          → timeout (超时)
                          → waiting_approval (等待审批)

Tool Call Card 的信息层次

┌─────────────────────────────────────────┐
│ 🔧 搜索知识库                    2.3s   │
│                                         │
│ 参数:                                   │
│   query: "膝关节不稳定常见原因"          │
│                                         │
│ 结果:                                   │
│   找到 3 条相关知识...                   │
│                                         │
│ [查看详情] [重试]                        │
└─────────────────────────────────────────┘
层次内容重要性
工具名称 + 状态”搜索知识库 ✅“必须
耗时”2.3s”推荐
参数摘要关键参数推荐
结果摘要简要结果推荐
完整详情折叠查看可选

典型工程实现

基础 Tool Call Card

function ToolCallCard({ toolCall }: { toolCall: ToolCall }) {
  const [expanded, setExpanded] = useState(false);

  return (
    <div className={`tool-call-card ${toolCall.status}`}>
      <div className="tool-call-header">
        <ToolIcon name={toolCall.name} />
        <span className="tool-name">{formatToolName(toolCall.name)}</span>
        <ToolStatusBadge status={toolCall.status} />
        {toolCall.duration && (
          <span className="duration">{toolCall.duration}ms</span>
        )}
      </div>

      <div className="tool-call-params">
        <code>{JSON.stringify(toolCall.arguments, null, 2)}</code>
      </div>

      {toolCall.status === 'done' && (
        <div className="tool-call-result">
          <span className="result-summary">{summarizeResult(toolCall.result)}</span>
          <button onClick={() => setExpanded(!expanded)}>
            {expanded ? '收起' : '查看详情'}
          </button>
          {expanded && (
            <pre>{JSON.stringify(toolCall.result, null, 2)}</pre>
          )}
        </div>
      )}

      {toolCall.status === 'error' && (
        <div className="tool-call-error">
          <span>❌ {toolCall.error}</span>
          <button onClick={() => retryToolCall(toolCall)}>重试</button>
        </div>
      )}
    </div>
  );
}

不同工具的视觉差异化

function ToolIcon({ name }: { name: string }) {
  const icons: Record<string, string> = {
    search_knowledge: '🔍',
    query_database: '🗄️',
    execute_code: '💻',
    call_api: '🌐',
    read_file: '📄',
    write_file: '✏️',
  };
  return <span>{icons[name] || '🔧'}</span>;
}

常见设计模式

1. 折叠式卡片

默认显示工具名称和状态,点击展开参数和结果。

2. 时间线式

多个工具调用按时间线排列,形成 Agent 的执行轨迹。

3. 嵌入式渲染

工具结果直接嵌入消息流中(如搜索结果卡片、图表)。

4. 生成式 UI (Generative UI)

assistant-ui 的特性:工具调用直接渲染为自定义 React 组件。

// assistant-ui 的 Generative UI 模式
const runtime = useChatRuntime({
  tools: {
    show_chart: {
      description: '展示图表',
      parameters: z.object({ data: z.array(z.number()) }),
      render: ({ data }) => <Chart data={data} />,
    },
  },
});

常见坑

  1. 只显示 loading 动画: 用户不知道 Agent 在做什么
  2. 参数显示为原始 JSON: 没有格式化,难以阅读
  3. 结果太长直接显示: 应该摘要 + 折叠
  4. 错误信息太技术化: “JSON parse error at line 3” 对用户没意义
  5. 不做超时提示: 工具执行很久时用户不知道是卡了还是在处理

和其他概念的关系

  • vs Human Approval UI: Approval UI 是 Tool Call UI 的审批变体
  • vs Tool Call Start: 事件格式,Tool Call UI 是渲染组件
  • vs Chat UI: Tool Call UI 是 Chat UI 的子组件
  • vs [[assistant-ui|assistant-ui]]: assistant-ui 的 Generative UI 是 Tool Call UI 的高级形态

参考资料

创建于 2026/6/30 更新于 2026/7/15