最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Claude 不会直接执行你的函数:它只会生成一段结构化的工具调用请求。真正执行函数:访问数据库:请求外部 API 的动作:必须由你的后端完成。
时间:2026-07-01 10:21:54 编辑:袖梨 来源:一聚教程网
完整链路大致如下:
用户提问↓Claude 判断是否需要工具↓返回 tool_use↓后端解析并执行真实函数↓回传 tool_result↓Claude 基于结果生成最终回答
也就是说,Claude 负责「决策和参数生成」,你的服务端负责「执行和安全控制」。
1. Claude Tool Use 适合什么场景?
工具调用并不是所有场景都需要。它更适合处理模型无法仅靠自身知识稳定完成的任务。
典型适用场景:
- 查询实时数据:天气、库存、物流、订单、股票价格
- 访问内部系统:CRM、ERP、客服工单、支付系统
- 结构化参数提取:表单解析、意图识别、规则判断
- 多步骤任务编排:搜索、计算、查询、写入等 Agent 类流程
不太适合的场景:
- 普通知识问答
- 文案生成
- 总结改写
- 固定 FAQ
- 不依赖外部数据的对话
如果一个任务 Claude 直接回答即可,强行挂工具只会带来额外请求轮次、更高 token 成本和更复杂的工程逻辑。
2. Claude 工具调用涉及的核心字段
在 Claude Messages API 中,和工具调用相关的字段主要有:
| 字段 | 作用 |
|---|---|
tools | 声明当前有哪些工具可用 |
input_schema | 定义工具参数结构和约束 |
tool_use | Claude 返回的工具调用请求 |
tool_result | 后端执行工具后返回给 Claude 的结果 |
tool_choice | 控制是否调用工具,以及调用哪个工具 |
理解这几个字段,基本就能掌握 Claude Tool Use 的主流程。
3. 工具调用完整流程
3.1 定义工具:tools
定义工具并不是把真实函数上传给 Claude,而是给 Claude 一份「工具说明书」。
Claude 会根据以下信息判断是否使用工具:
name:工具名称description:工具能力和使用边界input_schema:工具需要的参数格式
示例:
{ "name": "get_order_status", "description": "根据订单 ID 查询订单的支付状态、发货状态和预计送达时间。只有当用户明确询问订单状态、物流进度或订单是否发货时才使用。", "input_schema": {"type": "object","properties": { "order_id": {"type": "string","description": "订单编号,例如 OD20240601001"} },"required": ["order_id"]}}
这里的 get_order_status 只是一个声明。真正的 get_order_status 函数,需要你在后端自己实现。
3.2 发送用户问题和工具列表
首次请求时,需要把用户消息和 tools 一起传给 Claude。
伪代码结构如下:
{ "model": "claude-3-5-sonnet-latest", "max_tokens": 1024, "tools": [ { "name": "get_order_status", "description": "根据订单 ID 查询订单的支付状态、发货状态和预计送达时间。只有当用户明确询问订单状态、物流进度或订单是否发货时才使用。", "input_schema": {"type": "object","properties": { "order_id": {"type": "string","description": "订单编号"} },"required": ["order_id"]} }], "messages": [ { "role": "user", "content": "帮我查一下订单 OD20240601001 发货了吗?" }]}
Claude 会根据用户问题自行判断是否需要调用工具。
3.3 解析 Claude 返回的 tool_use
如果 Claude 判断需要调用工具,响应中会出现类似结构:
{ "type": "tool_use", "id": "toolu_01ABC", "name": "get_order_status", "input": {"order_id": "OD20240601001"}}
此时常见的 stop_reason 是:
"tool_use"
它表示:Claude 暂停生成最终回答,等待你执行工具并回传结果。
3.4 后端执行真实函数
接下来进入你的服务端逻辑:
- 读取
tool_use.name - 根据工具名路由到对应函数
- 校验
tool_use.input - 执行业务逻辑
- 组装工具结果
伪代码示例:
async function handleToolUse(toolUse) { const { name, input } = toolUse; if (name === "get_order_status") {if (!input.order_id) { throw new Error("order_id is required"); }return await getOrderStatus(input.order_id);} throw new Error(`Unknown tool: ${name}`);}
重点:不要信任模型生成的参数。
即使你在 input_schema 中定义了参数格式,后端也必须再次校验,尤其是以下高风险操作:
- 数据库写入
- 支付操作
- 文件系统操作
- 权限变更
- 邮件 / 短信发送
- 调用内部敏感接口
模型负责生成参数,不负责保证参数绝对安全。
3.5 使用 tool_result 回传结果
工具执行完成后,需要把结果包装成 tool_result 再发回 Claude。
关键点:tool_use_id 必须等于上一轮 Claude 返回的 tool_use.id。
示例:
{ "role": "user", "content": [ { "type": "tool_result", "tool_use_id": "toolu_01ABC", "content": "{"status":"shipped","estimated_delivery":"2024-06-05"}" }]}
如果 tool_use_id 对不上,Claude 就无法知道这个结果对应哪一次工具调用。
3.6 获取最终回答
Claude 收到 tool_result 后,会基于真实工具结果生成自然语言回答。
例如:
你的订单 OD20240601001 已发货,预计将在 2024-06-05 送达。
所以用户最终看到的回答,并不是工具直接返回的原始数据,而是 Claude 基于工具结果组织后的表达。
4. 核心配置项怎么写?
4.1 tools.name:短、明确、方便路由
推荐使用英文小写 + 下划线:
get_order_statussearch_productscancel_ordercreate_ticket
不推荐:
get_dataquerydo_actionprocess
原因很简单:工具名不仅给 Claude 看,后端通常也会根据它做分发。名字越抽象,越容易误调用,也越难排查。
4.2 tools.description:重点写清楚「什么时候用」
很多人只写工具能做什么,但这还不够。对 Claude 来说,更重要的是判断「什么时候该用」。
不推荐:
查询订单。
推荐:
根据订单 ID 查询订单的支付状态、发货状态和预计送达时间。只有当用户明确询问订单状态、物流进度或订单是否发货时才使用。
如果多个工具能力接近,一定要在 description 里写清楚边界。
例如:
search_products:当用户想查找可购买商品、价格、库存时使用。get_order_status:当用户已经提供订单 ID,并询问订单支付、发货、物流状态时使用。
否则模型很容易把「查商品」和「查订单」混在一起。
4.3 input_schema:用 JSON Schema 约束参数
一个合格的 input_schema 至少应该包含:
typepropertiesrequired- 字段级
description
示例:
{"type": "object","properties": {"order_id": {"type": "string","description": "订单编号,例如 OD20240601001"},"status_type": {"type": "string","enum": ["payment", "shipping", "refund"],"description": "要查询的状态类型"}},"required": ["order_id", "status_type"]}
如果字段只有固定取值,建议使用 enum。
否则模型可能生成各种近义值:
物流状态发货情况deliveryshipping_status
这些对人类来说差别不大,但对后端来说可能完全匹配不上。
4.4 tool_choice:控制是否调用工具
tool_choice 用来控制 Claude 的工具调用策略。
常见模式有三种:
自动选择
让 Claude 自己判断是否调用工具。
适合大多数对话式场景。
{"tool_choice": {"type": "auto"}}
强制调用某个工具
适合必须走结构化流程的场景,比如表单抽取、订单查询、工单创建。
{"tool_choice": {"type": "tool","name": "get_order_status"}}
禁止调用工具
如果是纯文本生成、总结、改写,不需要传 tools 即可。
如果 SDK 或 API 版本支持显式禁用,也可以按官方最新文档配置。Anthropic API 字段可能随版本演进,生产环境建议以官方文档为准。
4.5 temperature 和 max_tokens
工具调用场景下,建议降低随机性:
{"temperature": 0,"max_tokens": 1024}
尤其是参数抽取、查询类任务,temperature 不宜过高。否则可能出现:
- 参数值不稳定
- 工具选择不稳定
- 返回格式变化
- 多工具场景下路由混乱
max_tokens 也要留足空间,否则可能出现工具调用内容被截断的问题。
5. 多工具场景如何设计?
当业务中存在多个工具时,建议遵循两个原则:
- 工具职责单一
- 工具边界明确
示例:
[{"name": "search_products","description": "根据关键词搜索商品信息,包括商品名称、价格和库存。仅当用户想查找或比较商品时使用。","input_schema": {"type": "object","properties": {"keyword": {"type": "string","description": "商品搜索关键词"}},"required": ["keyword"]}},{"name": "get_order_status","description": "根据订单 ID 查询订单状态。仅当用户提供订单 ID 并询问支付、发货、物流或退款状态时使用。","input_schema": {"type": "object","properties": {"order_id": {"type": "string","description": "订单编号"}},"required": ["order_id"]}}]
不要把一个工具设计成万能入口:
handle_user_requestprocess_businessquery_data
这种设计短期省事,长期会带来三个问题:
- Claude 不知道什么时候该用
- 后端逻辑难以维护
- 参数 schema 会越来越臃肿
6. 常见避坑点
6.1 不要把工具描述写得太宽泛
错误示例:
用于查询业务信息。
这类描述会导致 Claude 在很多无关问题上也尝试调用工具。
建议写成:
仅当用户明确提供订单 ID,并询问订单支付、发货、物流或退款状态时使用。
6.2 不要依赖模型做权限判断
不要让 Claude 自己判断用户有没有权限取消订单、退款或查看数据。
权限判断必须放在后端:
用户身份校验↓权限校验↓参数校验↓执行工具
模型可以帮你理解意图,但不能替代权限系统。
6.3 tool_result 不要塞太多无关数据
工具结果越大,Claude 消耗的 token 越多,也越容易抓不住重点。
推荐返回精简结构:
{"order_id": "OD20240601001","shipping_status": "shipped","estimated_delivery": "2024-06-05"}
不推荐直接返回完整数据库记录,尤其是包含内部字段、日志、用户隐私信息的结果。
6.4 注意工具调用可能不止一次
在复杂任务中,Claude 可能连续发起多次工具调用。
例如:
用户:帮我查一下这款手机有没有货,如果有货就告诉我最近的门店。
可能流程是:
search_products↓check_inventory↓find_nearest_store↓最终回答
因此后端代码不要假设「每次对话只会有一次 tool_use」。
6.5 处理未知工具和异常参数
生产环境必须处理异常情况:
- Claude 返回了未知工具名
- 参数缺失
- 参数类型错误
- 工具执行失败
- 外部 API 超时
- 结果为空
建议统一封装错误结果,再返回给 Claude:
{"error": true,"message": "未查询到该订单,请确认订单编号是否正确。"}
这样 Claude 可以基于错误信息给用户一个可读的回复,而不是直接中断流程。
7. 一个简化版接入流程
可以把 Claude Tool Use 接入理解成下面这段伪代码:
async function chatWithTools(userMessage) {const firstResponse = await claude.messages.create({model: "claude-3-5-sonnet-latest",max_tokens: 1024,temperature: 0,tools,messages: [{role: "user",content: userMessage}]});const toolUse = firstResponse.content.find(item => item.type === "tool_use");if (!toolUse) {return firstResponse.content;}const toolResult = await handleToolUse(toolUse);const finalResponse = await claude.messages.create({model: "claude-3-5-sonnet-latest",max_tokens: 1024,messages: [{role: "user",content: userMessage},{role: "assistant",content: firstResponse.content},{role: "user",content: [{type: "tool_result",tool_use_id: toolUse.id,content: JSON.stringify(toolResult)}]}]});return finalResponse.content;}
真实项目中还需要补充:
- 多轮上下文管理
- 多个
tool_use的并发或串行处理 - 参数校验
- 权限校验
- 日志追踪
- 超时重试
- 敏感信息过滤
8. 实践建议
如果你准备在业务中接入 Claude Tool Use,可以按这个顺序推进:
- 先定义少量高价值工具,不要一开始挂十几个工具
- 每个工具只做一件事
description写清楚使用条件和边界input_schema尽量严格,能用enum就用enum- 后端必须做参数校验和权限校验
- 工具返回结果保持精简
- 记录完整日志,方便排查误调用
- 对高风险操作增加二次确认
尤其是涉及写操作时,不建议让模型一步完成。
例如取消订单可以拆成两步:
第一步:Claude 识别用户想取消订单,调用查询工具确认订单状态第二步:向用户确认是否取消第三步:用户确认后,后端再执行取消动作
这样可以降低误操作风险。
总结
Claude API 的 Function Calling,本质上是 Anthropic 的 Tool Use 机制。
它的核心不是「让模型执行函数」,而是:
让模型判断调用哪个工具、生成结构化参数;让后端执行真实逻辑、返回工具结果;再让模型基于结果生成最终回答。
接入时重点关注五件事:
- 工具定义是否清晰
- 参数 schema 是否严格
- 工具选择是否可控
- 后端校验是否完整
- 异常和权限是否兜底
只要把这些边界处理好,Claude Tool Use 就可以稳定连接业务系统,把大模型从「只会回答」扩展到「能参与真实业务流程」。
相关文章
- 奥奇传说新角色安技能简介 07-01
- 2025今日小鸡最新答案7月1日 支付宝小鸡最新答案2026年7月1日 07-01
- 蚂蚁庄园今日答案 中国古代诗词中豪放派词人代表是 07-01
- 蚂蚁庄园今日答案 荞麦枕真的能养生吗 07-01
- 蚂蚁庄园小课堂今日答案最新7.1 蚂蚁庄园今日答案汇总7月1日 07-01
- 小鸡庄园最新答案 小鸡庄园最新答案7.1 07-01