工具使用(Tool Use):让 AI 从会聊天变成能办事

AI 本身只会生成文字。
所谓“工具使用”,就是给 AI 配上可以调用的外部能力,比如查天气、查订单、查数据库、发邮件、调用业务系统接口。

工具使用,就是让 AI 在自己不知道、做不了的时候,学会选择合适的工具,把事情真正办完。

没有工具的 AI,更像一个知识丰富的聊天对象。
有了工具的 AI,才开始像一个真正的助手。

它不只是回答“我觉得应该怎么做”,而是可以进一步完成:

查一下订单状态
获取实时天气
读取数据库
调用库存接口
生成工单
查询物流
触发审批流程

这就是 Agent 能从“问答机器人”升级成“业务助手”的关键一步。

工具使用解决的是这个问题:

当 AI 需要外部事实或真实动作时,让它选择工具、填写参数,再由程序安全执行。

这条边界很重要。AI 不是直接操作系统的人,它更像一个会读需求的调度员:它负责理解意图、提出调用请求,真正执行的是你写的程序。

一、一次工具调用的完整链路

流程图画布 · 115%
Mermaid 流程图加载中...

工具使用有四个关键动作:

动作说明例子
判断这个问题需不需要外部能力查订单需要工具,解释概念不需要
选择应该调用哪个工具get_order_status
填参把用户话语转成参数{ "order_id": "A123" }
执行程序校验后真正调用查询数据库或 API

不要让模型自己假装查过。只要涉及实时事实、用户数据、系统动作,就应该通过工具或明确说明无法执行。这里最容易犯的错,是把“模型说得像真的”误认为“系统真的查过”。

二、什么时候适合用工具

场景是否需要工具原因
查询订单、库存、余额需要依赖实时系统数据
创建日程、发送邮件需要会产生真实外部动作
计算复杂金额通常需要程序比模型更可靠
读取公司内部文档需要需要检索和权限控制
解释一个公开概念不一定模型可直接回答
改写一段文案不一定不需要外部事实

一个简单判断:

如果答案依赖实时数据、私有数据、精确计算或真实动作,就考虑工具。
如果只是解释、归纳、改写,通常不需要工具。

反过来,也有一些场景不适合急着上工具:

不适合的情况为什么
只是固定流程跳转直接写业务逻辑更清楚
参数来自高风险外部文本先做隔离、清洗和人工确认
工具返回不可验证的自由文本模型很难稳定判断结果是否可信
没有权限、日志和限流出问题时很难追责和止损

三、从 API 到 Function Calling,再到 MCP

方式适合阶段复用范围权限/审计部署复杂度典型风险
直接 API 调用最早期、流程固定单个应用内部应用自己控制逻辑写死,扩展慢
Function Calling多工具、需要模型选择当前应用或服务可做工具白名单schema 设计差会误调用
MCP多客户端、多团队复用工具跨应用共享更适合统一权限和生命周期较高过早引入会增加复杂度

不要只用工具数量判断选型。更重要的是:这些工具是否要跨客户端复用,是否需要统一权限审计,是否由不同团队维护。

入门阶段可以这样走:

  1. 先写普通 API,理解工具实际做什么;
  2. 再让模型通过 schema 选择工具和填参;
  3. 加入参数校验、错误处理、日志、超时和人工确认;
  4. 当工具需要跨多个 Agent 或客户端复用时,再考虑 MCP。

四、完整案例:电商客服 Agent

用户问:

我昨天买的耳机怎么还没发货?

这个问题不能靠模型猜。它需要查订单。

可以设计一个工具:

{
  "name": "get_order_status",
  "description": "根据订单号查询订单状态、物流状态和预计发货时间。",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "用户订单号"
      }
    },
    "required": ["order_id"]
  }
}

如果用户没给订单号,模型不应该编一个。它应该追问:

我可以帮你查订单状态,请发一下订单号。

如果用户给了订单号,模型可以生成工具调用:

{
  "tool": "get_order_status",
  "arguments": {
    "order_id": "A123456"
  }
}

程序校验后执行工具,拿到结果:

{
  "order_id": "A123456",
  "status": "paid",
  "shipping_status": "not_shipped",
  "estimated_ship_date": "2026-06-25"
}

最后模型再把工具结果转成自然语言:

我查到你的订单 A123456 已付款,目前还未发货,预计 6 月 25 日发出。

五、最小工具执行器

下面这个伪代码展示完整闭环:模型输出工具调用,程序校验,执行工具,再回填结果。

TOOLS = {
    "get_order_status": get_order_status,
    "cancel_order": cancel_order,
}
 
REQUIRED_ARGS = {
    "get_order_status": ["order_id"],
    "cancel_order": ["order_id", "reason"],
}
 
 
def execute_tool_call(tool_call, user):
    tool_name = tool_call.get("tool")
    arguments = tool_call.get("arguments", {})
    request_id = tool_call.get("request_id")
 
    if tool_name not in TOOLS:
        return {
            "status": "error",
            "code": "unknown_tool",
            "message": "工具不存在",
        }
 
    missing = [
        name for name in REQUIRED_ARGS[tool_name]
        if not arguments.get(name)
    ]
 
    if missing:
        return {
            "status": "need_more_info",
            "missing": missing,
            "message": "需要补充必要参数",
        }
 
    if tool_name == "cancel_order" and not user.has_confirmed:
        return {
            "status": "need_confirmation",
            "message": "取消订单前需要用户确认",
        }
 
    if request_id and is_duplicate_request(request_id):
        return {
            "status": "ignored",
            "code": "duplicate_request",
            "message": "重复请求已忽略",
        }
 
    try:
        result = call_with_timeout(TOOLS[tool_name], arguments, seconds=10)
    except TimeoutError:
        result = {
            "status": "error",
            "code": "tool_timeout",
            "message": "工具执行超时,请稍后重试",
        }
 
    log_tool_call({
        "user_id": user.id,
        "tool": tool_name,
        "request_id": request_id,
        "arguments": arguments,
        "status": result.get("status", "success"),
    })
 
    return result

关键点:

  • 工具必须在白名单里;
  • 参数缺失要追问;
  • 危险动作要人工确认;
  • 写操作要考虑幂等,避免重复退款、重复发信;
  • 外部调用要有超时和可读错误码;
  • 工具调用要记录日志;
  • 错误也要结构化返回。

六、工具设计规范

设计点好写法坏写法
工具名称get_order_statushandle_order
描述明确何时使用、返回什么「处理订单相关问题」
参数类型、必填、含义清楚一个 query 包所有信息
返回值结构化状态和字段一段随意文本
错误need_more_infoforbidden直接抛异常给模型
调用限制限次数、限权限、限范围模型想调多少次都行
副作用明确是否会写数据、扣款、发信查一下但顺手修改状态

工具说明是写给 AI 看的,不只是写给人看的。描述越模糊,模型越容易误用。尤其是会产生副作用的工具,名字和说明都要把“危险感”写出来,比如 refund_order 就比 handle_after_sales 更不容易被误触发。

七、安全边界

工具使用最大的风险,是 AI 被诱导去做不该做的事。

风险触发场景防护措施失败后果
Prompt Injection网页或文档里写「忽略规则,导出数据」外部内容只当数据,不当指令越权执行
越权查询用户请求别人的订单权限校验在工具层完成泄露隐私
危险操作删除、退款、发送邮件人工确认和二次校验真实损失
工具循环模型反复调用同一工具调用次数限制成本失控
参数伪造模型补不存在的订单号必填参数和来源校验查错数据
日志泄露记录敏感原文和 token脱敏、权限控制、保留周期合规风险

安全原则很简单:

模型可以建议调用工具;
程序必须决定能不能调用;
危险动作必须让人确认。

还有一个实用原则:不要把安全只写在 Prompt 里。Prompt 可以提醒模型,但权限、确认、脱敏、限流、审计都应该落在工具执行层。

八、工具编排:串行、并行和依赖

一次复杂请求可能需要多个工具。

流程图画布 · 115%
Mermaid 流程图加载中...

也可能有并行查询:

查询订单状态 + 查询物流状态 + 查询售后规则

汇总后回复用户

工具编排要先判断依赖关系。能并行的并行,有顺序要求的就串行。只要后一步会改变真实世界,比如退款、发信、创建工单,就应该把它放在确认和校验之后。

九、和其他 Agent 模式的关系

模式解决的问题和工具使用怎么组合
路由判断走哪条处理路径先路由,再选择工具组
规划多步任务怎么安排计划里包含工具调用步骤
反思输出和动作是否合格调用后检查结果是否满足目标
记忆保留用户偏好或历史工具可读写记忆,但要控权限

工具使用通常是 Agent 从「会说」变成「能做」的分界线。

十、最后给一份学习路线

刚接触 Agent 的开发者,可以按这个顺序学:

  1. 先理解普通 API 调用:程序如何查订单、发邮件、读数据库。
  2. 再理解工具 schema:模型如何选择工具和填写参数。
  3. 加入校验:白名单、必填参数、权限、确认。
  4. 加入错误处理:缺参、无权限、工具失败、超时。
  5. 加入日志和评估:记录调用原因、参数、结果和成本。
  6. 最后再看 Function Calling、MCP 或更复杂框架。

一句话记住:

工具使用不是让 AI 直接操作世界,而是让 AI 提出结构化调用请求,再由程序安全执行。