第 9 章:工具调用 Tool Calling:让 AI 调用函数
本章目标
这一章让模型从“只会回答”变成“可以调用函数”。这是 Agent 的基础。
本章效果
工具 Agent 页面展示了最终回答和工具调用轨迹。演示模式会直接显示本地工具执行结果;真实模型模式下,模型会根据工具描述决定是否调用。

什么是工具调用
工具调用的核心是:你把可用函数告诉模型,模型根据用户问题决定是否调用。
例如用户问:
帮我算一下 499 元打 8 折是多少钱
模型可以调用:
calculate_discount({ price: 499, rate: 0.8 })
然后基于结果回答用户。
定义一个工具
import { tool } from "langchain";
import * as z from "zod";
export const calculateDiscount = tool(
({ price, rate }) => {
const result = price * rate;
return `折后价格是 ${result.toFixed(2)} 元`;
},
{
name: "calculate_discount",
description: "根据商品原价和折扣率计算折后价格",
schema: z.object({
price: z.number().describe("商品原价"),
rate: z.number().describe("折扣率,例如 0.8 表示八折")
})
}
);
工具名建议使用 snake_case,兼容性更好。
创建 Agent
import { createAgent } from "langchain";
import { createChatModel } from "@/lib/ai/model";
import { calculateDiscount } from "@/lib/ai/tools";
export async function createBusinessAgent() {
const model = await createChatModel();
return createAgent({
model,
tools: [calculateDiscount],
systemPrompt: "你是业务助手。需要计算时,优先调用工具。"
});
}
调用:
const agent = await createBusinessAgent();
const result = await agent.invoke({
messages: [
{
role: "user",
content: "499 元打 8 折是多少钱?"
}
]
});
工具调用适合什么
适合:
- 计算
- 查询数据库
- 调接口
- 搜索文档
- 获取实时数据
- 执行业务操作
不适合:
- 没有边界的自由操作
- 直接执行用户给出的任意代码
- 没权限控制的删除、支付、发消息等高风险动作
工具调用状态怎么展示
前端最好不要只显示“AI 正在思考”。更好的体验是展示工具状态:
正在调用价格计算工具...
已获得计算结果
正在生成回答...
后续可以结合事件流或自定义状态实现。
实战任务
完成:
- 定义
calculate_discount工具 - 创建
createBusinessAgent - 新增
/api/agent - 在页面上测试一次工具调用
常见坑
工具描述要具体。模型是否会正确调用工具,很大程度取决于工具名、描述和参数说明。
工具返回值不要太随意。返回给模型的信息要足够明确。
高风险工具必须加权限校验和二次确认。
本章小结
工具调用让模型具备执行能力。下一章会专门讲 Zod 参数设计,因为工具稳定性很大程度取决于参数 Schema。