Agent 学习系列 · 第 3 课

Tool Calling 与函数调用系统

前两课我们聊了「Agent 是什么」和「怎么用 Prompt 调教它」。从这一课开始,进入真正的工程实战。

一句话先立个 flag:真正的 Agent 工程,70% 都是 Tool Engineering。 一个 Agent 聪不聪明,很大程度上不取决于模型本身,而取决于你给它接了什么工具、工具靠不靠谱、调用安不安全。

本节目标很明确——掌握 Agent 的核心能力:Tool Calling(工具调用)。下面 8 个小节,从原理一路打到工程级落地。

图片

一、Tool Calling 原理:LLM 根本不调工具

这是最容易误解的地方。很多人以为「大模型调了工具」,其实完全不是。

LLM 在 Tool Calling 里真正做的事,只有一件:生成一段 JSON Schema。它描述「我要调哪个工具、参数是什么、什么类型」。至于工具怎么执行、结果怎么拿,全是你的系统(代码)负责的。

图片

所以记住一句话:模型从不直接碰工具、不联网、不读库。 它负责「决策」——决定调谁、传什么参数;真正干活的是你写的代码。Agent 的核心可控性,最终落在你的执行层上。

二、OpenAI Function Calling:Schema 怎么设计

以 OpenAI 的 Function Calling 为例,你给模型一个「工具清单」,每个工具带一份 JSON Schema。模型读懂后,返回对工具的调用请求。

一份好的 Schema,三个要素缺一不可:

图片

  • 参数描述(description)

    用自然语言讲清每个参数是干什么的、怎么填。模型靠这个理解语义。

  • 类型约束(type)

    string / number / boolean / enum / object,把取值空间收窄,避免模型瞎填。

  • 必填项(required)

    明确哪些参数不可省略,否则调用直接失败。把硬约束写进 Schema,比在代码里校验更靠前。

Schema 设计得越清楚,模型「翻车」的概率越低。这是 Tool Engineering 里性价比最高的一笔投入。

三、工具路由系统:让 Agent 自己选工具

工具多了,就不能「写死调用顺序」了——那是 Workflow,不是 Agent。Agent 需要动态路由

Tool Router 的任务是:根据当前 Query(用户问题)历史状态(已经做了什么、哪里失败了)、以及各工具的能力描述,从候选集里选出最合适的那个,并生成调用参数。

图片

路由逻辑可以简单(关键词匹配),也可以复杂(让一个小模型专门做路由决策)。但不管怎么做,核心都是同一件事:把「选哪个工具」也变成可观测、可干预的决策。

四、工具可靠性:5 个绕不开的工程问题

接工具最痛苦的不是「调不通」,而是「调着调着就挂了」。工程上这 5 个问题,迟早都会撞上:

图片

  • 超时(Timeout)

    给每次调用设 deadline,超时就中止,不阻塞整个 Agent。

  • 重试(Retry)

    失败自动重试,带指数退避,防止瞬间打爆下游。

  • 幂等(Idempotent)

    重复调用结果一致,才能「放心重试」而不产生副作用。

  • 限流(Rate Limit)

    控制 QPS,避免把第三方服务压垮。

  • 熔断(Circuit Breaker)

    错误率过高时直接切断,快速失败、保护系统。

这 5 个词,是工具调用从「能跑」到「能上线」的门槛。

五、Tool 调用安全:三种注入攻击

工具让 Agent 有了「行动力」,也带来了攻击面。三类注入,每一类都得防:

图片

  • SQL 注入

    永远参数化查询,绝不字符串拼接;用最小权限数据库账号。

  • Shell 注入

    命令走白名单,禁用 eval / 动态拼接,最好在沙箱里隔离执行。

  • Prompt 注入

    工具返回的内容当「数据」处理,不与 System Prompt 同权;隔离 + 过滤,别让外部文本劫持了 Agent 的决策。

安全不是上线后补的,是设计工具时就要内建的。

六、MCP:Agent 与工具的统一协议

前面每接一个工具都要写一套适配,太累了。MCP(Model Context Protocol)的出现就是为了解决这个问题。

图片

它把「Agent  ↔ 工具」的通信标准化成统一协议,核心三件套:

  • Tool Registry(工具注册)

    工具即插即用到统一目录。

  • Resource(资源读取)

    统一读取文件、数据库、API 等资源。

  • Context(上下文注入)

    把外部信息按标准格式喂给模型。

为什么重要? 一次接入,处处可用。不用再为每个工具写定制适配,生态里的工具拿来就能用。

七、工程级 Tool Registry 设计

当工具有十几个、几十个,光有「名字」不够,得有元数据才能被路由、被治理。一份像样的 Tool Registry 元数据至少包含:

图片

  • 名称(name)

    唯一标识,路由时匹配。

  • 能力(description)

    这个工具能解决什么问题。

  • 输入约束(schema)

    参数类型与必填项。

  • 成本(cost)

    每次调用花多少钱 / 多少 token。

  • 延迟(latency)

    预期耗时,用来定超时。

  • 权限(permission)

    可执行 / 需审批 / 禁止危险操作。

有了这套元数据,Router 才能「聪明地选」,运维才能「放心地管」。

八、本节实战:多工具 Agent

理论说完,动手。我们要搭一个能同时用 4 种工具的 Agent:

图片

  • 搜索(Search)

    联网获取实时信息。

  • SQL 查询

    从数据库取数。

  • Python 执行

    跑计算、处理数据。

  • 文件读取

    读本地 / 云上文件。

运行逻辑就是前两课讲的那套:用户提问 → Router 选工具 → 执行工具 → 观察结果 → 反思 → 决定下一步。四个工具共享同一个 Agent Loop,自由组合。一个典型任务可能是:搜索资料 → Python 分析 → 写结果到文件 —— 一气呵成。

💡 这一课没贴完整代码(篇幅所限),核心是把「Tool Calling 的骨架」讲透。下一篇我会带大家真的把这套多工具 Agent 跑起来,从 Schema 定义到执行循环逐行写。

本节重点回顾

图片

  • LLM 只造 Schema,不调工具——真正执行在你写的代码里。

  • Schema 三要素(描述 / 类型 / 必填)决定调用成败。

  • Tool Router + Tool Registry 是 Agent 的骨架:会选、可控、可治理。

  • 可靠性(超时/重试/幂等/限流/熔断)与安全性(防注入)是上线的底线。