(OpenClaw 前置知识)请解释 Tool Calling(工具调用)的完整链路:工具是怎么定义的、LLM 怎么调用它、结果怎么回传
- 标签:AI、OpenClaw、大模型应用开发、AI应用开发、Agent开发
🏛 业务架构师
Tool Calling 的完整链路分四段,我把关键点串起来:
1. 工具定义(供给侧):把能力封装成标准描述——名称、功能说明(写给模型看的"使用说明书")、参数 JSON Schema(类型、必填、枚举、含义)、返回值说明。MCP 协议下这些通过 tools/list 自动暴露给客户端。描述质量是第一生死线:描述含糊,模型就会选错工具、传错参数。
2. 模型决策(推理侧):用户请求+工具清单一起进入模型上下文,模型判断是否需要工具、选哪个、参数是什么,输出结构化调用意图(如 {"name": "query_order", "arguments": {"order_id": "A1024"}})——注意模型只是"说"要调什么,自己不能执行。
3. 运行时执行(工程侧):Agent 框架/应用代码接住意图,做安全检查(鉴权、参数校验、限流)后真正调用后端 API/数据库,拿到结果。这一段是企业加治理的地方——审计日志、幂等、超时重试都在这层。
4. 结果回传(闭环):工具结果作为"工具消息"回填对话上下文,模型基于真实数据生成最终回答,或决定继续调用下一个工具(形成 ReAct 循环)。
业务提醒:链路里最脆弱的是 1 和 4——工具描述要持续按 badcase 优化;工具返回的超大结果要截断/摘要后再回传,否则撑爆上下文窗口。工具调用成功率应该作为核心指标埋点监控。
🏗 系统架构师
Tool Calling 完整链路我按定义 → 调用 → 回传三段讲,并标出每段的生产考点:
工具定义(写给人看,更是写给模型看):
- 三要素:
name(语义化唯一名)、description(何时用、怎么用、返回什么——这段文字决定模型选择准确率,要当产品文档写)、inputSchema(JSON Schema 约束参数类型/枚举/必填); - 定义随请求注入模型上下文(函数声明),工具数量控制在几十个内,超了要分组按需注入。
调用决策(模型只产意图,不碰执行):
- 模型结合任务输出结构化意图:
{"name": "query_order", "arguments": {"order_id": "A123"}}——可以是并行多工具调用; - 框架层做三道校验:Schema 合法性、权限(该用户可用此工具吗)、安全(高危/非幂等操作挂审批)。
结果回传(决定下一轮推理质量):
- 执行层(HTTP/MCP/本地函数)返回结果,封装为 tool role 消息回填上下文;
- 大小控制是生产关键:超大结果(几十 KB)先摘要/截断/落盘回填引用,否则窗口被一个工具结果打爆;
- 错误返回结构化信息(错误码 + 建议动作),模型才能改道而不是傻重试;
- 结果回填后模型继续推理:再调用、换工具、或产出最终答案(循环直到无工具调用)。
架构本质:这是一个把"自然语言意图"翻译成"确定性 API 调用"的适配器协议——模型负责语义,工程负责可靠性。
💻 全栈开发专家
Tool Calling 完整链路三段:定义→调用→回传,我用真实实现讲:
1. 工具定义(开发时):核心是「名称 + 描述 + 参数 JSON Schema」,描述写给模型看:
java
@Tool(name = "query_train", description = "查询两城市间的火车票,用户提到坐火车/高铁时使用")
public TrainTicket queryTrain(
@ToolParam(description = "出发城市,如'北京'") String from,
@ToolParam(description = "日期,格式 yyyy-MM-dd") String date) { ... }框架把这个方法转成 JSON Schema 随请求发给模型(OpenAI 的 tools 字段、Anthropic 的 tool_use)。
2. 模型发起调用(运行时):模型读到用户问题,输出一个结构化 tool call(不是执行!):{"name":"query_train","arguments":{"from":"北京","date":"2026-10-25"}}。模型只产生意图和参数。
3. 结果回传:运行时校验参数 → 执行函数 → 把返回值序列化成 tool result 消息追加到对话 → 再调模型,模型基于结果生成自然语言回答(或发起下一个调用):
json
{"role": "tool", "tool_call_id": "call_1", "content": "{\"trains\":[...]}"}踩坑经验:一是参数幻觉(编造不存在的枚举值),必须 JSON Schema 校验 + 错误信息回喂让模型重试;二是结果要做裁剪(裁掉大 JSON 无关字段),超大结果会污染上下文;三是写操作加幂等键——模型层重试、网络层重试叠加时防重复副作用。