大模型工具调用这个概念,最容易让人产生误解。

很多人第一次接触 Function Calling、Tool Calling、LangChain Tools 时,会自然地以为:模型现在可以调用函数了,可以查数据库了,可以执行代码了。

但这并不是事实。

大模型本身并没有进入你的 Python 环境,也没有直接访问数据库,更不会真的替你执行某个业务接口。它真正做的事情,是在理解用户意图之后,生成一段结构化的“调用意图”。至于这个意图能不能执行、由谁执行、执行前是否需要校验、执行后如何把结果再交给模型,这些都发生在模型之外。

所以,工具调用的本质不是“模型执行函数”,而是:

系统定义工具能力,模型负责生成可执行意图,应用系统负责执行真实动作

这个边界非常重要。理解了它,才能真正理解 LangChain、OpenAI Function Calling、Agent 以及后面更复杂的 Harness Engineering。

为什么工具调用会成为大模型应用的关键能力

大模型的优势在语言和推理,而不是实时状态和确定性执行。

比如用户问:

帮我查询订单 1001 的状态,如果可以退款 50%,顺便计算退款金额。

这句话看起来只是一个普通请求,但里面已经包含了两个世界。

一个是语言世界:用户想做什么、订单号是什么、是否存在退款意图、下一步应该怎么处理。

另一个是系统世界:订单状态在哪里查、退款规则是什么、金额怎么计算、是否允许自动退款。

大模型可以很好地理解第一个世界,但它不能凭空知道第二个世界。订单状态必须来自订单系统,退款金额最好由确定性程序计算,退款动作更应该受权限和风控约束。

这就是工具调用出现的原因。

它不是为了让模型“无所不能”,而是承认模型有边界,然后给模型一种和外部系统协作的协议。

模型不需要记住所有业务数据,也不需要自己完成所有计算。它只需要判断:现在是否需要外部能力,如果需要,应该调用哪个工具,参数应该是什么。

真正的业务执行,仍然交给后端系统。

工具调用其实是一种协议设计

从工程视角看,工具调用更像是一种协议,而不是某个框架功能。

OpenAI 的 Function Calling、Anthropic 的 Tool Use、DeepSeek 兼容 OpenAI 风格的工具调用、LangChain 的 Tool 抽象,本质上都在解决同一个问题:

如何让模型把自然语言意图转化成机器可解析的结构,也就是我们说的Tools定义。

OpenAI 里常见的工具定义大概是这样:

{
  "type": "function",
  "function": {
    "name": "get_order_status",
    "description": "根据订单号查询订单状态",
    "parameters": {
      "type": "object",
      "properties": {
        "order_id": {
          "type": "string",
          "description": "订单号"
        }
      },
      "required": ["order_id"]
    }
  }
}

这段结构真正告诉模型的,不是“你可以执行这个函数”,而是:

这里有一个外部能力,名字叫 get_order_status,它适合用来查询订单状态,调用它时需要传入 order_id。

当模型判断需要这个能力时,它会返回类似这样的结构,也就是我们说的Tool_Call 调用意图:

{
  "name": "get_order_status",
  "arguments": {
    "order_id": "1001"
  }
}

注意,这一步还没有真正查询订单。它只是模型表达:“我认为现在应该调用这个工具,并且参数是这样。”

模型把模糊的自然语言,变成了应用系统可以识别、校验和执行的结构化意图。

工具调用的三层结构

如果只看代码,工具调用很容易被理解成一次普通函数调用。但从系统设计角度看,它至少包含三层:模型层、协议层、应用层

这三层分别解决不同问题。

模型层:大模型需要学会输出结构化调用意图

用户提出问题后,模型首先要判断:这个问题能不能直接回答,还是必须借助外部系统。

比如用户问“订单 1001 当前是什么状态”,模型不能凭训练知识回答,因为订单状态是实时业务数据。这时模型需要意识到:当前任务需要调用查询订单的工具。

这一层依赖模型本身的工具使用能力,也依赖工具描述是否清楚。工具名称、description、参数说明写得越准确,模型越容易判断什么时候该调用它。

现如今各种大模型都已经具备了识别了工具调用意图,得力于它们背后工程师对它们数据训练。它们自身开始具备了对工具的认识和调用决策能力。

API 协议层:大模型厂商定义工具结构

模型知道要调用工具还不够,它必须用应用程序能解析的格式表达出来。

这就是 OpenAI、Claude、DeepSeek、Gemini 等厂商定义 tool calling 协议的原因。模型不会直接返回一句“我要查询订单”,而是返回结构化数据,例如工具名、参数、调用 ID 等。

这一层的本质,是把自然语言意图转成机器可解析的结构。没有协议层,应用程序就很难稳定判断模型到底想调用哪个工具、传什么参数。

应用层:业务系统执行工具

模型返回 tool call 后,并不会真的执行函数。真正执行的是应用程序。

应用层要做的事情包括:解析模型返回的调用意图,校验参数,判断权限,找到对应函数或 API,执行工具,并把结果再返回给模型。

LangChain 的价值不在于发明工具调用

很多人学习 LangChain 工具调用时,会误以为工具调用是 LangChain 创造出来的能力。

其实不是。

工具调用首先是模型厂商在 API 层提供的能力。OpenAI、Claude、Gemini、DeepSeek 等模型厂商,负责让模型理解工具描述,并返回符合协议的工具调用结构。

LangChain 的价值在另一层。

它把不同模型厂商的工具协议、消息格式、函数封装、执行结果回填统一起来,让开发者不用每次都处理底层差异。

在 LangChain 里可以被包装成 Tool,再绑定给模型。模型返回 tool call 后,LangChain 会把它放进统一的消息结构里,再通过 ToolMessage 把执行结果返回给模型。

    ## 工具清单,绑定工具
    tools = [get_user_info_tool,get_user_address_tool]
    model = model.bind_tools(tools)
    msglist.append(usermsg)
    ## 1. 思考
    message = model.invoke(msglist)
    ## 2. 执行工具
    message = tool_loop(model,message)

所以 LangChain 更像是工具调用的编排层。

模型厂商提供“能不能识别工具、能不能输出调用结构”的能力;LangChain 提供“怎么把函数、模型、消息、执行循环组织起来”的能力。

这两者不能混为一谈。

真正的难点不是让模型返回 tool_call

从 Demo 角度看,工具调用很容易。

定义一个工具,传给模型,模型返回 tool_call,应用执行函数,再把结果返回给模型。几段代码就能跑起来。

但生产环境里的问题不在这里。

真正的问题是:模型可能选错工具,可能生成错误参数,可能在不该调用工具的时候调用工具,也可能在工具返回失败后继续编造答案。

更麻烦的是,工具一旦连接真实业务系统,风险就不再停留在文本层面。

查询订单还好,最多查错。
如果是删除文件、执行 SQL、发布配置、发起退款、发送客户通知,那就不能把决定权完全交给模型。

所以成熟的工具调用系统,一定会在模型和真实工具之间加一层治理,这也正是Harness Engirneering的核心之一。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐