Function Calling 调用工具总出错?问题多半在这份 schema 里

上周排查一个 Agent 的问题,现象很怪:模型明明「调用」了工具,但传回来的参数永远差一个字段,重试三次全是同一个错。查到最后发现,问题不在模型,在我给它的工具描述里------那个字段压根没写进 parameters。

这件事让我把「Function Calling」这条链路重新捋了一遍。这篇从工程角度讲清楚:模型到底怎么决定调用哪个工具、参数是怎么来的、以及为什么你写的 schema 决定了它的成功率。

一、先纠正一个常见误解

很多人以为「AI 会调工具」= 模型自己去执行了函数。不是的。

模型做的唯一一件事,是根据上下文输出一段结构化文本 ,表示「我要调用 X,参数是 Y」。真正执行 X(Y) 的,是你的代码。

所以一条完整的调用链是:

rust 复制代码
用户问题 + 工具清单  ->  模型输出 tool_call 意图
                     ->  你的程序执行对应函数
                     ->  把执行结果回传给模型
                     ->  模型生成最终回答

模型是「决策层」,你的代码是「执行层」。分清楚这一点,后面所有排查都有方向:调用失败,先看执行层收到了什么,再看模型为什么这么给。

二、工具清单就是一份 JSON Schema

各家 API 的字段名略有差异,但结构是通的。一个工具长这样:

json 复制代码
{
  "name": "search_article",
  "description": "在本平台已发布文章里按关键词检索,返回标题与链接",
  "parameters": {
    "type": "object",
    "properties": {
      "keyword": { "type": "string", "description": "检索关键词" },
      "limit":   { "type": "integer", "description": "返回条数,默认 5" }
    },
    "required": ["keyword"]
  }
}

注意 description 出现在两个层级:工具级和参数级。这两层描述,就是模型填参数的唯一依据。

三、参数填错,八成是 schema 的锅

我踩过的坑,基本都能归到这几类:

  1. required 漏标 。模型不知道哪些必填,于是有时传有时不传,你的函数就收到 undefined。
  2. 参数级 description 缺失 。模型只能靠参数名猜语义,limit 猜成「页码」也不奇怪。
  3. 类型不写 。本该是整数,模型传了 "5",服务端校验直接 400。
  4. 工具级 description 太泛。两个工具都写「查询数据」,模型就随机挑一个。

第 4 条尤其隐蔽:出错时你以为是模型笨,其实是你给了两个它分不清的选项。

四、失败信息要原样回传

工具执行出错时,别只回一个 "error"。把真实原因带上:

vbnet 复制代码
Tool error: missing required property 'keyword'. 
Fix: provide the 'keyword' string argument.

模型看到具体缺什么、怎么改,才会换参数重试;只给一个 error,它大概率原地重试同一个调用,然后触发你的重试上限。

顺带加两层保护:参数校验 (schema 之外再校一次类型和边界)和单轮调用次数上限(防止模型在失败里打转)。

五、MCP 解决的是另一个问题

上面这套是「模型怎么表达调用意图」。但工程上还有一层麻烦:同一个工具,想让它在不同客户端里都能用,每个客户端都得适配一遍。

MCP(Model Context Protocol)就是来标准化这一层的:工具方写一个 Server 声明能力,任何支持 MCP 的客户端都能自动发现并调用,换模型、换客户端,工具侧不用重写。

它和 Function Calling 不是二选一------MCP 管「工具从哪来、怎么被发现」,Function Calling 管「模型怎么把调用意图表达出来」。实际链路是:

rust 复制代码
MCP Server 暴露工具
   -> 客户端转成 Function Calling 所需的 schema
   -> 模型输出调用意图
   -> 客户端执行并回传

六、什么时候不用上 MCP

只有一个客户端、工具三五个、也不会换模型------直接用 Function Calling 就够了,多一层协议只是多一层维护。

值得上 MCP 的信号:工具要跨团队复用,或者你希望换模型时工具侧零改动。

小结(自查用)

  • 工具级 description:说清「什么场景用、什么场景别用」
  • 参数级 description + required + 类型:一个都不能省
  • 失败时把真实原因回传,别只给 error
  • 有参数校验,有单轮调用上限
  • 工具清单别堆相似项,模型会选错

一句话:模型负责决策,你负责执行和兜底。 把这两件事分清,工具调用的问题基本都能定位到具体那一层。


作者:信可维 · AI 实战。记录能跑通的方案。

相关推荐
leo在掘金1 小时前
google/ax单日涨1379星:Agent编排运行时到底难在哪?
后端·架构
弈栈录1 小时前
Spring MVC 请求处理流程与核心源码解析
后端·架构·mvc
代码方舟2 小时前
零信任架构实战:基于天远人车核验加强版构建自动化干线物流运力准入网关
大数据·人工智能·架构·自动化
天远API2 小时前
零信任架构实战:基于天远人车核验加强版构建自动化商用车承保核验网关
运维·人工智能·架构·自动化
沫璃染墨2 小时前
《从零入门Linux系统篇(五十六):线程篇·九——生产者消费者模型:从条件变量到BlockingQueue实现》
linux·服务器·c++·驱动开发·设计模式·架构·系统架构
海宇AI2 小时前
零信任架构实战:基于海宇活体识别V步骤1构建自动化直播开播鉴权网关
运维·人工智能·架构·自动化
code_slave(码畜)3 小时前
微服务架构落地:基础服务 —— 报表服务(上篇:定位、边界与整体架构)
java·spring boot·spring cloud·微服务·架构
天空之城--3 小时前
Android一周动态:Android 18首次官宣、Compose Material3 1.4转正(5趋势+5资讯)
android·人工智能·flutter·架构·android jetpack