Tool Calling 前端怎么接:工具进度、错误回传、权限边界
2026/7/22 5:21:15 网站建设 项目流程

《AI 前端实战》第 4/8 篇
上篇:Streaming UI 工程化
下篇预告:生成式 UI(JSON Schema → React)

第 2~3 篇解决了「模型会说话,而且说的过程体验还行」。
第 4 篇进入分水岭:模型开始调用工具

前端此时不再只是对话框,而要当「调度台」——展示进度、回收错误、守住权限。

你将学到

  • Tool Calling 的前端数据流
  • 工具进度组件怎么设计
  • 失败重试与 Human-in-the-loop
  • 权限白名单怎么落地
  • 一个双工具 Demo 的结构

一、先看数据流(前端视角)

用户输入 → 模型流式输出(可能含 tool_call) → 前端识别 tool_call,展示「运行中」 → 前端/后端执行工具(建议后端执行) → tool_result 回灌模型 → 模型继续生成最终回答

关键点:

  1. tool_call 不是最终答案,只是中间事件
  2. UI 要用parts模型,而不是一条纯文本气泡硬拼接
  3. 工具执行尽量在服务端,前端负责状态与确认

承接第 3 篇的消息模型:

type ChatPart = | { type: "text"; text: string } | { type: "tool"; id: string; name: string; args?: unknown; status: "pending" | "running" | "done" | "error" | "cancelled"; output?: string; error?: string; };

二、工具进度组件:用户要看见「它在干什么」

最少展示 4 个信息:

字段例子
工具名searchDocs
状态运行中 / 成功 / 失败
关键参数q=退款规则(注意脱敏)
结果摘要「找到 3 条文档」或错误原因

示意:

function ToolCard({ part }: { part: Extract<ChatPart, { type: "tool" }> }) { return ( <div className="rounded-lg border p-3 text-sm"> <div className="font-medium">工具:{part.name}</div> <div>状态:{part.status}</div> {part.error && <div className="text-red-500">{part.error}</div>} {part.output && <pre className="mt-2 overflow-auto">{part.output}</pre>} </div> ); }

体验原则:

  • 运行中可取消(若业务允许)
  • 成功默认折叠详情,失败默认展开
  • 不要把敏感参数(token、手机号)明文甩在 UI

三、错误回传:失败也是给模型的上下文

工具失败时,前端/网关至少要回传结构化错误:

{ "tool_call_id": "call_123", "ok": false, "error_code": "TIMEOUT", "error_message": "searchDocs timed out after 8s" }

然后让模型决定:换参数重试、换工具、或向用户道歉并给建议。

前端侧注意:

  1. 区分「工具失败」和「模型生成失败」
  2. 同一tool_call_id只更新一个 part,避免裂成多条
  3. 自动重试要有上限,并在 UI 显示「第 2/3 次重试」

四、权限边界:默认不信任模型

生产环境建议三级:

级别例子策略
L0 只读自动搜文档、查天气可自动执行
L1 低风险写入创建草稿可自动或二次确认
L2 高风险删数据、转账、发生产必须人工确认

前端确认框示例逻辑:

async function maybeRunTool(tool: ToolCall) { const level = permissionOf(tool.name); if (level === "L2") { const ok = await askUserConfirm(tool); if (!ok) return { ok: false, error_code: "USER_DENIED" }; } return executeTool(tool); }

白名单应来自服务端配置,前端只做展示与确认,不能只靠前端拦截

五、Human-in-the-loop:把人嵌进环里,而不是事后救火

适合打断确认的时机:

  • 参数看起来危险(批量删除、对外发送)
  • 模型连续两次工具失败
  • 费用敏感操作(大额 API 调用)

UI 上给三个明确动作:

  1. 允许执行
  2. 修改参数后再执行
  3. 拒绝并让模型换方案

这比「全自动」更慢一点,但能上线。

六、双工具 Demo(结构即可)

目标:用户问「北京天气怎么样,并写进笔记草稿」。

工具:

  1. getWeather(city)
  2. saveNote(title, content)

推荐状态序:

text(思考/开场) → tool(getWeather, running) → tool(getWeather, done) → text(简述天气) → tool(saveNote, pending_confirm) // L1/L2 → 用户确认 → tool(saveNote, done) → text(最终回复)

前端只要保证:每个 tool part 可独立更新;确认动作绑定到具体tool.id

七、三个高频坑

坑 1:把 tool 结果直接当最终气泡

用户会看到原始 JSON。应回灌模型,再生成可读回答;或对结果做摘要展示。

坑 2:前端直接拿着模型参数去打内网接口

容易变成 SSRF / 越权。工具执行放 BFF,前端只传tool_call_id与用户确认结果。

坑 3:停止生成后工具还在跑

停止要同时:abort 模型流 + 取消进行中的工具请求(能取消的才取消)+ UI 标cancelled

八、和本系列前后篇的关系

  • 第 3 篇:消息合并与重连,给 tool parts 打底
  • 第 4 篇:Tool Calling UI 与权限
  • 第 5 篇:生成式 UI——工具不只返回文本,还可返回界面描述

若你做的是 Agent 产品,这一篇是「能不能上线」的门槛之一。

小结

Tool Calling 前端三件事:

  1. 进度可见:用户知道模型在调用什么
  2. 错误可回传:失败成为下一轮上下文,而不是白屏
  3. 权限可阻断:高风险必须人确认

把对话框升级成调度台,你才算跨过 L2 → L3。


下篇预告:《AI 前端实战》第 5/8 篇
生成式 UI 实战:用 JSON Schema + React 动态渲染 AI 界面。

系列导航:
1 能力地图 · 2 流式 Chat · 3 Streaming 工程化

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询