17-Tools工具调用
17 - Tools 工具调用
本章课程目标:
- 理解 Tool(工具)、Tool Calling(工具调用)、Function Calling(函数调用) 分别是什么,建立“模型负责决策,程序负责执行”这条最核心的分工认知。
- 掌握使用
@tool装饰器定义 LangChain 工具,会配合 Pydantic 编写参数 schema,并能看懂name、description、args、tool_calls、ToolMessage这些关键对象。 - 跑通并理解本章全部案例:基础加法工具、Pydantic 参数 schema、天气查询工具、天气助手完整链路,为后续 记忆与对话历史、Agent 智能体、MCP 模型上下文协议 打基础。
学习建议: 学工具调用时先守住边界:模型负责判断要不要调用工具和填参数,程序负责真正执行工具并把结果交回去。读本章可以按 @tool、bind_tools、tool_calls、ToolMessage、业务闭环这条线走。Pydantic 不是装饰,它是在帮工具参数变成一份更可靠的契约。
官方文档与资源:详见 工具导航与参考资料索引 - 工具调用、MCP与智能体。
1、Tools 简介
1.1 定义
Tool(工具),是给大模型准备的一项外部能力。它本质上通常就是一个可调用函数,只不过我们把它包装成模型能理解的形式,让模型知道:
- 这个工具叫什么
- 这个工具是干什么的
- 这个工具接收哪些参数
Tool Calling(工具调用) 或 Function Calling(函数调用),说的是:模型在回答过程中,不直接给最终自然语言,而是先输出“我想调用某个工具,并附带参数”这一结构化意图。
然后要特别记住一条最重要的分工:
- 模型负责决定:要不要调用工具、调用哪个工具、传什么参数
- 程序负责执行:真正去调用函数 / API / 数据库 / 业务服务,并把结果再送回模型
所以从工程角度看,Tool 不是“模型自己突然学会调用外部系统”,而是我们把外部能力以受控方式开放给模型使用。
一句话定义: Tool 是外部能力本身,Tool Calling 是模型发起使用这项能力的过程。
术语约定: 为了减少后续章节的切换成本,本教程后文默认把这层机制统称为 Tool Calling;如果引用 OpenAI 或其他平台文档时出现 Function Calling,本质上仍然是同一层问题的不同叫法。
1.2 Tools 的作用
如果没有工具,大模型虽然会“说”,但它能做的事情仍然非常有限。它擅长语言理解、信息组织、总结改写、解释说明,但它并不能天然替你完成真实世界里的查询和操作。
最典型的限制包括:
- 不能稳定访问实时数据,比如最新天气、实时股价、今天的订单状态
- 不能直接操作外部系统,比如查数据库、发 HTTP 请求、读文件、调企业内部接口
- 不能保证计算与执行完全准确,比如复杂计算、严格表单提交、支付下单、状态变更
这也是为什么在真实项目里,几乎所有“真正有业务价值”的 LLM 应用,最后都会走到 Tools:
- 智能客服要查订单、查物流、查售后状态
- 企业助手要查知识库、查数据库、查工单系统
- 数据分析助手要跑 SQL、读报表、调统计接口
- 生活类助手要查天气、查地图、查航班、查日程

图意说明: 界面中用户询问「今天北京天气」,在未启用「联网搜索」等外部能力时,模型无法给出实时数据,只能建议去气象网站或开启联网搜索。该图用于说明:没有接入工具/插件时,模型再强也拿不到实时世界状态,与后文通过 Tool 调用天气 API 形成对照。
入门阶段可先把握一个基本判断:没有 Tool,大模型主要是在“说”;有了 Tool,它才开始能“做”。
1.3 Tool、Tool Calling、Agent 三者关系
这三者要先分清,因为后面学 Agent 时很多人都会把它们混在一起。
| 概念 | 它是什么 | 核心职责 |
|---|---|---|
| Tool | 一个被封装好的外部能力 | 负责“做事” |
| Tool Calling / Function Calling | 模型输出结构化调用意图的机制 | 负责“发起调用请求” |
| Agent | 会推理、会规划、会多步决策的智能体 | 负责“决定什么时候调用、调用几次、按什么顺序调用” |
可以把它们理解成这样:
- Tool 像工具箱里的“螺丝刀、扳手、计算器、天气接口”
- Tool Calling 像“我现在决定要用哪把工具,并说出参数”
- Agent 像“有判断能力的工人或调度者”,它会自己决定先用哪个工具、后用哪个工具、要不要继续调用
所以本章的重点,是先把 “工具本身” 和 “单轮/手动工具调用链路” 学明白。到了 第 21 章 Agent 智能体,你再去理解“让模型自己循环地、多步地调用工具”,就会轻松很多。
1.4 本章在项目中的位置
本章对应仓库中的 案例与源码-2-LangChain框架/08-tools 目录,整体学习路径非常清晰:
| 文件 | 作用 | 建议学习顺序 |
|---|---|---|
Tool_AddNumberTool.py |
最基础的 @tool 用法 |
先看 |
PydanticDemo.py |
先单独理解 Pydantic 校验与转换 | 再看 |
Tool_AddNumberToolPro.py |
给工具加上 args_schema |
接着看 |
QueryWeatherTool.py |
把真实 API 封装成 Tool | 再往后看 |
LLMQueryWeatherDemo.py |
把“模型 + 工具 + 解析 + 输出”串成闭环 | 最后看 |
本章不是零散介绍几个 API,而是围绕一个问题展开:
我们怎样把一个普通 Python 函数,逐步变成“可被模型正确理解、可被程序安全执行、可真正服务业务场景”的工具能力。
2、工具调用的工作方式
2.1 核心主线
只要先抓住一条主线,本章后面几乎所有 API 都会变得很好理解:
- 用户提出问题
- 程序把“用户消息 + 工具定义”一起发给模型
- 模型判断是否需要调用工具
- 如果需要,模型返回
tool_calls - 程序根据
tool_calls真正执行工具 - 程序把工具结果再放回消息流
- 模型基于工具结果生成最终自然语言回复
这就是工具调用的完整闭环。

小知识:泳道图 vs 普通流程图(面试题)
上图为泳道图(Swimlane diagram),按角色/系统分栏表示「谁在什么阶段做什么」。
- 普通流程图:只表示步骤的先后顺序和分支/判断,不区分「谁」执行哪一步;适合单角色、单系统内的流程(如算法步骤、单一业务线)。
- 泳道图(Swimlane diagram):按角色/部门/系统划分泳道,每个步骤落在对应责任方的泳道里,一眼看出「谁做啥」;适合多角色协作、跨部门/跨系统流程。
- 何时用泳道图:流程涉及多个责任主体(用户、模型、应用程序、第三方服务等)、需要明确责任边界与交接点时用泳道图。例如工具调用(用户 → 模型 → 你的代码 → 模型)、审批流、跨系统对接等。
如果你看过 第 11 章 和 第 13 章,这里会看到一条连续的消息主线:
- 第 11 章讲的是模型返回
AIMessage - 第 13 章讲的是消息流里有
ToolMessage - 第 17 章就是把这两件事真正接起来
也就是说,Tool Calling 不是脱离消息机制另起炉灶,它本质上仍然发生在消息流之中。
2.2 模型到底看到了什么
你可能会问:模型为什么知道“该调用天气工具,而不是直接胡编一个天气答案”?
原因是:当你使用 bind_tools(...) 把工具绑定给模型时,请求里除了用户问题,还会带上工具定义信息。根据 LangChain 和 OpenAI 官方文档,这些信息至少包括:
- 工具名称:例如
get_weather - 工具描述:也就是 docstring 或手动提供的 description
- 参数 schema:例如参数名、类型、字段说明
模型看到的并不是“一个黑盒函数”,而是“一个带名字、带用途说明、带参数规则的结构化能力描述”。这也是为什么工具描述写得好不好,会直接影响工具调用效果:模型不是靠读你的函数体来理解工具,而主要是靠 name、description、args_schema 来推断“什么时候该用、应该怎么传参数”。
2.3 程序主要做了什么
模型会输出工具调用意图,但模型不会替你执行工具。真正执行工具的一定是你的应用代码。
这一步通常包括:
- 读取模型返回的
tool_calls - 找到对应工具
- 取出参数
- 执行 Python 函数、HTTP 请求、数据库查询或其他业务逻辑
- 把结果重新回填给模型
这一点在实际项目里特别重要,因为它意味着:
- 权限控制在你手里
- 是否真的允许调用某个工具,在你手里
- 参数要不要做二次校验,在你手里
- 工具结果要不要脱敏、限流、重试,也在你手里
所以工具调用从来不是“模型直接操作你的系统”,而是模型提出请求,应用代码审核并执行。
2.4 tool_calls、AIMessage、ToolMessage 三者关系
这三个对象是最容易混淆、但又最关键的一组概念。
| 对象 | 它出现在哪一轮 | 作用 |
|---|---|---|
AIMessage.tool_calls |
模型决定要调用工具时 | 表示“模型想调用哪个工具、参数是什么” |
| 工具执行结果 | 程序执行工具后 | 表示“真实运行后的结果” |
ToolMessage |
把工具结果送回模型时 | 表示“这是某个工具执行后的返回消息” |
先建立一个非常实用的理解:
AIMessage.tool_calls是模型的请求ToolMessage是程序的回执
这和现实世界里“发起请求 → 执行操作 → 返回结果”很像。
如果一次回复里有多个工具调用,ToolMessage 还需要通过 tool_call_id 对应回前面的某一个 tool_call,这样模型和运行时才知道“这条工具结果是回答哪一次工具请求的”。
在 LangChain 官方更通用的讲法里,经常会直接展示:
- 模型返回
AIMessage(tool_calls=[...]) - 程序执行工具
- 程序构造
ToolMessage - 再把这些消息一起送回模型
而本课程当前案例为了更适合初学者理解,也保留了一种更直观的教学路径:通过输出解析器把工具参数取出来,然后手动执行工具,再把结果交给下一条 LCEL 链去整理自然语言。
这两种写法不矛盾,只是教学层次不同:一个适合看清过程,一个更贴近通用消息流。
2.5 什么时候不需要工具
不是所有问题都必须上 Tool。
如果用户只是问:
- “什么是 LangChain?”
- “请解释一下 Python 装饰器”
- “帮我总结这段文本”
这类问题模型本身就可以回答,此时直接 Prompt → Model → Parser 往往已经足够。
通常在下面几类场景,Tool 的价值才会明显体现出来:需要实时数据;需要访问外部系统;需要高确定性执行;需要把模型输出落到真实动作上。
这一点也很符合真实项目经验:Tool 不是为了“显得高级”而加,而是为了补足模型本身做不到或不可靠的那部分能力。
3、自定义 Tool:从最简单的工具开始
3.1 使用 @tool 装饰器
在 LangChain 里,最简单的工具定义方式就是使用 @tool 装饰器。
如果你第一次接触装饰器,不必把它理解得过于复杂。对本章而言,可先把握:装饰器的作用,是在不改函数核心逻辑的前提下,给函数额外加上一层“框架可识别的能力”。
放到这里,@tool 做的事情就是:
- 把一个普通 Python 函数包装成 LangChain Tool
- 让它具备
name、description、args等元信息 - 让它能够被模型或 Agent 识别并调用
LangChain 官方文档也明确强调:最简单的创建工具方式,就是使用 @tool 装饰器;默认情况下,函数 docstring 会成为工具描述。

所以先记住一句最重要的话:@tool 的意义,不是把函数“变复杂”,而是把函数“变成模型看得懂的工具”。
3.2 基础案例:加法工具
从教学上说,先别急着上天气、数据库、搜索引擎。最适合入门的,反而是一个最简单的数学工具,因为它能把重点都暴露出来。
【案例源码】案例与源码-2-LangChain框架/08-tools/Tool_AddNumberTool.py
这个案例最值得看懂的,不是“加法”本身,而是这三件事:
- 普通函数经过
@tool后就成了 Tool - Tool 可以直接通过
invoke(...)执行 - Tool 会自动暴露名称、描述、参数结构
也就是说,从这一步开始,你就已经把“Python 函数”变成了“模型可用能力”。
3.3 Tool 常用属性
你在实际开发中,经常会看到下面几个属性:
| 属性 | 作用 | 初学阶段怎么理解 |
|---|---|---|
name |
工具名 | 模型要调用谁,首先看这个名字 |
description |
工具说明 | 模型判断“什么时候该用这个工具”的最重要依据 |
args |
参数结构 | 模型知道“应该传什么参数、参数是什么类型” |
return_direct |
是否直接把结果返回给用户 | 主要在 Agent 场景更常见 |
入门阶段最值得优先关注的是:
description决定模型是否容易选中这个工具args决定模型是否容易传对参数
所以从工程实践上说,定义 Tool 时最怕的不是“函数实现难”,而是:名字取得太随意,描述写得太模糊,参数定义不清楚。

3.4 工具描述的作用
很多人定义工具时,只写一句非常短的 docstring,比如“查天气”或“获取信息”。这样虽然勉强能跑,但在真实项目里通常不够好。更好的工具描述应该尽量让模型看懂三件事:
- 这个工具是干什么的
- 什么时候应该调用
- 关键参数应该怎么填
例如同样是天气工具:
- “查天气”
- “查询指定城市的当前天气,参数 loc 传城市英文名,如 Beijing、Shanghai”
显然后者更容易让模型在正确场景下调用,也更容易传对参数。
这也是为什么在项目里定义 Tool 时,通常不建议把 docstring 写得过于省略。Tool 描述不是给人随便看看,它本身就是模型决策的重要输入。
3.5 真实项目里的工具层
在真实项目里,Tool 一般不会只做“玩具函数”,而往往是下面这些能力的轻量封装:
- 调第三方 API
- 调内部服务
- 查数据库
- 跑检索
- 执行某个稳定的业务动作
所以 Tool 层的工程价值非常高。它相当于把“模型”和“业务系统”之间,插入了一层可控的能力边界。
从架构上说,比较常见的组织方式是:
- Tool 层:暴露给模型的工具定义
- Service 层:真正的业务实现或 API 调用封装
- Model / Chain / Agent 层:负责决定何时调用工具
这样做的好处是:模型能力和业务实现解耦,后期替换模型、替换 API、替换调用策略都会更容易。
4、参数 schema:为什么要配合 Pydantic
4.1 为什么只写函数参数还不够
只靠 Python 函数签名,当然也能定义工具,但一旦进入真实项目,你很快就会遇到两个问题:参数类型和格式不够清晰;参数校验不够严格。
例如你只写:
1 | def add_number(a: int, b: int) -> int: |
这当然可以告诉模型“有两个整数参数”,但很多时候还不够。你还会希望表达:
- 这个参数具体是什么意思
- 有没有取值范围
- 是否允许为空
- 参数传错时怎样更清晰地报错
这就是 args_schema 和 Pydantic 出场的原因。
4.2 Pydantic 定义
Pydantic 是 Python 里非常常用的数据校验库,本质是把“参数结构、参数类型、字段说明、校验规则”统一收敛到一个模型类里。
在本章语境下,Pydantic 最重要的价值有两个:给程序看:做运行时校验和转换;给模型看:把参数 schema 描述得更清楚。
因此它适合用在 Tool 参数定义里。入门阶段可先把握一点:
Pydantic = 类型声明 + 自动校验 + 更清晰的参数说明。
4.3 入门案例
在把 Pydantic 放进 Tool 之前,先单独理解它本身会更容易。
【案例源码】案例与源码-2-LangChain框架/08-tools/PydanticDemo.py
这个案例最值得注意的是:
- Pydantic 会在实例化时做校验
- 合法输入可以自动转换
- 非法输入会明确报错
- 严格类型(如
StrictInt)可以避免“模糊转换”
这套能力放到 Tool 参数上会很有用,因为工具调用最怕“参数看起来像对,其实不对”。
4.4 加法工具的 Pydantic 版
理解了 Pydantic 之后,再看工具版就很顺了。
【案例源码】案例与源码-2-LangChain框架/08-tools/Tool_AddNumberToolPro.py
这个案例比基础版多出来的关键点,是:
- 用
BaseModel定义参数结构 - 用
Field(description=...)给参数写说明 - 用
@tool(args_schema=...)把参数模型绑定给工具
这样之后,模型看到的工具就不再只是“有两个整数参数”,而是会看到:
- 参数名是什么
- 参数类型是什么
- 参数用途是什么
这会显著提升模型生成正确参数的概率。
4.5 args_schema 的实践价值
对于玩具案例,直接写函数参数就够了;但只要进入真实项目,args_schema 往往是非常值得养成的习惯。
原因主要有三个:
- 更稳定:参数结构更清晰,模型不容易乱传
- 更安全:运行时可以做更严格校验
- 更可维护:工具定义本身就像一份小型接口文档
这和后端开发里写 DTO、写请求参数对象,其实是同一种工程思想。
你不是为了“显得规范”才写 schema,而是为了让:
- 模型更容易调用对
- 代码更容易排错
- 团队更容易协作
所以这一点意味着:Pydantic 让 Tool 从“能跑”走向“更像真正的接口定义”。
5、天气助手实战:把 Tool 跑成业务闭环
5.1 需求与准备
前面的加法工具是为了让你先看懂 Tool 的本质,但真正接近业务项目的,是天气助手这种“模型 + 工具 + 外部 API”的组合。
本节目标非常明确:让模型不只是“知道天气工具存在”,而是能在用户提问时,真的调用天气 API,再把结果整理成自然语言回复。
这个案例也非常贴近真实项目,因为现实里的 Tool 往往都不是本地纯函数,而更像这样:
- 调第三方接口
- 接收 JSON 数据
- 做必要加工
- 回到消息流或链路中继续生成最终答案
在运行本节案例前,你需要准备:
- OpenWeather API Key:在 OpenWeather API keys 页面 免费申请,将密钥写入项目根目录
.env(例如OPENWEATHER_API_KEY=你的密钥),并保证运行脚本时能加载到该变量。天气 HTTP API 总览见 OpenWeatherMap 文档。
版本说明: OpenWeather 的免费额度、可用产品、订阅档位和调用限制会随官方策略调整;本章只说明 API Key 获取和本地配置流程,具体额度与计费以当前 OpenWeather Pricing 页面和账号订阅页为准。

5.2 定义天气查询工具
先看天气工具本身,它负责把“真实 API 能力”包装成模型可用 Tool。
【案例源码】案例与源码-2-LangChain框架/08-tools/QueryWeatherTool.py
这个案例很适合帮助你建立两个关键认知:
第一,模型不会替你发 HTTP 请求。真正的请求逻辑仍然是你写的 httpx.get(...)。
第二,Tool 的意义不是替代业务实现,而是把业务实现包装成“模型可调用的接口”。
所以从这一步开始,你已经在做一件很像真实项目开发的事:
- 把业务能力封装成一个可复用函数
- 用 Tool 的方式暴露给模型
- 让模型只决定“何时调、怎么调”
5.3 模型绑定工具后,到底会发生什么
定义好 Tool 后,还需要把它交给模型,这通常通过 bind_tools(...) 完成。
LangChain 官方文档对这一点讲得很清楚:只有先把工具绑定给模型,后续模型调用时才有机会返回 tool_calls。
也就是说,bind_tools([get_weather]) 的含义不是“现在就执行工具”,而是:
把 get_weather 这项能力声明给模型,告诉它:你之后如果判断有必要,可以调用这个工具。

模型收到用户问题后,可能出现两种情况:不需要工具:直接返回自然语言答案;需要工具:返回 tool_calls。
一旦返回 tool_calls,就意味着模型在说:
我建议调用这个工具,参数如下,请你们应用程序去真正执行。
5.4 案例:天气助手完整链路
接下来就是本章最重要的业务闭环案例。
【案例源码】案例与源码-2-LangChain框架/08-tools/LLMQueryWeatherDemo.py
其中第 4 步「解析工具调用参数」依赖 JsonOutputKeyToolsParser,其角色是把模型输出中的工具调用片段解析成可执行的 Python 结构,详见 第 14 章 输出解析器。
这个案例的教学价值非常高,因为它把本章所有核心概念都串起来了:
- 定义 Tool
- 把 Tool 绑定给模型
- 让模型返回工具调用意图
- 解析工具调用参数
- 真正执行工具
- 把工具结果再加工成面向用户的自然语言回复
从链路角度看,它做了两件连续的事:
- 前半段:用户问题 → 模型判断 → 解析工具参数 → 调天气工具 → 得到天气 JSON
- 后半段:把天气 JSON 再交给模型 → 生成更自然的中文天气描述
这特别适合入门,因为它把“工具调用”和“最终回复生成”拆成了两个清晰阶段,而不是一下子混在一起。
注意:
LLMQueryWeatherDemo.py中通过from QueryWeatherTool import get_weather引用同目录天气工具,运行前请确保已配置OPENWEATHER_API_KEY,并尽量在项目根目录执行脚本,避免.env读取不到。
接口说明: 课程案例为了降低入门门槛,保留了
q=城市名的 Current Weather API 调用方式。生产项目如果需要更稳定的地理位置解析,建议先用 OpenWeather Geocoding API 将城市名、邮编或地址转换为经纬度,再用lat/lon调用天气接口。
5.5 课程案例写法与官方主线的关系
这一点很重要,建议单独说明清楚。本课程当前天气案例里,使用了:
bind_tools([get_weather])JsonOutputKeyToolsParser- 手动执行工具
- 再走一条输出链生成自然语言
而在 LangChain 官方主线和 OpenAI 官方 Function Calling 文档里,更常见的讲法通常是:
- 模型返回
AIMessage.tool_calls - 程序执行工具
- 把结果包装成
ToolMessage - 再把这组消息送回模型
两种写法的共同本质完全一样:
- 模型先发起工具调用意图
- 程序执行工具
- 结果再回到模型上下文里
课程案例之所以保留解析器写法,是因为它更直观:你能非常清楚地看到“模型产出参数 → 工具被调用 → 结果再被整理成人话”的每一个中间步骤。
所以建议你这样理解:
- 课程案例写法:更适合入门,看清链路
- 官方推荐写法:更贴近通用消息流和 Agent 扩展
这不是谁替代谁,而是同一条原理在不同教学层次上的两种展开方式。
6、从课程案例走向真实项目
6.1 Tool 在项目里通常怎么落位
如果你只写脚本,Tool 可以直接和业务逻辑写在一起;但如果是正式项目,更推荐把 Tool 看成“暴露给模型的接口层”。
一种比较常见、也比较适合团队协作的组织方式是:
- tool.py / tools/:定义给模型看的工具入口
- service.py / services/:写真实业务逻辑
- client.py / adapters/:封装第三方 API 或内部接口访问
- prompt / chain / agent 层:决定什么时候调用工具
这样做的好处是,后面无论你替换模型、替换 API 平台、替换 Agent 框架,都不会把整个工具层揉成一团。
6.2 设计 Tool 时,最值得重视的工程原则
对真实项目来说,Tool 定义得好不好,往往比“模型提示词写得漂不漂亮”更影响稳定性。
比较重要的原则包括:
- 职责单一:一个 Tool 最好只做一件清晰的事
- 输入明确:参数含义、类型、是否必填要说清楚
- 输出稳定:返回结构尽量稳定,不要时而返回字符串、时而返回复杂嵌套对象
- 异常可控:报错要能被程序捕捉和处理,不要直接把底层异常糊给用户
- 幂等与副作用隔离:能做查询就不要顺手做写入;涉及状态变更时,尽量拆成“先确认、再执行”的显式步骤
- 超时、重试与限流:外部 API 类 Tool 要设置超时、重试上限和频控,避免 Agent 在异常场景下反复调用
- 权限受控:涉及写操作、支付、删除、外呼等工具,需要额外设防
- 可观测:最好能记录调用日志、参数、耗时、错误信息,便于排障
这几点其实和普通后端接口设计的原则高度一致。
也正因为如此,Tool 本质上并不神秘,它只是把“后端能力”换了一种适合 LLM 使用的暴露方式。
6.3 本章与记忆、Agent、MCP 的关系
这一章在整个教程体系里,位置非常关键。
- 和 第 16 章记忆与对话历史 的关系:工具调用结果经常也要进入消息流,与对话历史一起参与后续推理
- 和 第 21 章Agent智能体 的关系:Agent 会在 Tool 基础上进一步解决“什么时候调、调几次、按什么顺序调”
- 和 第 20 章MCP模型上下文协议 的关系:MCP 解决的是“如何用标准协议把外部能力开放给模型”,可以看作更通用、更标准化的工具接入方式
一句话总结它们的关系:Tool 提供能力,Memory 提供上下文,Agent 负责决策,MCP 负责标准化接入。
所以本章虽然只讲 Tool,但它其实是后面很多高级能力的前置地基。
章节思考题:
一个函数是否应该暴露成 Tool,判断标准是什么?
参考思路: 看它是否需要模型根据自然语言判断调用时机和参数。如果是固定内部流程,普通代码即可;如果需要模型按上下文选择并填参,才值得暴露成 Tool。
工具描述写得差,会导致哪些真实问题?
参考思路: 模型可能不用工具、错用工具、参数填错、在不该执行时执行。模型看不到你的函数内部,只能依赖名称、描述和参数 schema 判断能力边界。
“模型负责决策,程序负责执行”在安全上意味着什么?
参考思路: 模型可以提出调用意图,但真正访问数据库、发消息、下单、删除数据必须由程序执行,并加权限、校验、确认、审计和失败处理。不能把副作用完全交给模型自由发挥。
有副作用的工具和只读工具,在设计上应该有什么不同?
参考思路: 只读工具重点是参数和结果质量;有副作用工具还要加二次确认、权限控制、幂等、回滚、日志和告警。风险越高,自动化程度越要谨慎。
本章小结:
- Tool 是什么:Tool 是暴露给模型的外部能力,本质上通常是被包装过的函数或接口;Tool Calling / Function Calling 则是模型输出调用意图的机制。
- 基本分工:模型负责“要不要调、调哪个、传什么参数”,程序负责“真正执行工具并回填结果”。
- 怎么定义 Tool:最简单的方式是使用
@tool装饰器。模型主要通过name、description、args_schema理解工具,所以工具名、工具说明、参数定义都非常关键。 - 为什么要配合 Pydantic:Pydantic 能让参数定义更清晰、校验更稳定、错误更容易定位,也更利于模型生成正确参数,是 Tool 从“能跑”走向“工程化”的重要一步。
- 和官方主线的关系:本课程为了教学直观,保留了
bind_tools + parser + 手动执行工具的展开方式;LangChain / OpenAI 官方则更常从AIMessage.tool_calls → ToolMessage的消息流角度讲解。两者本质一致,只是教学视角不同。
建议下一步: 先把本章 5 个案例全部跑一遍,重点观察“工具描述、参数 schema、模型返回 tool_calls、程序执行工具”这四个环节;然后继续学习 第 21 章 Agent 智能体,你会更容易理解为什么 Agent 的核心不是“多了几个 API”,而是在 Tool 基础上增加了自主决策与多步编排能力。