「Agent Tool」什么是 Function Calling?原理是什么?
0 前言
本文内容整理自公众号「小林面试笔记」的文章 1. 什么是 Function Calling?原理是什么?,用于记录与总结 AI Agent 工具调用相关的核心面试知识点。
「什么是 Function Calling?原理是什么?」,可以这样作答:
Function Calling 是一套让大模型与外部工具协作的标准机制:开发者先用 JSON schema 把每个工具的功能、参数要求描述清楚,随对话一起传给模型;模型判断需要调用工具时,不输出自然语言,而是直接输出一段结构化的 tool_calls JSON——声明「我要调哪个函数、参数填什么」;真正执行这段 JSON 的是开发者写的宿主代码,它拿到函数名和参数去调 API、查数据库,再把结果以
role: "tool"的消息回填到对话;模型看到结果后,生成最终答案。整个流程的本质是「两轮对话 + 中间执行」:第一轮,模型说「我需要工具帮忙」;中间,代码替它执行;第二轮,模型拿到执行结果给出答案。模型通过
finish_reason为tool_calls明确表达「需要工具帮助」,这是宿主代码决定是否执行的开关。这套机制最核心的设计原则只有一句话:模型全程只做决策,执行一律由宿主代码完成。模型负责判断「该不该调、调哪个、参数填什么」,代码负责真正跑起来——职责分得清清楚楚。
现在几乎所有主流大模型产品都是这套机制的落地应用:ChatGPT 网页版的「联网搜索」「画图」按钮,Cursor 的 Agent 帮你读文件、跑测试,Claude Code 的命令行工具调用……用户看到的是「模型在干活」,本质上都是「模型输出结构化的调用意图 → 宿主程序执行 → 结果回填」的闭环。
1 背景:Function Calling 解决了什么问题
先回答一个问题:为什么需要 Function Calling?直接让模型说一句「帮我查一下北京的天气」、代码自己解析意图,不行吗?
早期的方法正是这个思路:模型用自然语言表达意图,开发者写一堆 if/else 去解析。问题在于自然语言没有固定格式——「帮我查一下北京的天气」「北京现在多少度」「查查北京天气」说的是同一件事,写法却千变万化,if/else 稍微没覆盖到就失配;就算匹配上了,参数也很难可靠地抽取出来。这种方案又脆弱又难维护,换个说法就挂,根本无法标准化。

Function Calling 的关键改进只有一点:让模型直接输出结构化的 JSON,而不是自然语言。模型判断需要工具时,输出「函数名 + 参数」这种一眼就能解析的结构,代码按固定格式提取即可——准确率更高、格式统一,工具调用第一次有了标准答案。

这个机制由 OpenAI 于 2023 年推出,如今 Claude、Gemini、Qwen 等主流模型均已原生支持,成了大模型产品的事实标准。
2 三个角色:把 Function Calling 理解成一场任务委托
Function Calling 看起来复杂,把它理解成公司里的一场「任务委托」就清晰了——整个过程有三个角色:

- 开发者 = HR(招聘专员):为每个工具写一份「职位说明书」——JSON schema,说清楚工具是干什么的、需要什么参数。模型怎么认识工具?全靠这份说明书,它从不「见过」你的代码;
- 模型 = 经理(决策者):读完全部职位说明书,结合用户问题判断「该派谁去干」,决定调哪个工具、参数填什么,然后下达指令;
- 代码 = 员工(执行者):真正动手干活的人——调用函数、访问网络、查询数据库,然后把结果汇报回来。
这里藏着最常见的误区:很多人以为模型能「自己」访问网络、执行代码。模型面前没有浏览器,也没有代码执行器——它无权直接访问任何外部资源,所有实际动作都是宿主代码替它完成的。这也是整个机制最重要的一句话:
模型只做决策,执行交给代码。
3 工具定义:JSON schema 的每个字段都有含义
工具在模型眼里长什么样?看一个标准的工具定义(以天气查询为例):
1 | |
每个字段都有讲究:
name(工具的名字):唯一标识,模型在tool_calls里就是靠它点名要哪个工具;description(工具的说明):模型判断「该不该用、怎么用」的核心依据,也是这道题的常考点,下文展开;parameters(参数结构):用type/properties描述每个参数,required声明必填项,enum限定可选值;参数自己的description也要写清格式、示例值和限制条件。
模型判断的依据,全靠 description。 如果描述写得含糊,比如只写「获取天气」,模型就可能在不合适的场景硬调用——用户问「广州适合穿什么衣服」,它可能直接拿 get_weather 的天气数据当答案;写清楚一点,声明「查询指定城市的实时天气,包含气温、天气状况、风向风速,仅支持中国大陆城市」,模型才知道工具的边界在哪里、什么情况该用、什么情况不该用。

一句话记住:工具描述写得越清楚,模型越不会「瞎猜」。description 是写给模型看的「说明书」,不是写给同事看的注释,值得花心思打磨。
4 完整调用流程:两轮对话 + 中间执行
把前面的角色和定义串起来,一次完整的工具调用就是「两轮对话 + 中间执行」的闭环:

第一轮:模型「申请调工具」。 宿主代码把工具列表(tools)和用户问题一起发给模型。模型判断需要工具时,不回答你的问题,而是输出一个特殊响应:finish_reason: "tool_calls",并在 tool_calls 里给出要调的函数名和参数。finish_reason 就是模型递给代码的信号——「我要工具帮忙,请执行」。注意,这一轮模型是说了话但没给答案,答案要等执行完才有。
中间执行:代码干活。 宿主代码解析 tool_calls,拿到函数名和参数,执行对应的函数。这一步模型完全不参与,纯粹是你的程序在跑——这就是「模型决策、代码执行」的落地点。
第二轮:结果回填,模型给答案。 代码把执行结果以 role: "tool" 的消息塞回对话历史,并带上 tool_call_id 与第一轮的调用一一对应;然后再次调用模型,模型结合工具结果,最终给出自然语言答案。

配套的 Python 示例(OpenAI SDK 的经典写法):
1 | |
如果某个环节出错——比如工具执行时报错,把错误信息同样以 role: "tool" 回填,模型就能「看到」错误、调整参数重试,或在回答里如实说明。这是工程上最通用的容错手法。
5 并行工具调用:一次响应,多个工具
上面的例子一次只调一个工具,但现实问题常常要同时拿好几份信息:「北京和上海今天的天气分别怎么样?」每个城市都要调一次 get_weather。
Function Calling 对此有原生支持:一个响应里可以返回多个 tool_calls。模型一次性输出北京、上海两个城市的调用请求,宿主代码并行执行两个函数,再把两份结果一次性回填,模型生成最终答案。

收益很直观:如果串行处理,每调一个工具就要经历「发消息 → 等模型 → 执行」一整轮,两个工具要两轮对话;并行把多轮压缩成一轮对话 + 并行执行,工具越多节省越明显。实现上不过是拿到多个 tool_calls 后用 asyncio.gather 或线程池同时跑,再统一回填。
但并行不是无条件成立的——有依赖关系的工具必须串行。典型例子:「先查订单号,再根据订单号查物流」。第二步的输入依赖第一步的输出,模型没法同时输出两个调用,它会分两轮:第一轮先调「查订单」的工具,拿到订单号后,第二轮再输出「查物流」的调用。

一句话:无依赖的工具大胆并行,有依赖的乖乖排队。模型会自己判断什么时候能并行、什么时候必须分轮。
6 面试总结
回答「什么是 Function Calling」这道题,先避开两个经典误区:
| 误区 | 正解 |
|---|---|
| 模型能「自己」访问网络、执行代码 | 模型只输出结构化的调用请求,从不亲自执行;执行者永远是宿主代码 |
| Function Calling 与解析自然语言的土办法是一回事 | 关键区别在于模型直接输出结构化 JSON,工具调用因此有了统一标准 |
再按这四点组织答案,基本就稳了:
- 工具定义用 JSON schema,其中
description是模型判断「该不该调、怎么调」的核心依据,写清楚才不会瞎猜; - 运行时是「两轮对话 + 中间执行」的闭环:第一轮模型输出
tool_calls,宿主代码执行,第二轮role: "tool"回填后模型给出答案; finish_reason为tool_calls是模型明确表达「需要工具帮助」的信号;- 一次可返回多个
tool_calls,无依赖的工具并行执行,有依赖的分轮串行。
再背熟那句分工原则——「模型只做决策、代码负责执行」,把职责边界讲清楚,是最能体现对机制理解深度的加分项。
追问预案:
- 「
tool_choice的取值有什么区别?」——auto让模型自由判断;none禁止调用工具;required强制本次必须调工具;指定某个函数名则强制调用那个工具。 - 「Function Calling 和 ReAct 是什么关系?」——ReAct 是「思考 → 行动 → 观察」的循环范式,Function Calling 恰好是「行动」环节的标准实现:模型思考后输出结构化的调用请求(行动),执行结果回填(观察)。这也是为什么说工具调用是 Agent 的「手」——没有它,Agent 只会想、不会做。
- 「工具执行出错怎么办?」——把错误信息以
role: "tool"回填,模型能看到报错、调整参数重试或如实说明,不要直接中断流程。
参考
- 1. 什么是 Function Calling ?原理是什么? | 小林面试笔记
- 6. ReAct、Plan-and-Execute、Reflection 三种范式有什么核心区别? | 小林面试笔记(相关:工具调用与 ReAct 的关系)
本文图片均来源于公众号「小林面试笔记」,版权归原作者所有。