在这里插入图片描述

网罗开发 (小红书、快手、视频号同名)

  大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。


引言

让 Python 第一次调用大模型 API,代码其实非常简单:

from openai import OpenAI

client = OpenAI()

response = client.responses.create(
    model="gpt-5.5",
    input="你好,请介绍一下 Python。"
)

print(response.output_text)

到这里,我们已经可以让 AI:

理解问题
   ↓
生成答案
   ↓
返回结果

但是很快就会遇到一个问题。

如果我问 AI:

上海今天的天气怎么样?

模型可以回答。

但它真的知道今天上海的实时天气吗?

如果我继续问:

帮我查询数据库里订单号 10086 的状态。

模型可以回答:

我无法访问你的数据库。

再比如:

帮我给用户发送一封邮件。

模型可以帮你写邮件内容。

但它真的能够发送吗?

答案是:

仅仅拥有语言能力的大模型,并不能直接操作外部世界。

这就是 AI Agent 出现之前,LLM 应用面临的一个核心问题。

而解决这个问题的关键技术之一就是:

Tool Calling,也就是工具调用。

一、从“会聊天”到“会做事”

我们先看最简单的 ChatBot。

用户
 ↓
大模型
 ↓
回答

例如:

用户:

帮我计算 123 × 456。

模型可能直接计算:

123 × 456 = 56088

但如果我们希望模型调用一个真正的计算器呢?

流程就变成:

用户
 ↓
大模型
 ↓
判断需要计算
 ↓
调用计算器
 ↓
得到结果
 ↓
大模型
 ↓
生成最终答案

这时候,大模型就不再只是一个“聊天机器人”。

它开始具备:

调用外部能力的能力。

这就是 Tool Calling。

二、Tool Calling 到底是什么?

简单来说:

Tool Calling 就是让大模型自己决定什么时候调用你提供的工具,并生成调用工具所需要的参数。

例如我们给模型一个工具:

def get_weather(city):
    ...

然后告诉模型:

你可以调用 get_weather 查询天气。

用户输入:

帮我查询上海今天的天气。

模型不一定直接回答,它可能先返回一个工具调用:

{
  "name": "get_weather",
  "arguments": {
    "city": "上海"
  }
}

然后:

Python
 ↓
执行 get_weather("上海")
 ↓
得到天气数据
 ↓
把结果交给模型
 ↓
模型生成最终回答

注意一个非常重要的概念:

模型通常不是直接执行你的 Python 函数,而是告诉你的程序“应该调用哪个工具、参数是什么”。

真正执行工具的是你的应用程序,这一点一定要理解。

三、Tool Calling 的完整链路

我们把刚才的流程拆开。

第一步:用户提出问题。

帮我查询上海天气。

第二步:Python 把问题和工具定义一起发送给模型。

Python
 ↓
LLM

可用工具:
get_weather(city)

第三步:模型判断。

这个问题需要调用天气工具。

于是返回:

tool call

get_weather
city = 上海

第四步:Python 收到工具调用,然后真正执行

get_weather("上海")

第五步:得到工具结果

{
    "city": "上海",
    "temperature": 28,
    "weather": "晴"
}

第六步:Python 把工具结果再次交给模型,最后模型生成

上海今天晴,气温 28℃。

整个过程:

用户
 ↓
LLM
 ↓
Tool Call
 ↓
Python
 ↓
工具执行
 ↓
Tool Result
 ↓
LLM
 ↓
最终回答

这就是最基本的 Agent 工作闭环。

Tool Calling 完整执行流程**

在这里插入图片描述
图中重点突出两个角色:

LLM 负责“决定调用什么”

Python Runtime 负责“真正执行什么”

四、第一次写一个真正的 Tool

我们先不要接天气 API,自己写一个最简单的工具。

例如:

def calculate(a, b):
    return a + b

这个工具非常简单:

输入:

a
b

输出:

a + b

现在问题来了:

怎么让大模型知道这个工具存在?

答案是:

把工具描述告诉模型。

例如:

tools = [
    {
        "type": "function",
        "name": "calculate",
        "description": "计算两个数字的和",
        "parameters": {
            "type": "object",
            "properties": {
                "a": {
                    "type": "number",
                    "description": "第一个数字"
                },
                "b": {
                    "type": "number",
                    "description": "第二个数字"
                }
            },
            "required": ["a", "b"],
            "additionalProperties": False
        },
        "strict": True
    }
]

这里最重要的不是 Python 函数本身。

而是:

name
description
parameters

这三个信息。

五、为什么需要告诉模型参数?

因为模型需要知道:

这个工具到底怎么使用?

比如:

def get_weather(city):
    ...

模型如果只知道:

get_weather

它并不知道:

需要传什么参数?
城市叫什么?
参数是不是 city?
需要字符串还是数字?

所以我们需要通过 Schema 告诉模型:

{
    "city": "上海"
}

实际上,这就是一种结构化描述。

可以理解成:

Tool
 │
 ├── name
 │
 ├── description
 │
 └── parameters

当前 OpenAI Python SDK 的 Responses API 支持自定义 function tools,并使用 JSON Schema 描述函数参数;也可以通过 strict 对参数进行更严格的约束。

六、让模型真正选择工具

现在我们把工具传给模型。

from openai import OpenAI

client = OpenAI()

tools = [
    {
        "type": "function",
        "name": "calculate",
        "description": "计算两个数字的和",
        "parameters": {
            "type": "object",
            "properties": {
                "a": {"type": "number"},
                "b": {"type": "number"}
            },
            "required": ["a", "b"],
            "additionalProperties": False
        },
        "strict": True
    }
]

response = client.responses.create(
    model="gpt-5.5",
    input="帮我计算 100 + 200",
    tools=tools
)

这里发生了一件很重要的事情。

我们不再只是:

Input
 ↓
Output

而是:

Input
 ↓
LLM
 ↓
Tool Selection

模型开始拥有:

工具选择能力。

七、真正执行工具的是谁?

这是 Tool Calling 最容易被误解的地方。

很多人认为:

AI 调用了我的 Python 函数。

严格来说,并不是。

更准确的流程是:

LLM:

“我需要调用 calculate。”

        ↓

Python:

“好的,我来执行。”

        ↓

calculate(100, 200)

        ↓

300

所以:

LLM 负责决策,Runtime 负责执行。

这也是为什么后面的 Agent Runtime 会越来越重要。

八、完整写一个 Tool Calling Demo

现在我们把整个流程串起来。

import json
from openai import OpenAI

client = OpenAI()


def calculate(a, b):
    return a + b


tools = [
    {
        "type": "function",
        "name": "calculate",
        "description": "计算两个数字的和",
        "parameters": {
            "type": "object",
            "properties": {
                "a": {
                    "type": "number"
                },
                "b": {
                    "type": "number"
                }
            },
            "required": ["a", "b"],
            "additionalProperties": False
        },
        "strict": True
    }
]


response = client.responses.create(
    model="gpt-5.5",
    input="帮我计算 100 + 200",
    tools=tools
)

接下来,我们检查模型有没有产生函数调用。

Responses API 的输出中会包含不同类型的输出项,其中自定义函数调用对应 function_call;随后应用程序需要执行对应函数,并把结果作为 function_call_output 传回模型。

可以这样处理:

for item in response.output:

    if item.type == "function_call":

        print("工具:", item.name)
        print("参数:", item.arguments)

可能得到:

工具: calculate
参数: {"a":100,"b":200}

这时候:

args = json.loads(item.arguments)

result = calculate(
    args["a"],
    args["b"]
)

print(result)

得到:

300

到这里,我们已经真正执行了工具。

九、但是还差最后一步

很多人写到这里就结束了,其实还不完整。

为什么?因为模型只知道:

calculate(100, 200)

返回:

300

但最终回答还应该由模型生成。

所以我们需要把工具执行结果再次发送给模型。

逻辑变成:

第一次请求
 ↓
LLM
 ↓
function_call
 ↓
Python执行
 ↓
function_call_output
 ↓
LLM
 ↓
最终答案

这就是完整闭环。

十、为什么 Tool Calling 是 Agent 的基础?

现在我们再回头看 Agent,很多人觉得 Agent 特别神秘:

Agent
Planner
Memory
Tool
Reasoning
Runtime

实际上,最基础的 Agent 就是:

观察
 ↓
思考
 ↓
选择工具
 ↓
执行工具
 ↓
得到结果
 ↓
继续思考

也就是:

LLM
 ↓
Tool Call
 ↓
Tool
 ↓
Tool Result
 ↓
LLM

如果只有一次调用:

LLM
 ↓
Tool
 ↓
Answer

这是简单的 Tool Calling。

如果可以循环:

LLM
 ↓
Tool
 ↓
Result
 ↓
LLM
 ↓
Tool
 ↓
Result
 ↓
LLM
 ↓
Answer

它就开始接近真正的 Agent Runtime,所以:

Tool Calling 是从 ChatBot 走向 Agent 的关键一步。

ChatBot → Tool Calling → Agent

在这里插入图片描述
这张图重点说明:

Agent 并不是凭空出现的,它是在 Tool Calling 基础上演化出来的。

十一、Tool 不只是计算器

真正的 AI 应用中,工具可能是:

查询天气

get_weather(city)

查询数据库

query_database(sql)

搜索网页

web_search(keyword)

查询订单

get_order(order_id)

发送邮件

send_email(to, subject, content)

创建日历事件

create_calendar_event(...)

甚至:

execute_code(...)

这意味着:

只要 Python 能够调用它,理论上都可以包装成 AI 的 Tool。

例如公司内部系统:

ERP
CRM
OA
HR
财务系统
数据库
知识库

都可以成为 Agent 的工具,这时候 AI 才真正开始进入企业业务。

十二、一个真正的 AI 助手应该是什么样?

假设我们做一个企业 AI 助手,用户说:

查询一下张三最近的订单,如果有延期订单,帮我发邮件提醒销售。

这句话实际上包含了多个动作。

第一步:

查询员工 / 客户信息

第二步:

查询订单

第三步:

判断是否延期

第四步:

生成邮件

第五步:

发送邮件

传统程序可能需要:

if
    query()
if
    check()
if
    generate()
if
    send()

而 Agent 可以通过 Tool Calling 逐步完成:

User
 ↓
Agent
 ↓
查询订单 Tool
 ↓
订单结果
 ↓
LLM
 ↓
发现延期
 ↓
邮件 Tool
 ↓
发送成功
 ↓
LLM
 ↓
完成任务

这就是 AI Agent 真正有价值的地方:

它开始连接真实世界的工具。

十三、Tool Calling 和 MCP 有什么关系?

学到这里,很多人可能会想到:

这和 MCP 有什么区别?

这是一个非常好的问题,可以简单理解:

Tool Calling

解决的是:

模型如何决定调用工具?

而:

MCP

更关注:

工具如何被标准化地暴露给 AI 应用?

例如,传统方式:

Agent
 ↓
Python Function
 ↓
Database

MCP:

Agent
 ↓
MCP Client
 ↓
MCP Server
 ↓
Database

所以两者并不是完全竞争关系。

在很多 AI 系统里,它们反而可以组合:

LLM
 ↓
Tool Calling
 ↓
MCP Tool
 ↓
MCP Server
 ↓
External System

这也是未来 Agent 系统非常重要的一种架构模式。

十四、真正的难点开始出现了

到这里,你可能会觉得:

Tool Calling 好像也没有那么复杂。

确实,基础版本并不复杂。

真正困难的是:

当工具越来越多以后怎么办?

假设一个 Agent 拥有:

100 个工具

甚至:

10000 个工具

模型怎么选择?

工具描述怎么管理?

工具权限怎么控制?

工具调用失败怎么办?

多个工具能不能并行?

工具执行超时怎么办?

数据库返回错误怎么办?

用户没有权限怎么办?

这时候系统就不再只是:

LLM + Function

而开始出现:

Tool Registry
Tool Router
Permission
Scheduler
Runtime
State
Memory
Retry
Timeout

这就是为什么:

真正复杂的 Agent,核心不是“让模型调用工具”,而是“如何可靠地调度工具”。

从 Tool Calling 到 Agent Runtime

在这里插入图片描述

十五、总结

这是一次非常重要的升级。

最开始:

Python
 ↓
LLM
 ↓
文本

现在:

Python
 ↓
LLM
 ↓
Tool
 ↓
External System
 ↓
Result
 ↓
LLM

AI 不再只是回答问题。

它开始:

  • 查询数据
  • 搜索信息
  • 调用 API
  • 操作数据库
  • 发送邮件
  • 创建任务
  • 执行业务流程

这时候,大模型才真正开始从:

ChatBot

走向:

Agent。

但下一阶段的问题也随之出现:

如果一个 Agent 有几十个、几百个甚至上千个工具,它到底应该如何选择?

如果多个工具需要同时执行怎么办?

如果一个工具执行失败怎么办?

如果任务需要持续运行几分钟、几十分钟甚至几个小时怎么办?

这时候,我们就需要一个新的核心组件:

Agent Runtime。

它负责的不再只是“调用一个工具”,而是:

任务管理
+
工具调度
+
状态管理
+
重试
+
超时
+
并发
+
记忆

而这,也正是下一代 AI 应用架构开始发生变化的地方。

Logo

加入「COC·上海城市开发者社区」,成就更好的自己!

更多推荐