工具调用与 Agent:模型如何从会说话变成会做事?
本篇是「小模型训练系列」第 11 篇:从 Function Calling、工具 schema、参数校验、行动权限、Agent 循环、日志、回滚与人工确认出发,解释模型如何从生成文字走向可控行动。
正在沿着「小模型训练系列」系统学习,希望把概念、工程和真实判断串起来的读者。
上一篇讲推理与部署时,核心问题是:
模型能力如何稳定、可控、可负担地跑起来。
当模型已经能稳定回答问题,下一个问题会自然出现:
它能不能替人做事?
比如:
- 查询数据库
- 调用接口
- 创建日程
- 整理文件
- 生成报表
- 提交工单
- 检索资料后再写总结
- 根据用户要求触发一串工作流
这就是工具调用和 Agent 开始进入视野的地方。
但这里有一个很容易误解的点:
Agent 不是“让模型自由执行代码”。
更准确地说:
Agent 是把模型的语言判断,放进一套可控行动系统里。
模型负责理解意图、拆解任务、选择下一步。
工具负责执行具体动作。
系统负责限制权限、校验参数、记录日志、处理失败、必要时让人确认。
如果只看到“模型会调用工具”,而没有看到背后的权限、状态和审计,Agent 很容易从一个助手变成一个不可控的黑盒。
1. 先把“说话”和“做事”分开
普通聊天模型主要输出文字。
用户问:
明天杭州天气怎么样?
模型可以根据已知信息回答。
但如果要求它:
帮我查明天杭州天气,然后把结果写进我的日程备注。
这就不是单纯生成文字了。
它至少涉及两类动作:
- 查询天气
- 修改日程
第一步需要访问外部数据。
第二步会改变外部状态。
这两个动作的风险完全不同。
查询天气,通常是低风险。
修改日程,已经开始影响用户的真实生活。
如果再换成:
帮我把这笔款打出去。
那就不只是技术问题,而是权限、责任和安全问题。
所以工具调用的第一条原则是:
模型可以提出行动建议,
但行动必须经过系统边界。
模型不是直接伸手改变世界。
它要先把意图变成一个结构化请求。
系统再判断这个请求能不能执行。
2. Function Calling 解决了什么
Function Calling 可以理解成:
让模型不要只输出一段自然语言,而是按约定格式提出一次工具调用。
比如模型不再回答:
准备查询杭州天气。
而是输出类似这样的结构:
{
"tool": "get_weather",
"arguments": {
"city": "杭州",
"date": "明天"
}
}
这件事非常重要。
因为自然语言适合人读。
结构化调用适合系统执行。
如果模型只说:
查一下杭州明天的天气
程序还要猜它到底想调用哪个接口、参数是什么、日期怎么解析、城市是否合法。
Function Calling 把这个过程变得更明确:
模型负责选择工具和填参数
系统负责校验参数并执行工具
一个最简单的工具调用链路长这样:
flowchart LR
A["用户意图"] --> B["模型理解任务"]
B --> C["选择工具"]
C --> D["生成结构化参数"]
D --> E["系统校验"]
E --> F["执行工具"]
F --> G["返回工具结果"]
G --> H["模型组织最终回答"]
这条链路的关键,不是模型“更像人”。
而是模型开始进入工程系统:
文字判断 → 结构化请求 → 可校验执行 → 可追踪结果
3. 工具不是 Prompt,它是契约
工具调用最容易出错的地方,是把工具当成一段提示词。
比如只告诉模型:
你可以调用查询订单工具。
这还不够。
一个真正可用的工具,至少要定义清楚:
| 维度 | 要回答的问题 |
|---|---|
| 工具名 | 这个工具叫什么 |
| 用途 | 什么时候该用,什么时候不该用 |
| 参数 | 需要哪些字段,字段类型是什么 |
| 约束 | 哪些值合法,哪些值禁止 |
| 权限 | 谁能调用,什么场景能调用 |
| 返回 | 成功和失败分别返回什么 |
| 副作用 | 会不会改变外部状态 |
| 审计 | 调用记录保存在哪里 |
工具的本质是契约。
模型必须知道这个契约。
系统也必须按这个契约检查模型。
一个天气查询工具,可能长这样:
{
"name": "get_weather",
"description": "查询指定城市某一天的天气预报",
"parameters": {
"city": "string",
"date": "string"
},
"side_effect": "none"
}
一个日程修改工具,则完全不同:
{
"name": "update_calendar_event",
"description": "修改用户日程",
"parameters": {
"event_id": "string",
"note": "string"
},
"side_effect": "write",
"requires_confirmation": true
}
查询工具和写入工具,不应该享受同样的权限。
低风险工具可以自动执行。
高风险工具必须确认。
这不是保守。
这是 Agent 能长期可用的前提。
4. 参数校验:不要相信模型填的一切
模型生成的工具参数,不能直接执行。
原因很简单:
模型会犯错。
它可能把城市填错,把日期理解错,把订单号补全成不存在的值,甚至把一个危险动作包装成普通动作。
所以工具调用必须有参数校验。
参数校验至少包括:
- 字段是否齐全
- 类型是否正确
- 枚举值是否合法
- 长度是否超限
- ID 是否属于当前用户
- 是否触发敏感动作
- 是否需要人工确认
可以把模型看作一个很聪明但容易兴奋的实习生。
它会提出方案。
但真正执行前,系统要检查表单有没有填对。
一个安全的调用过程更像这样:
flowchart TD
A["模型生成工具调用"] --> B{"参数格式正确吗"}
B -->|"否"| C["拒绝执行并要求修正"]
B -->|"是"| D{"权限允许吗"}
D -->|"否"| E["拒绝并记录风险"]
D -->|"是"| F{"是否有副作用"}
F -->|"无副作用"| G["直接执行"]
F -->|"有副作用"| H{"是否需要确认"}
H -->|"需要"| I["请求人工确认"]
H -->|"不需要"| J["执行并记录日志"]
I --> K{"确认通过吗"}
K -->|"否"| L["取消执行"]
K -->|"是"| J
这张图里的重点不是复杂。
重点是:
模型负责提出调用
系统负责决定能不能执行
没有这层校验,Agent 就不是助手,而是一个会随机点按钮的系统。
5. 工具调用不等于 Agent
工具调用和 Agent 经常被放在一起说,但它们不是一回事。
工具调用是一种能力:
模型能按结构化格式请求外部工具。
Agent 是一种系统形态:
模型能围绕目标,多步观察、决策、行动、反馈,直到任务完成或停止。
可以这样区分:
| 概念 | 核心问题 | 典型形态 |
|---|---|---|
| 工具调用 | 这一步该调用哪个工具 | 单次函数调用 |
| 工作流 | 按固定流程执行哪些步骤 | 规则编排 |
| Agent | 在不确定环境里下一步做什么 | 观察-决策-行动循环 |
比如:
查一个订单状态
这可能只是一次工具调用。
用户投诉订单迟迟没到,判断原因、查物流、查售后政策、给出处理建议
这可能是一个工作流。
帮我排查这个线上问题,自己查看日志、定位异常、提出修复建议,并在我确认后创建工单
这才更像 Agent。
Agent 的关键不是调用工具多。
而是它需要根据中间结果决定下一步。
6. Agent 的基本循环
很多 Agent 系统可以抽象成一个循环:
观察 → 思考 → 行动 → 观察结果 → 再决定下一步
画成图大概是:
flowchart LR
A["目标"] --> B["观察当前状态"]
B --> C["判断下一步"]
C --> D["调用工具 / 执行动作"]
D --> E["获得结果"]
E --> F{"任务完成了吗"}
F -->|"完成"| G["输出结果"]
F -->|"未完成"| B
F -->|"失败 / 风险过高"| H["停止并请求人工介入"]
这个循环看起来很美。
但危险也在这里。
如果没有停止条件,Agent 可能反复尝试。
如果没有权限控制,Agent 可能做不该做的事。
如果没有日志,出了问题不知道它为什么这么做。
如果没有人工确认,高风险动作可能被自动执行。
所以 Agent 的难点不是“会不会循环”。
真正难的是:
什么时候继续
什么时候停止
什么时候交给人
7. 为什么 Agent 容易失控
Agent 容易失控,不是因为模型坏。
而是因为系统给了它太多模糊空间。
常见失控方式有几类。
7.1 目标不清
用户说:
帮我优化一下这个项目。
这个目标太大。
模型可能不知道是优化性能、代码结构、文案、部署、成本,还是用户体验。
目标越模糊,Agent 越容易展开成一串不受控动作。
7.2 工具边界不清
如果系统给模型一堆工具,却没有说明边界,模型可能随意选择。
比如同样是“处理用户问题”,它可能调用:
- 查询订单
- 退款接口
- 修改地址
- 发送短信
- 创建工单
如果这些工具都暴露给模型,却没有权限区分,风险会迅速上升。
7.3 中间结果不可验证
Agent 每一步都依赖前一步的结果。
如果前一步错了,后面可能一路错下去。
例如第一次检索找错文档。
后面再总结、判断、执行,全部建立在错误材料上。
这就是为什么 Agent 需要中间状态可见。
不是只看最后答案。
还要知道:
它查了什么
为什么查
工具返回了什么
下一步依据是什么
7.4 没有停止条件
如果 Agent 一直觉得“还可以再试一次”,就可能陷入循环。
比如:
搜索不到 → 换关键词 → 还是搜索不到 → 再换关键词 → 继续搜索
这看起来很努力。
但系统成本会被消耗,用户也会一直等待。
所以 Agent 必须有预算:
- 最多尝试几次
- 最多调用多少工具
- 最长运行多久
- 失败后怎么返回
没有预算的 Agent,很难上线。
8. 工具分级:不是所有动作都能自动执行
要让 Agent 稳定,工具最好分级。
可以先用三类理解:
| 工具类型 | 示例 | 风险 | 处理方式 |
|---|---|---|---|
| 只读工具 | 查天气、查订单、查文档 | 低 | 可自动执行,但要记录 |
| 低风险写入 | 创建草稿、生成待办、保存摘要 | 中 | 可执行,但要可撤销 |
| 高风险写入 | 退款、转账、删除数据、发送正式通知 | 高 | 必须人工确认 |
这个分级非常重要。
因为很多 Agent Demo 只展示了:
模型成功调用工具
但真实系统要问:
这个工具有没有副作用?
副作用能不能撤销?
调用前是否需要确认?
调用后是否能追责?
读工具和写工具不是一个级别。
可撤销动作和不可撤销动作也不是一个级别。
真正可靠的 Agent,不是所有事情都自动做。
而是知道哪些可以自动,哪些必须停下来请人确认。
9. 人工确认不是低级,而是安全阀
很多人谈 Agent 时,会把“需要人确认”看成不够智能。
这其实是误解。
人工确认不是系统失败。
它是高风险动作的安全阀。
比如下面这些动作,就不应该让模型直接完成:
- 删除生产数据库
- 给客户正式退款
- 对外发送法律相关通知
- 修改合同条款
- 执行付款
- 批量发送营销短信
- 自动封禁用户账号
这些动作不是不能由 AI 辅助。
而是 AI 应该先生成草案、整理证据、说明风险,再由人确认。
更稳的流程是:
flowchart LR
A["模型整理行动建议"] --> B["列出依据与风险"]
B --> C["生成待确认操作"]
C --> D["人工查看"]
D --> E{"是否批准"}
E -->|"批准"| F["系统执行"]
E -->|"拒绝"| G["取消 / 修改方案"]
F --> H["记录日志"]
G --> H
这不是削弱 Agent。
这是让 Agent 进入真实业务。
没有人工确认的高风险 Agent,只适合演示,不适合长期使用。
10. 日志:Agent 的黑匣子
Agent 做事必须留下痕迹。
如果系统只保存最后答案,而不保存中间过程,出问题时很难复盘。
至少要记录:
- 用户原始请求
- 模型拆解出的任务
- 选择了哪些工具
- 每次工具调用参数
- 工具返回结果
- 模型基于结果做出的判断
- 是否触发人工确认
- 最终执行了什么
- 失败原因和重试次数
这不是为了堆日志。
而是为了回答三个问题:
为什么这么做?
哪里出错了?
下次怎么改?
没有日志,Agent 就像一个只交最终答案、不写过程的学生。
答案对了,看起来很好。
答案错了,完全不知道错在哪里。
日志是 Agent 的黑匣子。
也是后续评估和训练的数据来源。
11. 回滚:做错以后能不能退回来
只读工具出错,通常只是回答不准。
写入工具出错,可能会改变真实世界。
这时就需要回滚设计。
比如:
| 动作 | 是否容易回滚 | 风险 |
|---|---|---|
| 生成一份草稿 | 容易 | 低 |
| 新建一个待办 | 较容易 | 低 |
| 修改日程备注 | 较容易 | 中 |
| 删除文件 | 取决于回收站 / 备份 | 中高 |
| 退款 | 通常难 | 高 |
| 转账 | 通常不可逆 | 极高 |
回滚不是事后才想的。
它应该在工具设计时就进入 schema 和权限策略。
比如工具可以标记:
{
"name": "delete_file",
"side_effect": "destructive",
"reversible": false,
"requires_confirmation": true
}
如果一个工具不可逆,就必须更严格。
如果一个动作不可回滚,就不应该让模型自动执行。
这条原则非常朴素:
不可逆动作,不交给不确定判断直接执行。
12. Agent 不是越自主越好
很多 Agent 产品喜欢强调:
全自动
自主规划
无需人工
但真实业务里,自主性不是越高越好。
更好的问题是:
哪些环节应该自动?
哪些环节应该辅助?
哪些环节必须由人决策?
可以用一张表判断:
| 场景 | 适合模型做什么 | 是否应自动执行 |
|---|---|---|
| 总结会议纪要 | 整理重点、生成草稿 | 可以 |
| 查询订单状态 | 调工具查询、组织回答 | 可以 |
| 判断退款资格 | 整理规则和证据 | 不宜直接退款 |
| 修改客户资料 | 生成建议修改项 | 需要确认 |
| 排查线上问题 | 查日志、定位线索 | 修复动作要确认 |
| 财务付款 | 准备资料、提醒流程 | 不应自动付款 |
Agent 的价值,不是替人承担所有判断。
而是把重复、繁琐、信息密集的环节先处理掉,让人只在关键节点决策。
这反而更符合生产环境。
13. 工作流和 Agent 怎么配合
并不是所有任务都需要 Agent。
很多任务用固定工作流更稳定。
比如报销流程:
上传票据 → OCR 识别 → 校验金额 → 匹配规则 → 人工确认 → 提交审批
这类流程不需要模型每一步自由发挥。
模型更适合承担其中一部分:
- 提取票据信息
- 判断异常点
- 解释为什么不通过
- 帮用户补全说明
整体流程仍然由规则控制。
可以把系统分成三层:
flowchart TB
A["规则工作流"] --> B["确定步骤与权限"]
C["模型"] --> D["理解意图 / 生成参数 / 解释结果"]
E["工具"] --> F["执行查询或操作"]
B --> G["可控业务流程"]
D --> G
F --> G
这比“所有事情都交给 Agent 自己想”更稳。
成熟系统里,Agent 往往不是替代工作流。
而是嵌入工作流。
规则负责边界。
模型负责理解。
工具负责执行。
人工负责关键确认。
14. 小模型适合做 Agent 吗
小模型也可以参与 Agent,但要选对位置。
小模型不一定适合承担复杂长期规划。
但很适合做边界清晰的子任务。
例如:
- 判断是否需要调用工具
- 从用户文本中抽取参数
- 将工具结果改写成易懂语言
- 判断一个请求是否超出权限
- 根据规则生成工单草稿
- 对工具调用结果做简单归因
这些任务相对明确,也容易评估。
小模型真正适合的位置,是“窄而稳”。
大模型可以负责更复杂的规划。
小模型可以负责高频、明确、低风险的局部判断。
一个更实际的组合可能是:
规则系统决定边界
小模型做分类和参数抽取
大模型做复杂理解和总结
工具执行真实动作
人工确认高风险节点
这比单独迷信某个模型更工程化。
15. 工具调用也需要评估
前面的评估体系文章讲过:
模型有没有变好,不能只看几个漂亮样例。
工具调用也是一样。
不能只看:
它成功调了一次工具
而要看:
- 该调用时是否调用
- 不该调用时是否拒绝
- 工具选择是否正确
- 参数是否完整
- 参数是否安全
- 工具失败后是否能处理
- 是否会重复调用
- 是否会越权调用
- 是否能正确解释工具结果
可以把工具调用评估拆成一张表:
| 评估项 | 看什么 |
|---|---|
| 触发准确率 | 该用工具时有没有用 |
| 拒绝能力 | 不该用工具时有没有停 |
| 工具选择 | 是否选对函数 |
| 参数质量 | 字段、类型、边界是否正确 |
| 权限遵守 | 是否越权 |
| 错误恢复 | 工具失败后是否能解释和降级 |
| 结果整合 | 是否把工具结果正确写进回答 |
这类评估非常重要。
因为 Agent 的错误不一定体现在最终文字里。
有时答案看起来很自然,但工具调用已经错了。
如果没有工具级评估,系统会误以为模型表现很好。
16. 一个可上线 Agent 的最小形态
刚起步的 Agent,不需要一开始就追求全自动。
更靠谱的最小形态是:
flowchart TD
A["用户请求"] --> B["判断任务类型"]
B --> C{"需要工具吗"}
C -->|"不需要"| D["直接回答 / 解释"]
C -->|"需要"| E["生成工具参数"]
E --> F["参数校验"]
F --> G{"是否高风险"}
G -->|"低风险"| H["执行工具"]
G -->|"高风险"| I["请求人工确认"]
I --> J{"确认通过"}
J -->|"否"| K["取消并说明"]
J -->|"是"| H
H --> L["记录日志"]
L --> M["组织最终回答"]
这个形态看起来不夸张。
但它已经具备几个关键能力:
- 能判断是否需要工具
- 能生成结构化参数
- 有参数校验
- 有风险分级
- 有人工确认
- 有日志
- 有最终回答
这比一个“全自动神奇 Agent”更值得信任。
因为它知道自己的边界。
17. Agent 与 RAG、微调、部署的关系
到这里,可以把前几篇串起来。
Agent 不是孤立技术。
它站在前面几层能力之上。
flowchart TB
A["数据工程"] --> B["Tokenizer / 样本构造"]
B --> C["训练 / 微调"]
C --> D["评估体系"]
D --> E["RAG / 外部知识"]
E --> F["推理与部署"]
F --> G["工具调用与 Agent"]
G --> H["真实业务闭环"]
如果没有数据工程,模型不知道该学什么。
如果没有样本构造,训练目标不清楚。
如果没有评估,无法判断能力是否可靠。
如果没有 RAG,外部知识难以追溯。
如果没有部署,模型无法稳定服务。
如果没有工具和权限,模型无法安全行动。
Agent 是一个上层形态。
底层每一层不稳,Agent 都会放大问题。
所以真正做 Agent,不是跳过基础,直接堆工具。
而是把前面的能力接成系统。
18. 常见误区
误区一:会调用工具就是 Agent
单次调用工具只是能力点。
Agent 需要围绕目标持续观察、决策、行动,并在必要时停止。
误区二:工具越多越强
工具越多,选择空间越大,风险也越大。
没有边界的工具集合,会让模型更容易误用。
工具应该按任务设计,不是越多越好。
误区三:让模型直接写代码执行最灵活
直接执行模型生成的代码风险极高。
更安全的方式是暴露受限工具,让模型在有限动作空间内选择。
误区四:人工确认会降低智能感
人工确认不是退步。
它是高风险动作进入真实业务的必要安全阀。
误区五:Agent 失败只是模型能力不够
很多 Agent 失败不是模型不聪明,而是系统没有权限设计、工具校验、状态管理、日志和回滚。
19. 这篇的核心结论
- 工具调用让模型从自然语言输出,进入结构化行动请求
- 工具不是 Prompt,而是系统契约
- 模型生成的参数必须经过校验,不能直接执行
- 工具调用不等于 Agent,Agent 需要多步观察、决策、行动和停止条件
- Agent 容易失控,通常是因为目标、工具边界、状态和停止条件不清
- 工具应该按风险分级,只读、低风险写入和高风险写入要区别对待
- 人工确认不是低级,而是高风险场景的安全阀
- 日志、回滚、权限和评估,是 Agent 从 Demo 走向真实业务的关键
- 小模型适合在 Agent 系统里做边界清晰的局部任务
- 真实 Agent 不是替代工作流,而是嵌入工作流,让系统更会理解和行动
可以用一句话收束:
模型从会说话到会做事,
中间隔着一整套可控行动系统。
没有工具,模型只能建议。
没有权限,工具会变危险。
没有日志,行动无法复盘。
没有确认,高风险动作不可托付。
没有评估,系统不知道自己是不是真的可靠。
Agent 的高级之处,不是“什么都自动做”。
而是:
在合适的边界里自动,
在关键的节点上停下来,
把人、模型、工具和流程放到正确位置。
下一篇预告
《Memory 与工作流:模型如何承接长期任务?》
工具调用解决了“模型如何行动”。
但真实任务很少一步结束。
模型还需要知道:
- 上一步做到了哪里
- 哪些信息已经确认
- 哪些任务还没完成
- 哪些上下文应该保留
- 哪些历史应该压缩
- 中断以后如何恢复现场
下一篇会继续拆开 Agent 的另一块底层能力:Memory 与工作流。
核心观点是:真正可用的 Agent,不只是会调用工具,还要能承接状态、延续任务,并在复杂流程里保持可恢复。
后续章节路线
| 顺序 | 章节方向 | 要解决的问题 |
|---|---|---|
| 第 12 篇 | Memory 与工作流:模型如何承接长期任务? | 对话记忆、任务状态、上下文压缩、恢复现场与流程编排 |
| 第 13 篇 | 行业模型与业务闭环:训练如何进入真实场景? | 领域数据、流程反馈、人工审核、持续评估与灰度改进 |
| 第 14 篇 | 系列总结:从数据到 Agent 的小模型工程地图 | 把训练、微调、评估、RAG、部署和 Agent 串成完整路线 |
持续学习,持续记录,持续筛选
如果这篇对你有用,可以继续沿着主题读下去。
福星家和会长期记录 AI 技术、生活成长、真实好物与正向文化观察。产品体验、人物故事、教育内容、生活方式、文化作品和内容共创都欢迎邮件沟通,合作内容会清楚标注。