导语
大语言模型训练数据是静态的,无法获取实时信息(天气、股价),也无法访问私有业务数据(订单、库存)。工具使用(Tool Use)通过函数调用机制,让智能体与外部 API、数据库、代码执行器交互,突破训练数据限制,实现实时信息检索与业务系统集成。本文介绍工具定义、调用流程、安全实践与主流框架对比,适合需要构建生产级智能体的开发者与架构师。
TL;DR
- 核心:工具使用是智能体通过函数调用与外部系统交互的能力,包含工具定义、LLM 决策、函数调用生成、工具执行、结果返回与整合六个步骤。
- 价值:突破训练数据时间限制(实时信息)、访问私有数据(业务系统)、执行实际操作(代码、API)。
- 流程:定义工具描述 → LLM 判断是否需要 → 生成结构化调用(JSON)→ 执行函数 → 返回结果 → LLM 整合回复。
- 安全:输入验证、权限控制、沙箱执行(代码)、审计日志、速率限制。
- 框架:LangChain(自定义工具为主)、Google ADK(预置工具丰富)、CrewAI(多智能体协作)。
- 延伸:与提示链、路由、并行化配合使用,见《./01-提示链.md》《./02-路由.md》《./03-并行化.md》。
是什么:工具使用的核心定义
工具使用(Tool Use),也称函数调用(Function Calling),是智能体通过结构化函数调用机制与外部 API、数据库、服务交互,甚至执行代码,从而突破大语言模型训练数据局限,获取实时信息和执行实际操作的能力。
核心机制(六步流程):
1. 工具定义 → 向 LLM 描述工具的用途、名称和参数
2. LLM 决策 → 判断是否需要调用工具
3. 生成函数调用 → 输出结构化调用请求(JSON)
4. 工具执行 → 框架执行实际函数
5. 返回结果 → 工具输出返回给智能体
6. LLM 处理 → 整合结果生成最终回复
核心思想:工具是连接 LLM 推理能力与外部功能的桥梁。
可视化示意图:
图:工具使用设计模式 - 智能体通过函数调用与外部系统交互的完整流程
读图要点:工具定义、LLM 决策、函数调用生成、工具执行、结果返回与整合的闭环流程。
常见误解澄清:
- ❌ 工具调用就是 API 调用:工具调用更广义,包括 API、数据库、代码执行、其他智能体等。
- ❌ 所有任务都需要工具:简单问答、文本生成等无需工具,仅在需要实时数据或外部操作时使用。
- ❌ 工具调用会增加很多延迟:可通过并行调用、缓存结果、异步执行优化。
为什么:产生背景与适用场景
产生背景
大语言模型的局限性:
- 训练数据静态:无法获取最新信息(天气、新闻、股价)。
- 无法访问私有数据:公司数据库、用户订单、业务系统。
- 无法执行实际操作:无法调用 API、执行代码、操作文件系统。
工具使用解决了这些限制,让智能体具备“行动能力”。
适用场景
场景 1:实时信息检索
问题:LLM 训练数据静态,无法获取最新信息(如天气、股价、新闻)。
解决方案:
用户请求 → 智能体识别需要实时数据 → 调用天气/股票 API → 获取数据 → 格式化回复
价值:提供实时、准确的信息,突破训练数据时间限制。
实例:天气查询、新闻搜索、股票价格查询、汇率查询。
场景 2:业务系统交互
问题:无法访问私有数据(如公司数据库、用户订单、库存系统)。
解决方案:
用户查询 → 智能体调用业务 API(库存、订单、支付)→ 获取结构化数据 → 返回结果
价值:访问结构化业务数据,实现与现有系统的集成。
实例:电商库存查询、订单状态查询、支付处理、CRM 数据查询。
场景 3:代码执行与计算
问题:LLM 不擅长精确计算、代码执行、数据分析。
解决方案:
用户需求 → 智能体生成代码 → 调用代码执行器(沙箱)→ 执行并返回结果 → 解释结果
价值:执行复杂计算、数据分析、代码验证。
实例:数学计算、数据分析、代码调试、图表生成。
怎么做:工具定义与调用流程
工具定义清单
工具定义必须包含以下信息:
| 要素 | 说明 | 示例 |
|---|---|---|
| 名称 | 工具的唯一标识符 | <code>get_weather</code> |
| 功能描述 | 清晰说明工具用途,LLM 据此判断是否需要调用 | "获取指定城市的当前天气信息" |
| 参数列表 | 参数名称、类型、是否必填、描述 | <code>city: str</code>(必填,城市名称) |
| 返回格式 | 返回数据的结构和类型 | <code>{"temperature": 25, "condition": "晴"}</code> |
| 使用示例(推荐) | 帮助 LLM 理解调用方式 | <code>get_weather(city="北京")</code> |
| 错误情况(推荐) | 说明可能的错误和返回格式 | 城市不存在时返回 <code>{"error": "城市未找到"}</code> |
调用流程(可落地步骤)
步骤 1:定义工具
# LangChain 示例
from langchain.tools import tool
@tool
def get_weather(city: str) -> str:
"""获取指定城市的当前天气信息。
Args:
city: 城市名称,如"北京"、"上海"
Returns:
天气信息的 JSON 字符串,包含温度、天气状况
"""
# 实际调用天气 API
return json.dumps({"temperature": 25, "condition": "晴"})
说明:使用 <code>@tool</code> 装饰器定义工具,描述要清晰,参数类型要明确。
步骤 2:注册工具到智能体
# LangChain 示例
from langchain.agents import create_tool_calling_agent
agent = create_tool_calling_agent(
llm=llm,
tools=[get_weather, get_stock_price, query_database],
prompt=prompt
)
说明:将工具列表传递给智能体,LLM 会根据用户请求自动判断是否需要调用。
步骤 3:执行与结果处理
# LangChain 示例
result = agent.invoke({"input": "北京今天天气怎么样?"})
# LLM 自动判断需要调用 get_weather,执行后整合结果返回
说明:框架自动处理工具调用流程,开发者只需关注工具定义和结果处理。
安全实践清单
| 安全措施 | 说明 | 实施建议 |
|---|---|---|
| 输入验证 | 验证参数类型、范围、格式 | 使用 Pydantic 模型验证 |
| 权限控制 | 限制工具访问权限 | 基于用户角色、API Key 控制 |
| 沙箱执行 | 代码执行在隔离环境 | 使用 Docker 容器、资源限制 |
| 审计日志 | 记录所有工具调用 | 记录调用者、参数、结果、时间戳 |
| 速率限制 | 防止滥用和成本超支 | 限制调用频率、设置配额 |
对比与取舍:主流框架选型
框架对比表
| 框架 | 工具定义方式 | 核心组件 | 内置工具 | 适用场景 |
|---|---|---|---|---|
| LangChain | <code>@tool</code> 装饰器 | <code>create_tool_calling_agent</code>, <code>AgentExecutor</code> | 少量第三方集成 | 自定义工具为主,灵活度高 |
| Google ADK | <code>FunctionTool</code>, 预置工具 | <code>Agent.tools</code> | Google Search、代码执行、Vertex AI Search | Google 生态集成,企业级应用 |
| CrewAI | <code>@tool</code> 装饰器 | <code>Agent.tools</code>, <code>Crew</code> | 部分集成 | 多智能体协作场景 |
选型建议
选择 LangChain 如果:
- 需要高度自定义工具
- 使用多种第三方 API
- 需要精细控制调用流程
选择 Google ADK 如果:
- 使用 Google Cloud 服务
- 需要预置工具(搜索、代码执行)
- 企业级安全与合规要求
选择 CrewAI 如果:
- 构建多智能体协作系统
- 需要工具在智能体间共享
- 快速原型开发
常见错误与排错
典型坑位
| 问题 | 症状 | 识别方法 | 修复建议 |
|---|---|---|---|
| 工具描述不清晰 | LLM 不调用或错误调用工具 | 观察 LLM 是否识别到需要工具 | 完善工具描述,添加使用示例 |
| 参数类型错误 | 工具执行失败,返回类型错误 | 检查工具定义和实际调用参数 | 使用类型注解,添加参数验证 |
| 缺少错误处理 | 工具失败导致整个流程中断 | 查看错误日志 | 在工具中实现 try-catch,返回清晰错误信息 |
| 权限不足 | 工具调用被拒绝 | 检查 API Key、权限配置 | 配置正确的认证信息 |
| 速率限制 | 频繁调用被限流 | 观察调用频率和错误码 | 实现重试机制、速率限制 |
调试技巧
- 启用详细日志:记录工具调用请求、参数、结果。
- 测试工具独立:先单独测试工具,再集成到智能体。
- 检查工具描述:确保描述清晰,LLM 能理解何时调用。
- 验证参数格式:确保 LLM 生成的参数符合工具要求。
FAQ
Q1:LLM 如何知道何时调用工具?
A:LLM 根据工具描述和用户请求判断。描述越清晰,判断越准确。可以在 system prompt 中引导,例如:"当用户询问实时信息时,使用相应的工具获取数据。"
Q2:工具调用会增加延迟吗?
A:会。每次调用增加 1 次 API 请求 + 工具执行时间。可通过并行调用多个工具优化。
Q3:工具调用失败怎么办?
A:应在工具中实现错误处理,返回清晰的错误信息。LLM 可根据错误信息重试或告知用户。建议使用结构化错误格式,便于 LLM 理解。
Q4:能否调用多个工具?
A:可以。LLM 可以决定依次或并行调用多个工具。框架通常支持工具链(Tool Chaining)。
Q5:如何确保工具安全?
A:1) 输入验证和清洗;2) 权限控制;3) 沙箱执行(代码);4) 审计日志;5) 速率限制。
Q6:工具定义需要包含什么?
A:必须:名称、功能描述、参数列表(类型、必填/可选)。推荐:使用示例、返回格式、错误情况。
Q7:函数调用和工具调用有什么区别?
A:函数调用指调用预定义的代码函数;工具调用更广义,包括 API、数据库、其他智能体等。在智能体语境中,两者常互换使用。
Q8:Google ADK 有哪些特色工具?
A:Google Search(网络搜索)、代码执行器(沙箱 Python 执行)、Vertex AI Search(企业私有数据搜索)、Vertex Extensions(企业级 API 封装)。详见 Google ADK Tools 文档。
延伸阅读与引用
官方文档
- LangChain Tools:LangChain 框架的工具使用指南,包含工具定义、集成和最佳实践。
- Google ADK Tools:Google ADK 工具文档,介绍预置工具和自定义工具的使用方法。
- OpenAI Function Calling:OpenAI 函数调用机制详解,适用于使用 OpenAI 模型的场景。
- CrewAI Tools:CrewAI 多智能体框架的工具使用说明。
总结
工具使用是智能体突破训练数据限制、连接外部世界的核心能力。通过清晰的工具定义、安全的调用流程、合理的框架选型,可以构建稳定、可扩展的生产级智能体系统。