做产品 PMaker
空格的键盘空格的键盘
Agent 与 Skill

工具调用

工具调用 | Agent 与 Skill | 做产品

工具调用

「它自己会调接口查数据」,这是对 Agent 最常见的误解。**模型一个接口也调不了。**它唯一能做的,是在回复里写出一段结构化的「请求」——剩下的全是你的代码。

你会遇到的现象

  • 以为给模型连上数据库,它就能自己查了

  • 模型调工具时参数给错,你不知道该怪谁

  • 不知道「工具列表」对模型意味着什么,随便塞了几十个进去

它其实不会调用

模型的一切行为都是「根据上下文,输出下一个 Token」。所谓工具调用,只是它在输出里写了一段特定格式的文字——通常是一段 JSON,写着「我要调用 query_order,参数是订单号 A1024」。

这句话写完之后,模型的工作就结束了。没有任何代码因为这句话而执行。真正把订单查出来、把邮件发出去、把库改掉的,是你写的执行代码——它看到模型输出的这段 JSON,解析它,调用对应的函数,再把结果作为一段「工具返回」放回上下文。

这就是「你把手借给它」的意思:**模型负责决定要干什么,你负责真的去干,并把它看到的结果还给它。**它永远只活在文字世界里。

一次调用长什么样

完整的流程是这样的:

**一、你把工具清单发给模型。**每个工具给三样东西:名字、参数结构(各参数的类型和含义)、一段说明(这个工具是干什么的、什么时候该用它)。说明写得好不好,直接决定模型会不会用对。

**二、模型在回答里输出调用请求。**格式由接口规范决定(OpenAI 风格、Anthropic 风格各有各的格式),但本质都一样:一段结构化文本。

**三、你的代码执行。**解析请求 → 校验参数 → 调用函数 → 捕获错误。

**四、结果返回。**把执行结果(成功的数据、或错误信息)拼成一段文字,连同原来的对话一起,再次发给模型。模型看到结果,继续思考下一步。

注意第四步:错误信息也一定要返回给模型。「查询失败:订单不存在」这句话要让它看到,它才知道换个参数重试,还是告诉用户查不到。很多 Agent 卡死,就是执行失败的结果没有回流。

紫色是模型做的,灰色是你的代码做的

你的代码 ① 发出工具清单 名字 · 参数 · 说明

模型 ② 写出调用请求 一段 JSON,仅此而已

你的代码 ③ 解析并执行 校验 · 调函数 · 捕错

你的代码 ④ 结果回流 写进上下文

模型看到结果,进入下一轮

两处最容易搞错

模型只出现在 ② 它一个接口也调不了,只会写出一段文字

④ 最常被漏掉:错误也要回流 失败结果没写回上下文,它就会原样重试到卡死

四个格子里有三个是你的代码。「模型自己会调接口」这句话,从第一步到最后一步都不成立——它写请求,你干活,你再把它该看到的还给它。

怎么设计工具清单

工具清单是给模型看的一份「说明书」,它的质量决定模型会不会正确伸手。三条经验:

**一、少而清楚,胜过多而全。**工具越多,模型越容易选错,占的上下文也越多。只放这次任务可能用到的。几十个工具塞进去,效果往往不如三个写清楚的。

二、说明里写「什么时候用、什么时候别用」。query_order:按订单号查询订单详情。仅当用户提供了订单号时使用;订单号通常形如 A 开头加数字。」——这样的说明比「查询订单」有用得多。

**三、参数名和类型要严谨。**模型会照抄你的参数名。给它 order_id 它就传 order_id,给它 id 它就传 id。含糊的命名会把错误一路带到执行层。

还有一点容易被忽略:**工具本身的稳定性。**你的函数改了签名,但模型还按旧的参数格式输出——请求就会失败。工具变更要有版本意识,或者干脆在代码里做参数容错。

三个坑

**一、以为工具是白送的。**每个工具都要你写执行逻辑、处理错误、考虑并发和超时。工具越多,你的工程债越多。

**二、忘了它是「你的」工具。**模型会调用你列出来的任何工具——包括有副作用的。该分级授权、加人工断点的地方,一定要加。见提示注入:外部数据可能诱骗模型去调不该调的工具。

**三、把工具结果当权威。**工具返回的数据也会出错、会过期、会来自不可信来源。模型拿到工具结果后同样可能基于错误数据一本正经地编。链路越长,越要在关键动作后做核验。

Agent 循环 工具调用是循环里「做」的那一步。

Skill 与 MCP 工具怎么组织、怎么批量接入,是这一层的进阶。

Agent 跑偏的三种形态 工具误用是跑偏的高频形态之一。