AI Agent 工程实践(13):Tool Calling——Agent 为什么要学会用工具?

发布时间:2026/7/22 6:58:19

AI Agent 工程实践(13):Tool Calling——Agent 为什么要学会用工具? 发布时间2026-07-12标签AI AgentLLMTool CallingFunction Call工程实现系列导航上一篇AI Agent 工程实践12为什么很多 Multi-Agent 项目最后都失败了下一篇AI Agent 工程实践14MCP——为什么它正在成为 Agent 的 USB 接口本文是 [AI Agent 工程实践] 系列的第 13 篇第二季 · 工程实现。Agent 最让人憋屈的时刻它分析了一堆然后告诉你你应该改这个函数——但你得自己去改。它能认识问题不能动手解决问题。像一个只出方案、不下工地的顾问。让它能动起来的只有一个东西Tool。Tool 是 Agent 的手——没有它再聪明的 Agent 也只是个聊天机器人。但很多人把 Tool Calling 要么想得太简单在 prompt 里写个命令就行要么想得太复杂需要一套完整的插件系统。这一篇讲清楚中间态Tool Calling 到底怎么设计从 Schema 到 Registry 到 Selection 到 Retry让 Agent 不只是说而是做。本文你将学到✓ Agent 为什么必须会用工具——以及不用工具时能力的上限在哪✓ Tool 的六层能力梯度从 LLM 内嵌到 Shell/Database 外部系统✓ Tool Calling 四大核心概念Registry / Schema / Selection / Retry✓ 一个可复用的 Tool Calling 设计模板——直接拿到项目里用适合阅读✓ 用 Function Call 做过 Agent、但觉得调用不稳定的人✓ 在搭 Agent 的工具系统、不确定怎么组织和管理的人✓ 被 Tool Calling 格式漂移折磨过的开发者问题背景Agent 前几篇搭好了记忆10、工作流11、决策框架12但还缺一条腿它怎么和外部世界交互。没有 Tool 的 Agent能力边界就是 LLM 的知识截止日期 上下文。它能写代码但不能跑代码能建议你查数据库但不能自己查能告诉你你去搜一下但不能自己搜。这就是 Tool Calling 要解决的问题让 LLM 从说变成做。但 Tool Calling 不是简单地在 prompt 里加一句你可以调用以下函数。它涉及四个实际的工程问题Tool 怎么声明——LLM 怎么知道有这个工具、参数是什么Tool 怎么选择——有 50 个工具时怎么选对的Tool 怎么调用——调用格式不稳定怎么办Tool 调用失败怎么办——重试换工具降级一句话没有工具的 Agent 是顾问有工具的 Agent 是工程师。而从顾问到工程师差的不是一行 prompt是一整套工具调用系统。错误尝试第一次在 prompt 里手写工具调用最早的Tool Calling就是一段 prompt当需要查数据库时输出 SQLSELECT * FROM ...我会执行后把结果贴给你。结果格式经常漂移——有时输出 SQL有时直接输出解释有时忘了加 。更致命的是模型会幻想SQL 语法——它写了SELECT * FROM nonexistent_table我执行失败后它说那你先建表——没有约束的 Tool Calling 就是和模型玩文字游戏。第二次给每个工具硬编码调用逻辑吸取教训工具调用不和模型商量了——硬编码if task db_query: run_sql()。结果灵活度归零。加一个新工具要改 Router 代码第 05 篇的问题重现换一个工具要改调用逻辑。硬编码的工具系统和硬编码的规则系统一样脆弱——不是 Tool Calling是 if-else 地狱。两次尝试指向同一个结论Tool Calling 需要的是声明式管理 结构化调用不是 prompt 里的自由文本也不是代码里的硬编码。它需要一套独立的治理机制。关键观察我把工具调用成功和失败的案例做了对比发现失败集中在四个环节失败环节典型表现占比Schema 不清晰参数类型填错、必填字段遗漏~30%Selection 错误有更合适的工具但没选到~25%调用格式漂移输出了工具描述而不是参数 JSON~25%失败无重试一次调用失败就停了~20%pie title Tool Calling 失败原因分布 Schema 不清晰 : 30 Selection 错误 : 25 调用格式漂移 : 25 失败无重试 : 20没有工具的 Agent 是顾问有工具的 Agent 是工程师。但更准确地说有工具的 Agent 可能是工程师也可能是一个乱用扳手的学徒——Tool Calling 需要治理不只是有就行。问题不在要不要 Tool而在怎么管 Tool——Schema 让 LLM 知道怎么用、Registry 统一管理能力清单、Selection 在多个工具里找到对的、Retry 在失败时兜底。这四个就是 Tool Calling 的治理四件套。最终方案Tool Calling 四件套 六层能力梯度Tool 的六层能力梯度不是所有 Tool 都在同一层级。从模型内部到外部系统能力是逐级梯度扩展的越往右Tool 离 LLM 越远风险越大LLM 内嵌推理零风险Shell 命令可能删库。Tool 设计的第一原则危险性越高的 Tool越需要 Schema 约束和人工审批。四件套Registry / Schema / Selection / Retry1. Tool Registry —— 统一能力清单Registry 是工具注册中心——所有可用工具在这里声明。它不是代码里的字典是可被 LLM 读取的声明文件# tool-registry.yaml browser_search: schema: search.yaml # 工具 Schema 引用 risk_level: low db_query: schema: query.yaml risk_level: medium retry: 3 # 最大重试次数 shell_exec: schema: shell.yaml risk_level: high requires_approval: true # 高危工具需审批Registry 的作用让加工具不需要改代码。新工具加一个 yaml 就上线和第 05 篇 Rule Router 的加 heavy 文件同一种设计哲学。2. Tool Schema —— 契约式声明每个 Tool 必须有 JSON Schema定义名称、描述、参数类型、约束条件。LLM 不认识你的代码但一定认识 Schema{ name: db_query, description: 执行一个只读 SQL 查询。仅支持 SELECT。, parameters: { type: object, properties: { sql: { type: string, description: 要执行的 SELECT 语句, pattern: ^SELECT.*$ // 只允许 SELECT }, database: { type: string, enum: [users, orders] // 限定可查的库 } }, required: [sql] } }Schema 是 Tool Calling 的契约——LLM 按契约填参数系统按契约校验。没有 Schema 的 Tool等于没有接口文档的 API。3. Tool Selection —— 在多个工具里找对的50 个工具时该用哪个不是 LLM 靠直觉判断的——需要 Selection 机制按任务类型路由和第 05 篇 Router 同构task_typedb→ 只暴露 db 相关工具按危险等级过滤普通任务只露出risk_level ≤ medium的工具按上下文裁剪当前对话里用过的工具提权没出现过的不建议Selection 不是让 LLM 在海量工具里猜而是先缩小候选集再让 LLM 精准选择——和第 10 篇 Memory 的先过滤再检索同一个模式。4. Tool Retry —— 调用失败后的兜底Tool Calling 的失败不是要不要重试的问题是怎么重试更聪明失败类型策略参数格式错误重试 1 次纠正参数工具不存在不重试找替代工具超时重试 3 次指数退避1s/2s/4s高危工具失败不重试转人工审批def call_with_retry(tool, args, max_retries3): for attempt in range(max_retries): try: return tool.run(args) except SchemaError: # 参数问题 → 纠正重试 args correct_args(args) except ToolNotFound: # 工具不存在 → 找替代 tool find_alternative(tool) except TimeoutError: # 超时 → 退避重试 sleep(2 ** attempt) return fallback() # 全失败 → 降级Retry 不只是再来一次它是根据失败原因换策略——Schema 错就修参数工具不存在就换工具超时就等一等。这是一种带上下文的恢复机制。架构图 / 流程图Tool Calling 完整链路关键点LLM 不直接访问工具——它通过 Schema 描述工具、通过 Selection 筛选工具、通过 Registry 获取工具、通过 Retry 恢复工具。每一层都是让 LLM 和工具之间保持安全距离的防火墙。代码或配置示例完整工具声明Schema Registry# tools/browser_search.yaml name: browser_search description: 使用 Tavily Search API 搜索互联网 parameters: query: type: string description: 搜索关键词 required: true max_results: type: integer default: 5 risk_level: low retry: max: 3 strategy: exponential_backoff# tool-registry.yaml — 统一注册 tools: browser_search: schema: browser_search.yaml risk: low db_query: schema: db_query.yaml risk: medium retry: 3 shell_exec: schema: shell_exec.yaml risk: high requires_approval: true # 高危必审批Tool Calling 入口逻辑def tool_call(task, registry, llm): # 1. LLM 决策需要哪个工具、什么参数 tool_name, args llm.decide(task, toolsregistry.list_schemas()) # 2. Selection校验合法性任务匹配 安全等级 if not registry.is_allowed(tool_name, task): return fallback(Tool not allowed for this task) # 3. 从 Registry 拿到工具实例 tool registry.get(tool_name) # 4. 执行 Retry return call_with_retry(tool, args)代码不长但四个概念全在里面LLM 读 Schema 选工具 → Selection 做合法性校验 → Registry 管理能力 → Retry 兜底执行。设计权衡候选方案优点缺点为什么不选Prompt 手写工具调用零工程格式漂移、无约束、不可靠Tool Calling 不是文字游戏硬编码工具选择稳定不灵活、无法动态扩展每加工具改代码不可持续声明式四件套可扩展、有约束、可恢复需维护 Schema选择理由唯一把 Tool Calling 从碰运气变成可治理的方案Tool Calling 不是越复杂越好。如果你的 Agent 只用一个工具比如只查数据库一个直接调用就够了不需要 Registry。四件套的价值在工具多、风险分层、需要动态扩展时体现。总结✅ Agent 没有 Tool 只是顾问——能做分析不能做事。Tool 是 Agent 的手。✅ 六层能力梯度LLM 内嵌 → Function Call → Python → Browser → Shell → Database越往右离 LLM 越远、风险越大。✅ Tool Calling 四件套Schema契约声明/ Registry统一管理/ Selection安全裁剪/ Retry分类兜底。✅ 核心设计原则LLM 不直接访问工具——通过 Schema 描述、Selection 过滤、Registry 获取、Retry 恢复。✅ 工具少就别上四件套——一个直接调用就够。工具多、风险分层时才值得。参考资料OpenAI Function Calling 官方文档→ Tool Schema 的标准格式与参数约束规范Anthropic — Tool Use 文档→ 声明式 Tool Calling 的设计哲学与安全模型LangChain — Tool 抽象与 Callbacks→ Registry 与 Retry 的工程参考实现第 05 篇Rule Router→ 任务路由思想Tool Selection 的同构设计第 10 篇Memory 架构→ 先过滤再检索模式Tool Calling先 Selection 再执行的同源设计系列导航上一篇AI Agent 工程实践12为什么很多 Multi-Agent 项目最后都失败了下一篇AI Agent 工程实践14MCP——为什么它正在成为 Agent 的 USB 接口本文是 [AI Agent 工程实践] 系列的第 13 篇第二季 · 工程实现。

相关新闻