第3课:亲手跑通工具调用,别把“请求”当作“结果”
运行无网络城市时间工具,验证请求、参数、执行及返回。
本文目录 · 7 节
前两课从任务边界走到人的控制权。本课选编微软 AI Agents for Beginners 第4课《Tool Use Design Pattern》,保留原课的城市时间查询案例,将依赖云账号的示例改为本地可运行练习。你会看到工具定义、调用请求、参数检查、执行结果如何衔接,而不是只读一段框架介绍。
需要 Python 3.10 或更新版本与纯文本编辑器,不安装第三方包。程序不调用模型、不访问网络,不是真正接入大模型的 Agent。我们用固定 JSON 模拟模型提出的调用,用固定 UTC 时间让参考输出可重复;因此输出不是执行当天的实时钟表。
一、工具使用模式解决什么问题
原教材把工具使用模式定义为:给模型接入可执行代码,使它通过生成函数调用来实现目标。工具可以只是计算器,也可以连接数据库或外部服务。它适用于动态信息检索、代码计算、工作流自动化、客服系统与内容处理等场景。
工具并不是一句“你可以查时间”。完整实现还需要工具说明、执行逻辑、消息处理、连接工具的基础设施、错误处理和状态管理。少了其中一部分,模型可能提出正确请求,程序却没有执行;也可能工具已经返回,结果却没送回正确的会话。
图中工具定义整理为模型能读取的形式,随后才进入模型处理。原图的两个编号4表示普通回复与函数调用两条处理分支;理解交接即可,不要把它当作要照抄的 SDK 操作序号。
二、先看请求里有什么、没有什么
微软原课以查询旧金山当前时间展示函数调用。模型收到函数说明后,返回的关键内容是函数名和参数,不是最终时间。宿主根据返回信息执行时间函数,再把执行结果送回模型。本课改用上海与UTC两种固定偏移,避免初学者在不同时区数据库安装环境中遇到额外依赖。
{"name":"get_time","arguments":{"location":"上海"}}这段请求不包含时间结果,也没有“已成功”字段。即使候选请求里夹带一个漂亮答案,也不能把它当成实际工具返回。输入格式正确,只是进入执行层的第一关;还要确认工具名、参数、业务范围和本次授权。
三、保存并运行完整示例
新建 time_tool_lesson.py,把下面整段代码复制进去。tools 是给调用方看的接口说明;本例不会把它发送给真实模型。模拟调用路径与模型选择工具的能力必须分开看。
import json
from datetime import datetime, timedelta, timezone
tools = {
"name": "get_time",
"description": "根据固定教学时刻,返回上海或UTC的时间;不是实时查询",
"parameters": {"location": "上海 或 UTC,必填字符串"},
}
reference = datetime(2026, 9, 4, 1, 0, tzinfo=timezone.utc)
def get_time(location):
offsets = {"上海": 8, "UTC": 0}
if location not in offsets:
return {"ok": False, "error": "本练习只支持上海和UTC"}
target = timezone(timedelta(hours=offsets[location]))
value = reference.astimezone(target).strftime("%Y-%m-%d %H:%M %z")
return {"ok": True, "location": location, "time": value, "simulated": True}
def dispatch(raw):
try:
request = json.loads(raw)
except json.JSONDecodeError:
return {"ok": False, "error": "调用必须是一个有效JSON对象"}
if type(request) is not dict or set(request) != {"name", "arguments"}:
return {"ok": False, "error": "顶层字段不符合约定"}
if request["name"] != tools["name"]:
return {"ok": False, "error": "未授权的工具名称"}
args = request["arguments"]
if type(args) is not dict or set(args) != {"location"}:
return {"ok": False, "error": "需要且只接受location参数"}
if type(args["location"]) is not str:
return {"ok": False, "error": "location必须是字符串"}
return get_time(args["location"])
samples = [
'{"name":"get_time","arguments":{"location":"上海"}}',
'{"name":"get_time","arguments":{"location":"UTC"}}',
'{"name":"get_time","arguments":{"location":"未知城市"}}',
'{"name":"send_email","arguments":{"location":"上海"}}',
'{"name":"get_time","arguments":{"location":8}}',
]
print("工具说明:", tools["description"])
for raw in samples:
result = dispatch(raw)
print("请求:", raw)
print("工具结果:", json.dumps(result, ensure_ascii=False))
if result["ok"]:
print("教学时刻:", result["time"])
else:
print("未取得时间,不能报告成功。")在文件目录运行 python time_tool_lesson.py;系统使用 py 或 python3 时换成相应启动命令。预期第一项返回 2026-09-04 09:00 +0800,第二项为 2026-09-04 01:00 +0000,后三项依次报告未知地点、未授权工具名和参数类型错误。
四、为什么要分开这些函数
get_time 专心处理本题支持的地点和时间换算;dispatch 负责检查请求并选择允许的工具。这样即使候选请求写成发送邮件,程序也不会凭名字寻找任意系统函数。它没有邮件工具,更没有账号凭据。
json.loads 只负责解析JSON,不保证业务合法。本课继续检查字段集合和字符串类型,不把数值8自动猜成“东八区”。严格处理可以让失败显露出来,而不是把不一致藏到最终答案中。
真实接口往往还提供工具调用ID。原课在回传结果时保留对应调用ID,是为了使多个工具结果回到正确请求。当前练习逐条同步执行,所以没有模拟并发和调用ID;以后接入真实模型不能因为本例省略就忽略接口要求。本课也不实现生产级输入资源限制、认证或多用户隔离。
五、从“能运行”走到“值得相信”
微软原课特别提醒,动态生成SQL有删除、篡改或注入风险;应通过数据库访问权限控制,比如只读角色,而不是只在提示词中说“不要修改”。同样,本例的工具允许列表是真实检查,角色说明只是沟通层,两者不能互相替代。
如果你把工具换成查询订单,应只提供必要字段,避免把全部客户资料送给模型;换成取消订单,则需要额外的目标核对与明确确认。读取与写入的风险不同,即使JSON完全正确,也不能证明用户同意本次写操作。
工具返回也可能失败、过时或不完整。本例在结果中保留 simulated,最终展示也写“教学时刻”,避免把固定参考时间冒充实时查询。真实应用还要核对数据时间与单位;“调用成功”不能自动代表“满足问题”。
六、练习、排错与下一步
练习一,把上海请求最后加上文字“已执行成功”。解析应失败,因为这不是单个JSON对象。练习二,删除location字段,应在执行前被拒绝。练习三,把参考时刻小时从1改为2,上海结果应变成10点;这验证最终展示确实来自函数结果,而不是固定写在回复里。
如果报文件不存在,检查当前目录和文件后缀;如果报缩进错误,检查复制时空格;如果未知城市失败,这是预期,不应为消除红字直接移除检查。不要用 eval 执行模型输出,也不要把原课里需要真实云凭据的代码片段混进这个离线文件。
完成标准是保留两条成功结果、三条拒绝结果,并能指出请求、执行、结果分别产生在哪里。本轮三课覆盖任务定义、人本设计和工具交接,尚未搭建真正的大模型 Agent 服务;后续接入框架、云账号和真实数据时,仍要重新验证权限、成本、错误处理与用户控制。
版权与许可
选译 Microsoft AI Agents for Beginners《Tool Use Design Pattern》。保留工具组件与函数调用流程,城市时间示例改为离线固定时刻,新增严格检查和练习;配图原样保留,非微软官方中文版本。完整 MIT 声明如下:
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE文字来源:Microsoft AI Agents for Beginners;中文选译及补充练习;Copyright (c) Microsoft Corporation;MIT完整声明随公开正文。