AI Agent 入门第四课:工具调用——给 Agent 装上"手",让它真正干活
# AI Agent 入门第四课:工具调用——给 Agent 装上”手”,让它真正干活

你有没有想过,为什么 ChatGPT 知道的东西那么多,却不能帮你查今天的天气?
这个问题困扰了我很久。后来我才搞明白:LLM 本质上是个”嘴”,它只能说话,不能做事。它的知识是训练时冻结的快照,不是实时的。而工具调用(Tool Use),就是给这张嘴装上一双手——让它不只能说”旧金山可能现在是早上”,而是能真的查出来告诉你”09:24 AM”。
LLM 的”嘴”和”手”
打个比方:LLM 是个博学的顾问,坐在办公室里。你问他什么,他都能侃侃而谈。但如果你让他”查一下今天股价”,他只能凭记忆猜——因为他没有手,没法打开电脑搜索。
工具调用改变了这一切。现在,顾问桌上多了几个按钮:一个连数据库、一个能发邮件、一个能执行代码。他可以根据你的问题,自己决定按哪个按钮,拿到结果,再整合成答案告诉你。
LLM 输出的是”我要调用 get_stock_price('AAPL')“这段指令,真正执行的是你的代码。这个分工很重要:模型决策,程序执行。
四大使用场景
🔍 动态信息检索
LLM 的训练数据有截止日期,但世界在转。实时股价、今天天气、数据库最新记录——这些全靠工具调用。
比如你给 Agent 连上 SQLite,它可以直接写 SQL 查”上个月销售额最高的产品”,拿到真实数据,而不是靠记忆编一个。我自己测试过,这个场景下的准确率比纯 LLM 高出一个量级。
💻 代码执行
数学问题、数据分析、生成图表——LLM 描述逻辑,Code Interpreter 真正跑起来。
最典型的例子:让 Agent 分析一份 CSV 数据。LLM 写出 pandas 代码,沙箱里执行,结果回传,LLM 再解读。整套流程下来,连 Excel 都不用打开。
⚙️ 工作流自动化
连上邮件服务、任务调度器、数据管道,Agent 就能自动化那些让你崩溃的重复操作。
举个例子:每周一早上,Agent 自动拉取上周数据、生成报告、发邮件给老板。你睡到自然醒,收件箱里已经全搞定了。(不是在做梦,现在真的可以这样。)
🎧 客户支持
Agent 连上 CRM 系统、工单平台、知识库,就能处理”我的订单在哪”这类问题,而不是给你一段废话。
用户问”我的退款申请进度”,Agent 查工单系统返回真实状态,而不是”您好,我是智能客服,很高兴为您服务……”那种车轱辘话。
六大构建模块
要让工具调用跑起来,背后有六个核心模块,缺一不可:
| 模块 | 白话解释 |
|---|---|
| Function/Tool Schema | 菜单——告诉 LLM 有哪些工具可选、每个工具要传什么参数 |
| Function Execution Logic | 厨房——决定何时调用哪个工具,处理条件分支和路由 |
| Message Handling System | 服务员——管理用户→LLM→工具→LLM→用户的完整对话流 |
| Tool Integration Framework | 供应链——把 Agent 和各种外部服务(API/数据库/函数)连起来 |
| Error Handling & Validation | 应急预案——工具挂了怎么办,参数不对怎么处理,别让 Agent 崩溃 |
| State Management | 记忆——追踪对话历史和工具调用上下文,让多轮对话有连贯性 |
这六块像乐高一样,你可以手写每一块,也可以用框架把它们打包好直接用。

完整流程拆解:「旧金山现在几点?」
让我们用一个最简单的例子,把整个链路走一遍。
第一步:用户提问
“旧金山现在几点?”
第二步:LLM 看到工具描述
系统启动时,我们已经把工具的 Schema(相当于说明书)塞给了 LLM:
`json
{
“name”: “get_current_time”,
“description”: “Get the current time for a given location”,
“parameters”: {
“type”: “object”,
“properties”: {
“location”: {
“type”: “string”,
“description”: “City name, e.g. ‘San Francisco'”
}
},
“required”: [“location”]
}
}
`
第三步:LLM 做决策
LLM 分析问题,判断需要调用 get_current_time,返回:
`json
{
“tool_name”: “get_current_time”,
“parameters”: { “location”: “San Francisco” }
}
`
注意:LLM 没有执行任何代码,它只是”点了这道菜”。
第四步:代码执行函数
`python
def get_current_time(location: str) -> str:
“””Get the current time for a given location”””
# 实际实现:调用时区 API 或 pytz 库
tz_map = {“San Francisco”: “America/Los_Angeles”}
tz = pytz.timezone(tz_map.get(location, “UTC”))
return datetime.now(tz).strftime(“%I:%M %p”)
# 执行结果
result = get_current_time(“San Francisco”) # → “09:24 AM”
`
第五步:结果回传 LLM,整合输出
工具返回 "09:24 AM",消息系统把这个结果塞回对话上下文,LLM 整合后输出:
“旧金山现在是早上 9:24。”
完整链路就是这样:用户问 → LLM 选工具 → 代码执行 → 结果回 LLM → 用户得答案。
手写 vs 用框架:我的建议
手写工具调用没什么不可以,但你要自己处理 Schema 注册、消息历史管理、工具调度……每一块都是坑。我自己第一次手写,光调试消息格式就花了半天。
框架的好处是:用一个 @tool 装饰器,剩下的全帮你搞定。
`python
from agent_framework import tool
from agent_framework.azure import AzureAIProjectAgentProvider
@tool
def get_current_time(location: str) -> str:
“””Get the current time for a given location”””
# 框架自动读取函数名、docstring、参数类型
# 生成完整的 JSON Schema,注册到 LLM 上下文
return f”{location}: 09:24 AM”
# 创建 Agent,直接传函数引用
provider = AzureAIProjectAgentProvider(credential=AzureCliCredential())
agent = await provider.create_agent(
name=”TimeAgent”,
instructions=”Use available tools to answer questions.”,
tools=get_current_time # 就这一行,Schema 自动生成
)
response = await agent.run(“旧金山现在几点?”)
`
@tool 装饰器会自动提取函数签名和 docstring,生成符合 OpenAI 格式的 JSON Schema。你只需要写业务逻辑,其他全交给框架。生产环境用框架,省下来的时间用来喝咖啡。

Azure AI Agent Service 内置工具全家桶
如果你用 Azure 生态,内置工具直接开箱即用,不用自己写集成代码:
知识工具(Knowledge Tools) — 用来”找信息”:
- Grounding with Bing Search:实时网络搜索,解决 LLM 知识截止问题。问”今天有什么新闻”这类实时问题必用
- File Search:在上传的文件里检索内容,适合”帮我在这份合同里找违约条款”
- Azure AI Search:连企业内部知识库,适合客服机器人、内部 FAQ 系统
动作工具(Action Tools) — 用来”干事情”:
- Function Calling:调用你自己写的函数,最灵活,所有自定义逻辑走这里
- Code Interpreter:沙箱里执行 Python 代码,处理数据分析、生成图表
- OpenAPI 定义的工具:只要有 API 文档,Agent 就能自动学会调用那个接口
- Azure Functions:云函数触发,适合触发复杂的业务流程和系统集成
选哪类?需要查信息用知识工具,需要干活用动作工具,很多时候两类混着用。
安全这件事不能省
工具调用给了 Agent 真实的执行能力,这意味着搞砸的代价也是真实的。三条准则:
1. 最小权限原则:给数据库只配 SELECT 权限,别给 DROP TABLE 的机会。Agent 不需要删数据,就别给它删数据的权力。我见过有人把写权限全开,结果 Agent 把测试数据库清空了。
2. 隔离执行环境:代码执行必须在沙箱里,生产数据不能直接暴露给 Agent。标准做法是经过 ETL 流程,把数据放到只读数仓,App 层只能拿只读访问凭证。
3. 输入验证不能省:用户输入可能包含 SQL 注入、Prompt 注入,工具层要做参数校验和类型检查。不要相信 LLM 生成的参数是安全的。
课后思考题
- 如果一个工具调用失败了(比如 API 超时),Agent 应该怎么处理?直接告诉用户”失败了”,还是重试,还是换个工具?你会怎么设计错误处理逻辑?
- 假设你要给电商客服 Agent 配置工具,需要查订单、退款、改地址……你会设计几个工具?粒度怎么拆?
- 工具调用的安全边界怎么画?哪些操作应该让 Agent 自主执行,哪些必须加”人工确认”环节?
AI 的世界每天都比昨天更陌生一点,但也更有意思一点。我们明天见。
第 5 课预告:Agentic RAG——让 Agent 自己决定去哪找答案,不再被动等着你塞资料进来。期待的扣 1。
夜雨聆风