Tool Calling(工具调用):大模型是如何调用外部工具的?
更新: 10/15/2026字数: 0 字 时长: 0 分钟
当我们使用 AI 编程工具时,只需要输入一句话:“帮我读取项目中的 package.json,检查依赖是否存在问题。”
随后,AI 就可能自动读取文件、分析依赖、执行命令,甚至根据检查结果修改代码。
但大模型本身只是一个根据输入生成输出的模型。它为什么能够读取本地文件?为什么能够执行终端命令?它生成的内容又是如何变成真正的操作的?
这背后有一项非常关键的技术:Tool Calling(工具调用)。
Tool Calling 让大模型不仅能够生成文本,还能够通过应用程序提供的工具与外部系统交互。它是 AI Agent、AI 编程助手、智能客服和自动化工作流的重要基础。
本文将从实际开发场景出发,讲清楚 Tool Calling 的工作原理、执行流程,以及如何使用 TypeScript 实现一个简化的工具调用系统。
一、什么是 Tool Calling?
Tool Calling,通常翻译为“工具调用”,指的是应用程序向大模型提供可用工具的定义,让模型根据用户需求决定是否请求调用某个工具,再由应用程序执行工具并将结果返回给模型。
这里有一个非常重要的区别:
大模型负责提出工具调用请求,真正执行工具的通常是承载大模型的应用程序或 Agent Runtime。
例如,我们可以向模型提供一个 getWeather 工具,告诉它这个工具的用途、参数类型和调用方式。
当用户询问“北京今天的天气怎么样”时,模型可能返回一个结构化调用请求:
{
"name": "getWeather",
"arguments": {
"city": "北京"
}
}这并不意味着大模型已经查询了天气。它只是根据工具定义和用户问题,判断应该请求调用 getWeather。
接下来,应用程序接收到请求,找到对应的工具实现,执行查询,再将天气结果交还给模型。
因此,完整的工具调用至少包含两个不同的动作:
- 模型决策:选择工具,并生成符合要求的参数。
- 程序执行:验证请求、调用真实工具、返回执行结果。
如果没有后面的执行程序,即使模型生成了看起来完全正确的工具调用请求,也不会自动产生外部操作。
二、Tool Calling 的完整执行流程
理解 Tool Calling 最好的方式,就是看一次真实的调用过程。
假设我们正在开发一个 AI 助手,希望它能够读取项目文件。用户提出需求:
帮我读取
package.json,告诉我项目使用了哪些依赖。
为了实现这个功能,我们需要给 AI 提供一个读取文件的工具。
2.1 整体执行流程
① 用户提出需求
读取 package.json,分析项目依赖
② 应用程序向模型提供工具定义
工具名称、用途、参数结构
③ 大模型决定调用工具
生成 readFile 的调用请求
④ Agent Runtime 执行工具
校验参数、检查权限、读取文件
⑤ 工具结果返回模型
将文件内容加入对话上下文
⑥ 大模型生成最终回答总结项目依赖并回复用户
这就是一次典型的 Tool Calling 流程。
需要注意,工具定义通常会在模型请求中提供,而不是等模型决定调用工具后才临时告诉它有哪些工具可用。实际执行过程中,应用程序还需要根据所使用的模型 API,正确处理工具调用标识、参数和工具结果。
2.2 第一步:向模型注册工具
假设我们要提供一个 readFile 工具,可以先定义它的名称、用途和参数:
const toolDefinition = {
name: "readFile",
description: "读取项目工作区内的文本文件",
parameters: {
type: "object",
properties: {
path: {
type: "string",
description: "需要读取的相对文件路径",
},
},
required: ["path"],
additionalProperties: false,
},
};这个定义告诉模型:
- 工具名称是
readFile。 - 工具用于读取项目文件。
- 调用时需要提供
path参数。 path必须是字符串。
这里的 toolDefinition 只是一个示意性的工具描述对象。真实项目中,通常需要将工具转换成模型 API 所要求的格式,例如特定的 JSON Schema 结构。
还要注意:工具定义不是工具实现。
它只描述工具能够做什么,并没有真正读取文件。
2.3 第二步:模型生成工具调用请求
应用程序将用户问题和工具定义发送给支持 Tool Calling 的模型。
模型可能返回类似这样的结构:
{
"tool_calls": [
{
"id": "call_001",
"name": "readFile",
"arguments": {
"path": "package.json"
}
}
]
}这里有几个重要信息:
| 字段 | 作用 |
|---|---|
id | 标识本次工具调用,便于匹配执行结果 |
name | 指定需要调用的工具 |
arguments | 提供工具需要的参数 |
这一步的本质是模型根据上下文生成结构化数据,而不是直接操作文件系统。
模型可能一次请求调用一个工具,也可能在支持相应能力的情况下请求调用多个工具。
此外,模型也可能判断不需要调用工具,直接生成普通文本回答。
2.4 第三步:应用程序执行工具
收到调用请求后,应用程序需要找到对应的工具实现。
例如,使用 Node.js 读取文件:
import { readFile } from "node:fs/promises";
async function readProjectFile(
projectRoot: string,
relativePath: string,
): Promise<string> {
// 这里只展示基本的路径检查,生产环境需要更完整的安全校验。
if (
relativePath.startsWith("/") ||
relativePath.includes("..")
) {
throw new Error("不允许访问该路径");
}
const targetPath = `${projectRoot}/${relativePath}`;
return readFile(targetPath, "utf8");
}这段代码才是真正执行文件读取的程序。
在实际的 AI Agent 中,调用执行前还应完成以下检查:
- 确认工具已注册,禁止调用未授权的工具。
- 校验参数类型和必填字段。
- 将目标路径解析到指定工作区,并防止通过路径穿越或符号链接访问未授权文件。
- 根据当前权限判断是否允许执行。
- 调用真实的文件读取接口,并处理异常。
上面的示例为了讲解原理而进行了简化,不应直接作为生产环境中的安全文件访问实现。
2.5 第四步:将执行结果返回模型
假设文件读取成功,程序得到以下内容:
{
"name": "my-app",
"dependencies": {
"react": "^19.0.0",
"vite": "^6.0.0"
}
}应用程序会把这份结果作为工具执行结果,关联到之前的工具调用,并再次发送给模型。
模型拿到真实的文件内容后,就可以回答:
这个项目使用了 React 19 和 Vite 6。React 用于构建用户界面,Vite 用于开发服务器和项目构建。
至此,一次完整的工具调用结束。
需要强调的是,真实的工具结果通常需要遵循对应 API 的消息格式,并与工具调用 ID 正确匹配,不能只把结果作为一条普通用户消息随意拼接。
三、Tool Calling 背后的三个关键角色
了解完整流程之后,可以进一步拆解 Tool Calling 的三个核心角色。
3.1 大模型:决定调用什么工具
大模型主要负责理解用户需求、分析上下文,并选择合适的工具和参数。
例如:
- 用户要求查询天气,选择天气查询工具。
- 用户要求读取代码,选择文件读取工具。
- 用户要求检查项目,选择终端执行或代码检查工具。
但是,模型的选择并不一定正确。它可能选错工具、生成无效参数,或者在信息不足时做出不合理判断。
因此,不能把模型生成的工具调用请求直接当作可信的执行指令。
3.2 Agent Runtime:调度和管理工具
Agent Runtime 可以理解为 AI Agent 的运行环境和调度层。
它通常负责:
- 向模型提供可用工具。
- 接收模型生成的工具调用请求。
- 校验工具名称和参数。
- 执行权限检查。
- 调用实际工具实现。
- 将执行结果交还模型。
- 管理多轮调用、超时和错误处理。
例如,模型请求执行 readFile,Runtime 就需要根据工具名称找到相应实现,而不是让模型任意指定一段程序直接运行。
3.3 工具实现:真正与外部系统交互
工具实现才是真正执行操作的部分。
它可以是一个普通的 TypeScript 函数,也可以是数据库客户端、HTTP 请求封装、终端命令执行器,或者远程服务提供的接口。
| 工具 | 典型实现 | 实际作用 |
|---|---|---|
| 文件读取 | Node.js 文件 API | 读取文本文件 |
| 文件写入 | Node.js 文件 API | 创建或修改文件 |
| 数据库查询 | 数据库驱动 | 执行 SQL 查询 |
| HTTP 请求 | fetch 或 HTTP 客户端 | 请求外部 API |
| 终端执行 | child_process 等 | 启动系统进程执行命令 |
这里要区分工具的实现与底层执行主体。例如,Node.js 可以发起文件写入,但最终的文件系统操作由操作系统提供的能力完成;数据库工具可以发送 SQL,但实际查询由数据库服务处理。
大模型负责决定,Runtime 负责调度,工具实现负责执行,底层系统负责完成实际操作。
四、使用 TypeScript 实现一个简易 Tool Calling 系统
理解原理后,我们可以尝试自己实现一个简化的工具调度系统。
为了避免绑定特定模型厂商,下面只实现工具注册、参数检查和执行逻辑。模型 API 的请求与响应格式则通过前面介绍的接口进行对接。
4.1 定义工具类型
首先,定义统一的工具接口:
type Tool = {
name: string;
description: string;
execute: (
args: Record<string, unknown>,
) => Promise<string>;
};每个工具都包含三个部分:
name:工具名称。description:工具用途说明。execute:实际执行函数。
4.2 注册工具
假设我们要实现一个简单的加法工具:
const tools: Tool[] = [
{
name: "add",
description: "计算两个数字的和",
async execute(args) {
const a = args.a;
const b = args.b;
if (
typeof a !== "number" ||
typeof b !== "number" ||
!Number.isFinite(a) ||
!Number.isFinite(b)
) {
throw new Error("参数必须是有效数字");
}
return String(a + b);
},
},
];这里的工具并不需要大模型参与计算。模型只需要判断什么时候调用 add,并提供 a 和 b 两个参数。
真正的计算由 TypeScript 函数完成。
4.3 根据模型请求执行工具
接下来,实现一个简单的工具分发函数:
async function executeTool(
name: string,
args: Record<string, unknown>,
): Promise<string> {
const tool = tools.find(
(item) => item.name === name,
);
if (!tool) {
throw new Error(`未知工具:${name}`);
}
return tool.execute(args);
}当模型请求调用:
const result = await executeTool("add", {
a: 10,
b: 20,
});
console.log(result);程序会输出:
30这就是 Tool Calling 的核心执行逻辑:根据工具名称找到对应实现,再将参数传递给执行函数。
当然,这个示例只是最小实现。真实系统还需要结合模型 API 的工具调用协议、JSON Schema 校验、权限管理、超时控制和异常处理等能力。
五、Tool Calling 和 Function Calling 有什么区别?
在阅读大模型相关技术资料时,你可能还会遇到 Function Calling 这个术语。
两者在很多场景下表达的是相近的概念,但具体含义取决于使用的平台和框架。
Function Calling 通常强调模型请求调用某个函数;Tool Calling 则经常作为更广泛的工具调用概念使用。
工具不一定只是一个普通函数,它还可以是:
- 一个外部 HTTP API。
- 一个数据库查询接口。
- 一个 MCP Server 提供的工具。
- 一个用于执行命令的受控程序。
- 一个远程服务提供的业务能力。
需要注意,具体平台可能会把函数调用也统一归类为工具调用,因此不能简单地认为两者在所有 API 中都有严格、统一的定义。
对于应用开发者来说,更值得关注的是工具调用协议、参数格式、执行机制和权限控制,而不只是名称。
六、Tool Calling 和 MCP 有什么关系?
Tool Calling 解决的是模型如何提出工具调用请求,以及应用程序如何围绕这些请求完成执行的问题。
而 MCP(Model Context Protocol)主要解决的是 AI 应用如何以相对统一的协议接入外部工具和上下文资源。
可以简单理解为:
- Tool Calling:模型决定要调用什么工具,以及传递什么参数。
- MCP:为 AI 应用连接外部工具和上下文资源提供标准化协议。
- Agent Runtime:负责协调模型调用、工具执行和结果反馈。
例如,一个 MCP Server 可以提供查询数据库的工具。AI 应用通过 MCP 获取工具定义,再把适合模型调用的工具信息提供给模型。
当模型请求调用数据库工具时,应用程序会根据具体集成方式,将请求转发给对应的工具执行端,再把结果返回模型。
MCP 并不取代 Tool Calling,二者可以配合使用;但 Tool Calling 也不要求必须通过 MCP 实现,应用程序完全可以直接注册和执行本地工具。
七、为什么 Tool Calling 必须配合权限控制?
如果一个 AI Agent 只能执行加法,风险通常比较低。
但如果它可以读取文件、修改代码、执行终端命令、访问数据库,工具调用就可能影响真实系统。
例如,模型可能生成一个删除文件的请求,或者尝试执行具有破坏性的命令。
即使模型的意图是合理的,也不能保证生成的参数一定安全。因此,生产环境中的工具系统需要明确的安全边界。
7.1 工具白名单
只允许调用已经注册且获得授权的工具。
不能因为模型返回了一个名为 deleteProductionDatabase 的工具请求,就动态创建或执行对应操作。
7.2 参数校验
不能完全相信模型提供的参数。
例如,文件路径必须经过规范化和访问范围检查;SQL 查询需要遵循应用程序的授权规则;终端命令不能仅凭字符串看起来正常就直接执行。
7.3 最小权限原则
工具只能获得完成任务所必需的权限。
例如,代码分析工具可以只读访问项目目录,而代码修改工具才具有指定工作区的写入权限。生产环境操作则可以要求更严格的审批。
7.4 高风险操作需要人工确认
删除文件、修改生产数据库、发布服务等操作,可以根据风险等级要求用户确认。
真正可靠的安全控制必须由执行环境强制实施,而不能只依靠提示词要求模型不要做危险的事情。
八、总结
Tool Calling 是 AI Agent 与外部世界交互的重要基础。
它让大模型能够根据用户需求选择工具、生成参数,并通过应用程序执行真实操作。结合 Agent Loop,模型还可以在获取工具执行结果后继续分析和行动,从而完成更复杂的任务。
理解 Tool Calling,可以记住这条核心链路:
用户提出需求 → 模型请求调用工具 → Runtime 校验并执行 → 工具返回结果 → 模型继续处理。
当 AI 能够读取文件、修改代码、查询数据库或者执行命令时,背后通常都离不开类似的工具调用机制。
但工具调用本身并不意味着模型拥有无限的系统权限。它能执行什么操作,最终取决于应用程序注册了哪些工具、执行环境授予了哪些权限,以及底层系统允许它做什么。
掌握这一机制之后,就可以继续深入研究 Agent Loop、MCP,以及 AI Coding Agent 如何利用工具读取、修改和验证项目代码。