大模型只会聊天,不会办事——这是很多产品经理对 LLM 的第一印象,也是 Function Calling(函数调用,也常叫工具调用)要打破的那堵墙。学完这一课,你能回答三个问题:模型”调用工具”时到底发生了什么;一份工具定义由哪三部分组成、哪部分最影响调用准确率;工具报错时系统应该怎么兜底。文末还有一份”查订单状态”的工具 schema 全文,可以直接拿去和工程师对齐。
这一课不需要你写代码。你只要能读懂 JSON——就是接口文档里那种花括号加引号的结构化数据格式——就能跟上全部内容。它是第 4 课智能体入门的续篇:那一课我们说过”没有工具的智能体只能说、不能做”,现在就给它装上手脚。
先拆穿原理: 模型从头到尾没有执行任何函数
Function Calling 这个名字有很强的误导性。它听起来像是”模型去调用了一个函数”,仿佛模型伸出手按下了某个按钮。实际发生的事情朴素得多:
模型只是输出了一段 JSON,内容是”我想调用工具 X,参数是 Y”。真正去执行这个函数的,永远是你自己的系统。
拿餐厅打个比方。模型是坐在包间里的点菜顾问,它对着菜单(你提供的工具列表)说”来一份宫保鸡丁,微辣”。但它不进厨房、不掂勺,甚至不知道厨房今天有没有鸡肉。写菜单的是你,炒菜的是你的后端服务,把菜端回桌上(把执行结果回传给模型)的还是你。模型全程只做两件事:看菜单点菜,以及吃到菜之后发表评价(生成最终回答)。
这个认知对产品经理至关重要,因为它直接回答了三个高频疑问:
- “模型会不会乱操作我们的数据库?” 不会,除非你的系统拿到调用意图后不做任何校验就执行。风险在执行层,不在模型层。
- “调用失败算谁的锅?” 要分段看:参数生成错了是模型侧问题(通常是工具描述没写好),执行报错是你系统侧的问题。定位问题先分清是哪一段。
- “能不能限制它只做某些操作?” 能,而且这是白名单机制:不在工具清单里的操作,模型连”点菜”的资格都没有。
站内那篇Agent 的手脚:工具调用把这套机制放在智能体语境下讲过:Function Calling 就是让第 4 课那种”只能说”的智能体获得行动能力的标准方式。顺带一提,即使某个模型不原生支持这个特性,也可以靠提示词约定输出格式来模拟,社区里有过让不支持工具调用的模型兼容 Function Calling 的讨论——原理完全一样:让模型输出结构化的”调用意图”,你的系统解析后代为执行。
Schema 三件套: name、description、parameters
要让模型会点菜,你得先写好菜单。这份菜单就是工具的 schema(结构定义),核心只有三件套。
name: 工具的唯一标识
给系统看的,要求唯一、机器可读,一般用小写字母加下划线,比如 get_order_status。命名本身也要说人话:query_a3 这种名字模型猜不出用途,get_order_status 一眼就懂。模型选工具时,名字也是判断依据之一。
description: 写给模型看的”产品文案”
这是三件套里最被低估的一项。description 的质量直接决定调用准确率,因为模型完全靠这段文字判断”什么时候该用这个工具、什么时候不该用”。
写 description 的要领和写好的功能文案一致:
- 说清楚这个工具做什么、返回什么:”根据订单号查询订单当前状态、物流信息和预计送达时间”。
- 说清楚什么时候用:”当用户询问订单进度、快递到哪了、为什么还没发货时使用”。
- 必要时说清楚不做什么:”仅支持查询,不能修改或取消订单”。
如果模型频繁在该调用时不调用、或者不该调用时乱调用,第一件事不是怀疑模型能力,而是回头改 description。这和第 2 课提示词工程里的经验是同一条:与其堆形容词,不如把边界写明白。
parameters: 参数的结构化约束
用 JSON Schema(一种描述数据结构的通用规范)声明每个参数的名称、类型、是否必填、格式约束。每个参数也有自己的 description,同样影响模型填参的正确率。类型和格式约束能在系统侧拦住一大半”编出来的参数”。
产品经理未必要亲手写 schema,但你要能评审它——看完下面的动手环节,你手里就有一份评审清单了。
一次调用的时序: 从用户提问到最终回答
把一次带工具的对话拆开,是一个六步的往返:
- 用户提问:”我的订单 20260701-8841 到哪了?”
- 应用把问题和工具清单一起发给模型。注意:工具清单是每次请求都要随身携带的,模型不会”记住”你有哪些工具——第 1 课讲过,上下文窗口之外的东西模型一概不知道。
- 模型输出调用意图。它判断这个问题自己答不了,于是不生成正常回答,转而输出一段结构化数据:调用
get_order_status,参数{"order_id": "20260701-8841"}。 - 你的系统执行。应用解析这段 JSON,校验参数合法性,检查权限(这个用户有没有资格查这个订单?),然后调用真正的订单接口。
- 结果回填。把接口返回的数据(”运输中,预计明天送达”)作为一条新消息发回给模型。
- 模型生成最终回答。这时它才用自然语言组织答案:”您的订单正在运输中,预计明天送达。”
几个容易被忽略的点:
- 第 3 步和第 6 步是两次独立的模型调用,意味着两份 token 账单和两段延迟。如果一个任务要串联五个工具,就是至少六次模型往返。评估”AI 客服必须 3 秒内响应”这类需求时,这笔账要先算。
- 第 4 步是你的主场,也是你的责任。校验、鉴权、限流、日志都发生在这里。模型输出的参数只是”建议值”,不校验就直接执行,等于把生产系统的方向盘交给一个概率生成器。
- 第 5 步的结果同样占上下文窗口。工具一次返回一万行 JSON,窗口就被吃掉一大块,后面的对话质量跟着下降。让工具返回”够用的最少字段”是常见优化。
工程实现上这套往返还有流式传输等细节,感兴趣可以看站内模拟 OpenAI 的 Function Calling 流式调用的实战帖。产品层面,理解到”六步往返、两次计费”就够用了。
动手: 给”查订单状态”写一份工具 schema
下面是一份自产的示例,采用通用的 JSON Schema 风格(各家 API 对字段的组织方式略有差异,但 name/description/parameters 的骨架是共通的),你可以直接拿它当评审模板:
{
"name": "get_order_status",
"description": "根据订单号查询订单当前状态。返回订单状态(待支付/已发货/运输中/已签收/已取消)、最新物流节点和预计送达时间。当用户询问订单进度、快递位置、为什么还没收到货时使用。仅支持查询,不能修改、取消或催发订单。",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "订单号,格式为 8 位日期加 4 位序号,例如 20260701-8841。必须由用户明确提供,不得猜测或编造。",
"pattern": "^[0-9]{8}-[0-9]{4}$"
},
"include_logistics": {
"type": "boolean",
"description": "是否返回全部物流轨迹节点。默认 false,只返回最新一条。",
"default": false
}
},
"required": ["order_id"]
}
}
对着这份 schema,评审清单自然就出来了:
- description 是否覆盖”做什么、何时用、不做什么”三段?
- 每个参数是否有自己的说明和类型约束?
pattern这类格式校验能在源头拦掉大量错误参数。 - “必须由用户明确提供,不得猜测”这句写在参数描述里,是对抗模型瞎填参数的第一道防线;第二道防线永远是你系统里的校验代码。
- 必填列表是否最小化?必填项越多,模型越容易在信息不足时硬编一个值凑数。
把这份 JSON 拿到评审会上,业务方看 description 段就能确认能力边界,工程师看 parameters 段就能确认接口契约——一份文档同时服务两拨人,这正是工具 schema 的价值。
多工具、并行调用与报错处理
模型怎么在多个工具里做选择
真实产品不会只有一个工具。一个客服机器人可能同时挂着查订单、查物流、发优惠券、转人工四个工具。模型选择工具的依据只有两样:用户的问题,加上各工具的 description。所以当两个工具的描述语义重叠(”查订单”和”查订单详情”),误选率会明显上升。治理方法很直接:让每个工具的职责边界在文字上互斥——就像好的产品不该有两个入口做同一件事。
并行调用: 快,但要有兜底
用户一句话里包含多个可独立执行的请求时(”帮我查下订单 A 和订单 B 的物流”),支持并行调用的模型会一次输出多个调用意图,你的系统并发执行后统一回填,省掉多轮往返的延迟。但并行也引入了新的失败面:曾有中转接口出过并行函数调用集体失效的故障,只做并行、不做失败兜底的设计在生产环境撑不住。
工具报错了怎么办: 回喂模型,别吞掉
执行失败时最糟糕的两种处理:静默吞掉错误装作没发生,或者把原始报错直接甩给用户。正确姿势是把错误信息作为工具结果回喂给模型,比如回填一句”订单号不存在,请确认格式为 8 位日期加 4 位序号”。模型拿到这条信息后通常会自己纠错:换个参数重试、改用别的工具,或者礼貌地向用户追问。
生态里已经有人把”自动重试”做成基础设施,比如 Toolify 的自动重试机制。但重试不是万灵药:Claude Code 出过工具调用死循环,模型每次重试都复现同一个错误参数,越试越错。所以重试必须带上限(比如三次),超限就降级——转人工、或者给预设的兜底话术。
可靠性问题不分厂商:DeepSeek 在 OpenCode 中工具调用失效、Qwen3.7-Max 把幻觉误判为注入都是真实案例,甚至出现过 Claude Opus 在调用后”自曝失败”却照常输出结果的信任危机——这也是第 4 步的校验和日志不可省略的原因。工具调用的稳定性应当是模型选型的一等公民指标,社区已经有批量测试各模型工具调用支持度的开源工具,更多模型能力横向对比可以翻模型对比专题。
局限: 为什么学完 Function Calling 还要学 MCP
Function Calling 解决了”单个应用怎么接工具”,但留下两个结构性问题。
第一,各家 API 的定义格式不互通。 主流厂商的工具定义在字段组织和调用协议上各写各的(差异属于工程细节,骨架仍是三件套),你为 A 家模型写的工具接入层,换 B 家模型就要重写适配。工具有 N 个、要支持的模型有 M 家,集成工作量就是 M 乘 N。
第二,工具多了模型选不准。 几十个工具的 description 全塞进上下文,既烧 token,又拉低选择准确率——菜单印到十页纸,谁都会点错菜。
这两个问题催生了 MCP(Model Context Protocol):把工具接入标准化成统一协议,让 M 乘 N 变成 M 加 N。这是第 10 课的主题。先说结论:MCP 不是替代 Function Calling,而是给它修了高速公路——底层的”输出调用意图、系统执行、结果回填”机制原封不动。
产品视角: 工具清单就是产品能力清单
把视角拉回产品工作,Function Calling 给产品经理两个实打实的抓手。
能力边界第一次变得可评审
你的 AI 产品能做什么、不能做什么,不再是一句含糊的”看模型发挥”,而是一份可以逐行评审的工具列表。写 PRD 时,”AI 助手支持查订单、查物流、开发票”可以直接翻译成三个工具 schema,需求和实现之间第一次有了逐条对应的翻译关系。反过来也成立:砍掉一个工具就是明确下线一个能力,灰度一个工具就是灰度一个功能。AI Agent 专题归档里大量智能体产品的能力差异,本质上就是工具清单的差异;Claude Code 这类 AI 编程工具,剥开看也是”一个装满文件读写和命令执行工具的智能体”。
权限与审计是安全底线,不是可选项
工具是模型伸进真实系统的手,每一只手都要回答三个问题:
- 谁能用:工具要按用户身份鉴权。客服机器人查订单,只能查当前会话用户自己的订单,这个约束写在你的执行层,不能指望模型自觉。
- 能做多大的事:读操作和写操作分级。”查询订单”可以自动执行;”取消订单””退款”这类不可逆操作要加人工确认环节——在设计上就不给模型直通生产的通道。
- 事后能不能查:每一次调用意图、参数、执行结果全量留痕。出了客诉,你要能回放”那天模型为什么给这个用户发了优惠券”。
这三条不是工程师的自留地,而是产品经理必须写进需求文档的验收标准。调用成功率、误调率、重试率这些指标,也应该进你的产品数据看板——它们就是 AI 功能的健康度。
最后补一个应用视角:工具调用和第 7 课的 RAG 检索可以互相嵌套,比如用 System Prompt 与 Function Call 重构知识库检索,让模型像人一样”先决定查什么、再翻资料”。开源客户端也在快速跟进,Open WebUI 引入原生函数调用后工具生态明显活跃;甚至8G 显存的本地小模型也已经能跑工具调用。这个能力正在从 API 特性变成所有 AI 产品的标配,越早把工具清单管起来,越早占住主动权。本系列其他课程收录在 AI 产品经理专题。
相关阅读
- Agent 的手脚:工具调用
- 技术探讨:如何让不支持工具调用的模型兼容 Function Calling
- 推荐支持函数调用的 GPT API 方案
- Open WebUI 更新:支持原生函数调用,增强 AI 模型工具交互能力
- 开发者破解 AI 接口流式调用难题:如何正确模拟 OpenAI 的 Function Calling 与 MCP
FAQ
Function Calling、插件、智能体是一回事吗
三个层次。Function Calling 是底层机制:模型输出调用意图,系统负责执行。插件是把这套机制包装后的产品形态,用户感知到的是”多了个功能”。智能体则是在机制之上加了目标和循环——第 4 课讲的那种智能体,靠工具调用获得行动能力,靠循环决定下一步做什么。谈方案时先对齐说的是哪一层,能省很多口水。
模型会不会绕过工具清单执行危险操作
不会”绕过”,因为模型根本没有执行通道,它的全部输出都只是文本。真正的风险有两类:一是它生成了错误参数而你的系统不校验就执行;二是工具本身权限给得太大。所以安全建设的重心在执行层——参数校验、按用户鉴权、写操作加人工确认、全量审计日志,四样都不能省。
为什么模型有时该调用工具却直接编了个答案
最常见的原因是 description 没写清适用场景,模型判断”这个我自己能答”。其次是工具太多、描述语义重叠,模型选不准干脆不选。先改 description,再做工具瘦身;还不行,就在系统提示词里明确规则,比如”涉及订单信息必须调用工具查询,不得凭记忆回答”。
工具是不是接得越多越好
不是。每个工具的定义都占上下文窗口,工具越多,选择准确率越低、单次请求成本越高。经验做法是按场景分组、按需加载:一次请求只携带当前场景相关的工具子集。到第 10 课你会看到,MCP 在协议层面也给这个问题提供了新的组织方式。
不写代码的产品经理要参与到什么程度
至少三件事。一是评审每个工具的 description 和参数说明——这是文字活,不是代码活,而且直接决定调用准确率;二是定义权限分级,哪些工具自动执行、哪些必须人工确认;三是把调用成功率、误调率纳入产品看板,作为 AI 功能的核心健康指标。这三件事工程师替代不了你。
结语
Function Calling 把大模型从”会说”推到”会做”,但执行权和风险始终握在你的系统手里。写好每一段 description,管好工具清单与权限分级,就是产品经理在这件事上最大的杠杆。第 10 课我们把工具接入标准化:MCP。







