当前位置: 首页 > news >正文

Claude Tool Use 怎么用?从零到生产的完整教程(2026)

上周接了个需求,做一个能查天气、查数据库、还能发邮件的 AI 助手。一开始想着用 LangChain 套一层,后来发现 Claude 原生的 Tool Use(也叫 Function Calling)已经很成熟了,根本不需要额外框架。但官方文档写得有点绕,我踩了不少坑才把整条链路跑通。把摸索出来的东西全写下来,让你少走弯路。

Claude Tool Use 是 Anthropic 提供的原生函数调用能力,允许你在对话中定义工具(函数),Claude 会自动判断何时调用哪个工具、提取参数,你执行函数后把结果返回给它,它再生成最终回答。目前 Claude Sonnet 4.6 和 Opus 4.6 都支持,Sonnet 性价比最高,Opus 复杂推理更强。

先说结论

维度说明
支持模型Claude Opus 4.6、Sonnet 4.6、Haiku 4.6
协议格式Anthropic 原生格式 / OpenAI 兼容格式均可
核心流程定义工具 → 发送请求 → Claude 返回工具调用 → 你执行函数 → 结果回传 → Claude 生成回答
并行调用支持,一次可调用多个工具
嵌套调用支持,工具结果可触发新一轮工具调用
踩坑重灾区tool_result 的 content 必须是字符串、工具描述写得烂会导致调用率暴跌

核心流程一图看懂

本地工具函数Claude API你的代码本地工具函数Claude API你的代码发送消息 + 工具定义返回 tool_use(要调用哪个工具、参数是什么)执行本地函数返回执行结果把 tool_result 回传Claude 生成最终回答

这个流程是整个 Tool Use 的骨架,后面的代码全是围绕这个转的。

环境准备

pipinstallopenai httpx

这里用的是 OpenAI SDK。因为很多聚合平台都兼容 OpenAI 协议,Claude 的 Tool Use 在 OpenAI 兼容模式下也能正常工作,切换模型零成本。

方案一:基础 Tool Use(单工具调用)

先来最简单的场景——让 Claude 调用一个查天气的函数。

importjsonfromopenaiimportOpenAI client=OpenAI(api_key="your-api-key",base_url="https://api.ofox.ai/v1"# 聚合接口,一个 Key 调 Claude/GPT/Gemini)# 1. 定义工具tools=[{"type":"function","function":{"name":"get_weather","description":"获取指定城市的当前天气信息,包括温度、湿度、天气状况","parameters":{"type":"object","properties":{"city":{"type":"string","description":"城市名称,如:北京、上海、深圳"},"unit":{"type":"string","enum":["celsius","fahrenheit"],"description":"温度单位,默认摄氏度"}},"required":["city"]}}}]# 2. 你的本地函数(实际项目中这里调真实 API)defget_weather(city:str,unit:str="celsius")->dict:# 模拟数据,实际替换成真实天气 APIfake_data={"北京":{"temp":22,"humidity":45,"condition":"晴"},"上海":{"temp":26,"humidity":72,"condition":"多云"},"深圳":{"temp":31,"humidity":80,"condition":"雷阵雨"},}data=fake_data.get(city,{"temp":20,"humidity":50,"condition":"未知"})ifunit=="fahrenheit":data["temp"]=data["temp"]*9/5+32data["city"]=city data["unit"]=unitreturndata# 3. 发送请求messages=[{"role":"user","content":"深圳今天天气怎么样?适合跑步吗?"}]response=client.chat.completions.create(model="claude-sonnet-4.6",messages=messages,tools=tools,tool_choice="auto"# 让 Claude 自己决定要不要调工具)# 4. 处理工具调用assistant_message=response.choices[0].messageifassistant_message.tool_calls:# Claude 决定调用工具messages.append(assistant_message)# 先把 assistant 消息加进去fortool_callinassistant_message.tool_calls:func_name=tool_call.function.name func_args=json.loads(tool_call.function.arguments)print(f"Claude 要调用:{func_name}({func_args})")# 执行本地函数iffunc_name=="get_weather":result=get_weather(**func_args)# 把结果回传(注意:content 必须是字符串!)messages.append({"role":"tool","tool_call_id":tool_call.id,"content":json.dumps(result,ensure_ascii=False)})# 5. 让 Claude 根据工具结果生成最终回答final_response=client.chat.completions.create(model="claude-sonnet-4.6",messages=messages,tools=tools)print(final_response.choices[0].message.content)else:# Claude 觉得不需要调工具,直接回答了print(assistant_message.content)

实测输出:

Claude 要调用: get_weather({'city': '深圳'}) 深圳今天31°C,湿度80%,有雷阵雨。不太建议户外跑步哦, 湿度太高容易中暑,雷阵雨也不安全。建议等晚上凉快点再去, 或者去室内跑步机上练练。

Claude 不是机械地把数据复述一遍,它会结合天气数据给出建议。这就是 Tool Use 比硬编码模板强的地方。

方案二:多工具 + 自动循环调用

真实项目很少只有一个工具。下面这个例子定义了三个工具,并且实现了自动循环——Claude 可能调完一个工具还想调另一个,代码自动处理。

importjsonfromopenaiimportOpenAI client=OpenAI(api_key="your-api-key",base_url="https://api.ofox.ai/v1")# 定义多个工具tools=[{"type":"function","function":{"name":"search_products","description":"根据关键词搜索商品,返回商品列表(名称、价格、库存)","parameters":{"type":"object","properties":{"keyword":{"type":"string","description":"搜索关键词"},"max_results":{"type":"integer","description":"最多返回几条,默认5"}},"required":["keyword"]}}},{"type":"function","function":{"name":"get_product_reviews","description":"获取指定商品ID的用户评价摘要","parameters":{"type":"object","properties":{"product_id":{"type":"string","description":"商品ID"}},"required":["product_id"]}}},{"type":"function","function":{"name":"create_order","description":"创建订单。注意:仅在用户明确表示要购买时才调用","parameters":{"type":"object","properties":{"product_id":{"type":"string"},"quantity":{"type":"integer","description":"购买数量,默认1"}},"required":["product_id"]}}}]# 模拟业务函数defsearch_products(keyword,max_results=5):return[{"id":"P001","name":f"机械键盘-{keyword}款","price":359,"stock":42},{"id":"P002","name":f"薄膜键盘-{keyword}入门","price":89,"stock":156},]defget_product_reviews(product_id):reviews={"P001":{"score":4.7,"count":2341,"summary":"手感好,Cherry轴,就是有点吵"},"P002":{"score":4.1,"count":892,"summary":"便宜够用,适合办公"},}returnreviews.get(product_id,{"score":0,"summary":"暂无评价"})defcreate_order(product_id,quantity=1):return{"order_id":"ORD20260329001","status":"created","product_id":product_id,"quantity":quantity}# 函数路由FUNC_MAP={"search_products":search_products,"get_product_reviews":get_product_reviews,"create_order":create_order,}defchat_with_tools(user_input:str):messages=[{"role":"system","content":"你是一个电商购物助手,帮用户搜索商品、查看评价、下单购买。"},{"role":"user","content":user_input}]max_rounds=5# 防止死循环forround_numinrange(max_rounds):response=client.chat.completions.create(model="claude-sonnet-4.6",messages=messages,tools=tools,tool_choice="auto")msg=response.choices[0].message# 没有工具调用,说明 Claude 准备好回答了ifnotmsg.tool_calls:returnmsg.content# 有工具调用,执行并回传messages.append(msg)fortool_callinmsg.tool_calls:func_name=tool_call.function.name func_args=json.loads(tool_call.function.arguments)print(f" [Round{round_num+1}] 调用{func_name}({func_args})")result=FUNC_MAP[func_name](**func_args)messages.append({"role":"tool","tool_call_id":tool_call.id,"content":json.dumps(result,ensure_ascii=False)})return"工具调用轮次超限,请简化问题"# 测试answer=chat_with_tools("我想买个键盘打代码用,帮我看看有啥推荐的,评价好的那种")print(answer)

跑起来后,Claude 会先调search_products,看到结果后自动调get_product_reviews查评价,再综合两次结果给出推荐。两轮工具调用,全自动。

踩坑记录

这部分是我花时间最多的地方。

坑 1:tool_result 的 content 不是字符串直接报错

content字段必须是字符串,不能直接传 dict。

# ❌ 错误写法messages.append({"role":"tool","tool_call_id":tool_call.id,"content":{"temp":22}# 这会报 422 错误})# ✅ 正确写法messages.append({"role":"tool","tool_call_id":tool_call.id,"content":json.dumps({"temp":22},ensure_ascii=False)})

坑 2:工具描述写太简单,Claude 不调或者乱调

这个坑比较隐蔽。我一开始给get_weather的 description 写的是"获取天气",三个字。结果 Claude 经常不调这个工具,直接瞎编一个天气回答。

description 要写清楚三件事:这个函数干什么、输入什么、返回什么。参数的 description 也一样,别偷懒。

# ❌ 太简单"description":"获取天气"# ✅ 写清楚"description":"获取指定城市的当前天气信息,返回温度(数字)、湿度(百分比)、天气状况(文字描述)"

坑 3:忘记把 assistant message 加回 messages

这个 bug 特别坑,报错信息还不明显。Claude 返回工具调用后,必须先把那条 assistant 消息原封不动加回 messages,再加 tool result,顺序不能乱。

# ❌ 漏掉了 assistant messagemessages.append({"role":"tool","tool_call_id":tool_call.id,"content":result_str})# ✅ 先加 assistant,再加 tool resultmessages.append(assistant_message)# 这一步不能少!messages.append({"role":"tool","tool_call_id":tool_call.id,"content":result_str})

坑 4:并行工具调用时 tool_call_id 必须一一对应

Claude 有时候一次返回多个 tool_calls(比如同时查两个城市的天气)。每个 tool_result 的tool_call_id必须和对应的 tool_call 匹配,搞混了就 400 错误。用上面for tool_call in msg.tool_calls的写法就不会出问题。

tool_choice 参数详解

这个参数控制 Claude 调不调工具、怎么调:

行为适用场景
"auto"Claude 自己决定(推荐)大多数场景
"none"禁止调工具纯聊天轮次
"required"强制必须调工具你确定这轮一定要调工具
{"type": "function", "function": {"name": "xxx"}}强制调指定工具流程编排、测试

90% 的时候用"auto"就够了。只有在做严格的多步骤流程编排时才需要强制指定。

小结

Claude Tool Use 的核心就是那个请求-调用-回传的循环,搞懂这个剩下的都是细节。重点记四条:description 要写详细、content 必须是字符串、assistant message 不能漏、循环要设上限防死循环

我现在用的方案是通过 ofox.ai 的聚合接口调 Claude,它是一个 AI 模型聚合平台,一个 API Key 可以调 Claude Opus 4.6、GPT-5、Gemini 3 等 50+ 模型,低延迟直连,支持支付宝付款。换模型不用改代码,Claude 的 Tool Use 和 GPT-5 的 Function Calling 用同一套代码就能跑,方便对比效果。

代码我放 Gist 上了,直接 copy 就能跑。有问题评论区见。

http://www.jsqmd.com/news/559592/

相关文章:

  • Hourglass:Windows终极时间管理工具,3大场景提升效率的秘诀
  • go 语言之网络编程
  • 2026郑州靠谱驾校机构推荐:高新区安达驾校,本地正规全包班/通过率高/莲花街附近优选 - 品牌推荐官
  • 2026 兰州日式搬家TOP6|正规靠谱、不踩坑、全程不动手精选榜单 - 深度智识库
  • Nigate:开源NTFS读写工具解决Mac跨平台文件传输难题
  • 告别默认ResNet-50:为你的病理图像特征提取,升级CLAM+CONCH v1.5的保姆级指南
  • SPIRAN ART SUMMONER部署指南:Ubuntu20.04环境配置全解析
  • 脱发用什么洗发水好?成分党实测:避开3大误区再选,第一名真香 - 博客万
  • 2026年佛山做账报税服务推荐:佛山市联聚财税管理有限公司,专业代理记账与资质办理服务 - 品牌推荐官
  • 舒茨CGC-300固定污染源烟气排放连续监测系统作用 - 品牌推荐大师
  • PHPStudy V8.1安装避坑指南:解决Apache启动报错AH00526的3种方法
  • 2026云南耐水防潮隔墙板厂家解析:耐水防潮板材本土实力厂商报告 - 深度智识库
  • 2026年上海废旧物资回收公司推荐:上海沪昱宁环保科技,KTV/空调/货架/酒店公寓回收全覆盖 - 品牌推荐官
  • SDXL-Turbo助力插画师:风格测试与色彩搭配效率提升
  • Unity内联序列化类的秘密
  • 杭州海尚探秘!2026年3月绝美打卡地等你来发现✨ - 界川
  • 2025-2026年大厂求职机构测评:技术岗求职竞争五家热门机构综合选择调研 - 十大品牌推荐
  • 【IEEE出版 | 往届会后3个月检索】第六届电子、电路与信息工程国际学术会议(ECIE 2026)
  • 2026年营养实训室建设厂家推荐:璞泰健康科技有限公司,全场景营养实训解决方案提供商 - 品牌推荐官
  • 基于Qwen3-ASR-1.7B的语音交互游戏开发指南
  • 2026年击剑比赛风险评估推荐:聚焦国际与品牌赛事场景,五大服务商全面评价 - 博客万
  • 零食年度盘点:“好吃”与“放心”两全 - 华Sir1
  • 告别Zabbix!轻量级监控神器Netdata在Ubuntu 22.04上的花式玩法
  • OpenClaw+GLM-4.7-Flash开发提效:日志分析+异常告警自动化
  • Unity序列化为何拒绝多态
  • 京东e卡回收流程,三步轻松搞定 - 京顺回收
  • 在国产麒麟V10系统上,用kubeadm一步步搭建3个master节点的k8s高可用集群(含haproxy+keepalived配置)
  • 用RK3588开发板给机械臂装上‘大脑’:从电机驱动到AI视觉抓取的保姆级实践
  • 在移动终端Termux中配置SSH密钥,实现免密安全登录远程服务器
  • 【MySQL】函数:聚合函数