在接入 Claude API 时很多开发者会搜索Claude API Function Calling希望实现类似 OpenAI Function Calling 的能力让大模型根据用户问题自动决定是否调用某个函数并传入结构化参数。不过需要先明确一点在 Anthropic Claude 官方文档中这项能力通常被称为Tool Use也就是“工具使用”或“工具调用”而不是 Function Calling。从开发视角来看下面这些说法基本指的是同一类能力Claude Function CallingClaude API Tool UseClaude 工具调用Claude API 工具调用配置Claude 调用外部函数但严格来说Claude 并不会直接执行你的后端函数。它的职责是判断是否需要调用工具并生成一份结构化的工具调用请求。真正的函数执行、数据库查询、接口请求、权限校验、业务系统写入仍然需要由你的服务端代码完成。1. Claude Tool Use 的核心工作流程Claude 工具调用的完整链路可以概括为用户提问 ↓ Claude 判断是否需要工具 ↓ 返回 tool_use 调用请求 ↓ 后端解析 tool_use 并执行真实函数 ↓ 后端将执行结果通过 tool_result 回传给 Claude ↓ Claude 基于工具结果生成最终回答也就是说Claude 只负责“提出调用意图”而不是“实际执行动作”。例如用户问帮我查一下订单 OD20240601001 发货了吗Claude 可能返回一个工具调用请求{type:tool_use,id:toolu_01ABC,name:get_order_status,input:{order_id:OD20240601001}}随后你的后端根据name找到对应函数查询订单系统再把结果返回给 Claude。2. 什么场景适合使用 Claude Function CallingClaude Tool Use 并不是所有场景都必须使用。它更适合那些需要外部数据、实时信息或业务系统能力的任务。2.1 适合使用工具调用的场景常见场景包括查询实时数据例如天气、汇率、股票价格、物流进度、库存状态等。调用内部业务系统例如 CRM、ERP、订单系统、支付系统、客服工单系统等。获取用户相关数据例如账户余额、会员等级、订单列表、售后记录等。执行结构化任务例如从自然语言中抽取参数、补全表单、分类、规则判断等。构建 Agent 多步骤流程例如先搜索商品再查询库存再生成购买建议。2.2 不一定需要工具调用的场景以下任务通常可以直接让 Claude 回答普通知识问答文案生成文章总结内容改写固定 FAQ代码解释不依赖实时数据的推理任务如果一个任务本身不依赖外部系统强行加入工具调用会带来额外成本请求轮次变多token 消耗增加后端逻辑变复杂调试链路变长出错点更多。因此工具调用应该用于“模型自己无法可靠完成”的任务而不是所有任务都挂工具。3. Claude Tool Use 中几个关键字段在 Claude Messages API 中与工具调用关系最密切的字段主要有以下几个。字段作用tools声明当前可供 Claude 使用的工具列表input_schema定义工具参数结构和约束tool_useClaude 返回的工具调用请求tool_result后端执行工具后回传给 Claude 的结果tool_choice控制 Claude 自动选择工具、强制调用工具或不调用工具stop_reason判断 Claude 是否因为需要调用工具而暂停输出理解这几个字段是实现 Claude Function Calling 的基础。4. 第一步定义工具 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]}}这里需要注意description不只是说明工具能做什么更重要的是告诉 Claude什么时候应该使用它。5. 第二步发送用户消息和工具列表首次请求 Claude 时需要同时传入用户问题工具列表tools模型参数其他上下文信息。示例请求结构如下{model:claude-3-5-sonnet-20241022,max_tokens:1024,tools:[{name:get_order_status,description:根据订单 ID 查询订单的支付状态、发货状态和预计送达时间。只有当用户明确询问订单状态、物流进度或订单是否发货时才使用。,input_schema:{type:object,properties:{order_id:{type:string,description:订单编号例如 OD20240601001}},required:[order_id]}}],messages:[{role:user,content:帮我查一下订单 OD20240601001 发货了吗}]}Claude 收到请求后会判断当前问题是否需要调用工具。6. 第三步解析 Claude 返回的 tool_use如果 Claude 认为需要使用工具响应内容中通常会包含tool_use。示例{type:tool_use,id:toolu_01ABC,name:get_order_status,input:{order_id:OD20240601001}}此时响应中的stop_reason通常是stop_reason:tool_use这表示Claude 暂停生成最终自然语言回答等待你执行工具并返回结果。开发者需要在后端做几件事遍历 Claude 返回的content找到type为tool_use的内容块读取name根据name分发到对应后端函数校验input参数执行业务逻辑。7. 第四步后端执行真实函数拿到tool_use后需要由后端执行真正的函数。例如asyncfunctiongetOrderStatus(orderId){// 示例这里可以查询数据库、调用订单系统或第三方接口return{order_id:orderId,payment_status:paid,shipping_status:shipped,estimated_delivery:2024-06-05};}工具分发逻辑可以类似这样asyncfunctionexecuteTool(toolUse){const{name,input}toolUse;if(nameget_order_status){if(!input.order_id){thrownewError(order_id is required);}returnawaitgetOrderStatus(input.order_id);}thrownewError(Unknown tool:${name});}这里有一个非常重要的原则永远不要无条件信任模型生成的工具参数。尤其是涉及以下场景时后端必须做严格校验数据库查询订单取消支付退款文件读写邮件发送权限变更用户隐私数据查询内部系统写操作。Claude 生成的参数应该被视为“用户输入”而不是可信指令。8. 第五步通过 tool_result 回传执行结果工具执行完后需要将结果包装成tool_result再发送给 Claude。其中最关键的字段是tool_use_id:toolu_01ABC这个 ID 必须与上一轮 Claude 返回的tool_use.id完全一致。示例{role:user,content:[{type:tool_result,tool_use_id:toolu_01ABC,content:{\order_id\:\OD20240601001\,\payment_status\:\paid\,\shipping_status\:\shipped\,\estimated_delivery\:\2024-06-05\}}]}注意tool_use_id不能自己随便生成必须对应上一轮的tool_use.id如果有多个工具调用需要分别回传对应结果工具执行失败时也应该返回可解释的错误信息。9. 第六步Claude 生成最终回答Claude 收到tool_result后会结合工具返回的数据生成自然语言回答。例如最终回复可能是订单 OD20240601001 已支付目前已经发货预计将在 2024-06-05 送达。从用户视角看这就是一次完整的“模型调用函数并回答”的流程。但从系统实现看实际经历了两次 Claude API 请求第一次用户问题 toolsClaude 返回tool_use第二次回传tool_resultClaude 返回最终回答。10. tools.name工具名要短、明确、可路由工具名建议使用英文小写和下划线例如get_order_status search_products cancel_order create_ticket query_user_profile不建议使用过于泛化的名称get_data query do_action handle_request process原因有两个第一Claude 需要通过工具名理解大致用途。第二后端通常会根据工具名做函数分发。例如consttoolHandlers{get_order_status,search_products,cancel_order};如果工具名过于抽象后续调试和排查都会很麻烦。11. tools.description重点写清楚“什么时候用”很多开发者在写工具描述时只写工具能做什么例如查询订单。这种描述太短Claude 很难准确判断调用边界。更推荐的写法是根据订单 ID 查询订单的支付状态、发货状态和预计送达时间。只有当用户明确询问订单状态、物流进度、是否发货或预计送达时间时才使用。好的description应该包含三类信息这个工具能做什么用户表达什么意图时应该使用什么情况下不应该使用。例如{name:search_products,description:根据关键词搜索商品列表返回商品名称、价格、库存和商品 ID。只有当用户想查找、比较或购买商品时才使用。不要用于查询订单状态。}当你有多个职责相近的工具时描述边界尤其重要。例如get_order_status查询订单状态search_products搜索商品cancel_order取消订单create_refund_request创建退款申请。如果描述写得模糊模型很容易误选工具。12. input_schema用 JSON Schema 约束参数input_schema用来告诉 Claude 工具需要哪些参数以及每个参数的类型和含义。一个基本 schema 通常包括typepropertiesrequired字段级description示例{type:object,properties:{order_id:{type:string,description:订单编号例如 OD20240601001}},required:[order_id]}如果某个字段只有固定取值建议使用enum。例如{type:object,properties:{status_type:{type:string,enum:[payment,shipping,refund],description:要查询的状态类型。payment 表示支付状态shipping 表示物流状态refund 表示退款状态。}},required:[status_type]}如果不使用enum模型可能生成各种不稳定的值例如物流状态 发货情况 delivery shipping_status 快递这些值对人类来说意思接近但对后端代码来说可能完全无法匹配。因此能枚举的字段尽量枚举能限制格式的字段尽量限制格式。13. tool_choice自动调用、强制调用与禁用工具tool_choice用来控制 Claude 是否使用工具以及使用哪个工具。常见策略有三种13.1 自动选择工具让 Claude 自己判断是否需要调用工具。适合大多数对话场景例如用户可能问普通问题也可能查询订单也可能搜索商品。这种情况下可以传入tools但不强制指定具体工具。13.2 强制调用某个工具适合必须结构化输出或必须走业务系统的场景。例如你希望 Claude 一定调用get_order_status{tool_choice:{type:tool,name:get_order_status}}适合场景表单信息抽取固定接口查询参数解析必须经过后端校验的业务流程。13.3 禁止工具调用适合纯文本生成任务例如写文章总结内容翻译文本生成标题普通知识问答。最简单的方式是不要传tools。如果你使用的 SDK 或 API 版本支持显式禁用工具也可以根据 Anthropic 官方文档进行配置。由于 API 字段可能随版本变化建议以最新官方文档为准。14. temperature 和 max_tokens 如何设置在工具调用场景中一般建议降低temperature。原因是工具调用更关注参数稳定工具选择准确输出结构可控行为可预测。通常可以设置为{temperature:0,max_tokens:1024}当然并不是所有场景都必须设置为 0。如果你的任务需要一定创造性例如工具结果返回后生成营销文案可以适当提高 temperature。但对于订单查询、支付、退款、库存、权限这类业务场景建议优先使用低温度配置。15. 多工具调用时的处理方式在复杂场景中Claude 可能一次返回多个tool_use。例如用户问帮我查一下订单 OD20240601001 的物流状态再看看有没有同款商品还在售。Claude 可能同时请求两个工具get_order_statussearch_products后端需要分别执行每个工具并分别返回对应的tool_result。关键点是每个tool_result都要对应正确的tool_use_id。伪代码示例consttoolResults[];for(constblockofresponse.content){if(block.typetool_use){constresultawaitexecuteTool(block);toolResults.push({type:tool_result,tool_use_id:block.id,content:JSON.stringify(result)});}}然后把所有工具结果一起回传给 Claude。16. 工具执行失败时怎么处理真实业务系统中工具调用失败很常见例如订单不存在用户未登录权限不足第三方接口超时参数格式错误数据库异常。不要直接让程序崩溃也不要返回空字符串。更推荐返回结构化错误信息例如{success:false,error_code:ORDER_NOT_FOUND,message:未找到订单 OD20240601001}再通过tool_result回传给 Claude。Claude 可以根据错误信息生成更友好的回复没有查询到订单 OD20240601001。请确认订单编号是否正确或提供下单手机号后四位继续查询。这样可以显著提升用户体验。17. 常见坑位与排查建议17.1 把 Claude 当成真正的函数执行器Claude 不会真正执行函数。它只会返回工具调用请求。错误理解Claude 会自动调用我的后端函数。正确理解Claude 会告诉你它想调用哪个工具真正执行动作的是你的服务端。17.2 忘记处理 stop_reason tool_use如果返回结果中stop_reason是tool_use说明 Claude 正在等待工具结果。此时不能直接把这一轮响应当最终回复展示给用户而应该执行工具并继续下一轮请求。17.3 tool_use_id 对不上tool_result.tool_use_id必须等于上一轮tool_use.id。如果 ID 不匹配Claude 无法判断工具结果属于哪次调用。17.4 工具描述太模糊例如查询数据。这类描述会导致 Claude 不知道什么时候调用也不知道和其他工具的边界。应该写清楚工具用途调用条件不适用场景参数含义。17.5 input_schema 太宽松如果 schema 没有限制模型可能生成难以处理的参数。例如后端只接受payment shipping refund但模型可能返回物流状态 快递 delivery解决方式是使用enum或更清晰的字段描述。17.6 后端不做参数校验这是非常危险的做法。工具调用中的参数来自模型推断本质上仍然是不可信输入。必须做必填校验类型校验格式校验权限校验业务规则校验风险操作二次确认。17.7 工具过多且边界重叠如果一次传入过多工具并且描述相似Claude 选错工具的概率会上升。建议只传当前场景需要的工具拆分工具职责避免多个工具功能重叠在 description 中写清楚边界。18. 推荐的后端接入结构一个相对清晰的 Claude Tool Use 后端结构可以分为几层Controller ↓ Claude Client ↓ Tool Use Parser ↓ Tool Router ↓ Tool Handler ↓ Business Service职责划分如下模块职责Controller接收用户请求Claude Client调用 Claude Messages APITool Use Parser解析 Claude 返回的 tool_useTool Router根据工具名分发处理器Tool Handler校验参数并调用业务服务Business Service执行真实业务逻辑Tool Result Builder构造 tool_result 并回传 Claude这样设计的好处是工具扩展更方便业务逻辑更清晰更容易做日志追踪更容易做权限控制更容易处理异常。19. 最佳实践总结实现 Claude Function Calling / Tool Use 时可以遵循以下实践工具名使用清晰的英文动词短语例如get_order_status、search_products。description 写清楚调用时机不只写“能做什么”还要写“什么时候用”。input_schema 尽量严格必填字段、字段类型、枚举值都要明确。后端必须做参数校验不要信任模型生成的参数。高风险操作要二次确认例如退款、取消订单、删除数据、修改权限。处理好stop_reason tool_use它表示 Claude 正在等待工具结果。正确维护tool_use_idtool_result 必须和 tool_use 一一对应。不要给 Claude 传过多无关工具只传当前任务需要的工具减少误调用。工具执行结果尽量结构化建议返回 JSON方便 Claude 理解。做好日志和链路追踪记录用户输入、tool_use、tool_result、最终回答方便排查问题。20. 小结Claude API 的 Function Calling 本质上是 Anthropic 的Tool Use能力。它并不会直接执行函数而是通过tool_use告诉后端想调用哪个工具需要哪些参数当前为什么需要暂停等待工具结果。后端执行真实函数后再通过tool_result把结果回传给 ClaudeClaude 才会生成最终自然语言回答。如果要稳定落地 Claude 工具调用重点不在于“让模型调用函数”这个概念本身而在于工具定义是否清晰参数 schema 是否严格后端分发是否可靠权限和参数校验是否完善异常情况是否可控。对于订单查询、业务系统接入、实时数据检索、Agent 工作流等场景Claude Tool Use 是非常实用的能力。只要把工具边界、参数约束和后端安全控制做好就可以构建出稳定可靠的 Claude API 工具调用系统。