在AI Agent技术快速迭代的今天,从最初的工具调用能力,到如今可自主分工的子智能体(Sub-Agent),整个技术体系的演进围绕着“让AI更高效、更自主地完成复杂任务”这一核心目标展开。很多开发者在接触Agent相关技术时,容易混淆Function Call、MCP、Skill、Sub-Agent等概念,不清楚它们之间的递进关系。本文将以“Function Call → MCP → Skill → Sub-Agent”为演进主线,拆解每一个阶段的核心价值、技术痛点及演进逻辑,帮你理清AI Agent从“会调用工具”到“能自主协作”的完整进化路径。

一、起点:Function Call(函数调用)—— 连接大模型与现实世界的桥梁,AI 学会“伸出手”触达工具

Function Call 是 AI Agent 技术的基石,核心价值在于打破大模型“只会思考、不会行动”的壁垒——它不只是简单的工具调用能力,更是将非结构化自然语言转换为结构化程序指令的关键,为后续 MCP、Skill、Sub-Agent 体系的构建奠定了核心基础。结合实战场景,我们从技术背景、核心原理、源码解析、实战案例四个维度,全面拆解 Function Call 的核心逻辑与应用方法。

在Function Call出现之前,大模型(LLM)本质上只是一个“高级对话机器人”,擅长处理非结构化文本的理解与生成,但无法与外部工具(数据库、API、代码编译器等)进行有效交互——它能回答“如何查天气”,却不能真正调用天气API获取实时数据;能看懂代码需求,却不能自主执行编译、调试操作。Function Call的诞生,打破了这一壁垒,成为AI Agent技术演进的第一个关键节点。

1.1 技术背景与核心定义:为何大模型需要“手脚”?

在 Function Call 出现之前,大语言模型(LLM)本质上只是一个“高级文本预测引擎”,尽管具备强大的非结构化文本理解与生成能力,但存在三个无法规避的核心局限,使其难以对接现实世界、完成实际任务:

  • 知识截止(Knowledge Cutoff):无法获取实时动态信息,比如当前的天气、实时股价、最新行业政策等,只能依赖训练数据内的静态知识;

  • 计算能力薄弱(Computational Limits):不擅长精确的数学运算(如 12345 * 67890 这类复杂计算易出错),也无法完成逻辑严谨的数值推导;

  • 无法与外部交互(No Side Effects):无法直接操作外部世界,比如发送邮件、写入数据库、调用第三方 API,只能输出文本,无法产生实际的操作反馈。

Function Call(函数调用)技术应运而生,它的核心定位的是“连接大模型与现实世界的桥梁”。需要明确的是,Function Call 并非让大模型直接执行代码,而是让大模型输出“我想调用这个函数”的结构化指令(通常为 JSON 格式),再由外部程序解析并执行该函数,最终将执行结果反馈给大模型,形成完整闭环——这就像给只有“大脑”的大模型,装上了可触达现实世界的“手脚”。

其核心定义可概括为:为 LLM 提供一套标准化的“结构化指令规范”(以 JSON Schema 为核心),让大模型能够将用户的非结构化自然语言需求,转换为计算机可识别、可执行的函数调用指令,搭建起“非结构化需求→结构化指令→工具执行→结果反馈→最终响应”的完整链路,实现 LLM 与外部工具、现实世界的有效交互。

1.2 核心原理:JSON Schema 与推理循环

Function Call 的核心的是一套闭环推理系统,所有工具调用的逻辑都围绕“定义工具→思考决策→执行工具→反馈结果→最终响应”五个步骤展开,而 JSON Schema 则是连接大模型与工具的“通用语言”。

  1. 定义工具(Define Tools):开发者通过 JSON Schema 详细描述可用函数的名称、功能描述、参数规范(类型、必填项、说明),让大模型清晰了解每个工具的用途和调用方式,避免调用出错;

  2. 思考与决策(Reasoning):大模型接收用户输入后,结合已定义的工具 Schema,判断是否需要调用工具、调用哪个工具,若需要则输出 JSON 格式的工具调用请求;

  3. 执行工具(Execution):宿主程序(如 Python 代码)解析大模型输出的 JSON 指令,提取函数名称和参数,执行对应的本地函数或第三方 API;

  4. 反馈结果(Observation):将工具执行的结果(转换为字符串格式)追加到对话历史中,让大模型获取执行反馈,为后续决策提供依据;

  5. 最终响应(Response):大模型结合用户原始需求和工具执行结果,生成自然、准确的最终回答,完成整个交互闭环。

1.3 源码解析:手写一个计算器 Agent

为了更直观地理解 Function Call 的执行逻辑,我们以“计算器 Agent”为例,通过源码拆解(参考 demo_calculator.py),剖析从工具定义到执行循环的完整过程,适配开发者实战需求。

1.3.1 定义工具 Schema

首先,我们定义两个核心计算工具(加法 add、乘法 multiply),通过 JSON Schema 规范其调用格式,明确函数名称、功能描述和参数要求:

import json
from openai import OpenAI  # 此处以 OpenAI 客户端为例,可替换为 deepseek、Claude 等

# 初始化客户端(实际使用时替换为自己的 API 密钥)
client = OpenAI(api_key="your-api-key")

# 1. 工具定义 (JSON Schema) - 明确可用工具及调用规范
tools = [
    {
        "type": "function",
        "function": {
            "name": "add",
            "description": "计算两个数字的和,适用于加法运算场景",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {"type": "number", "description": "第一个加数,必须是数字类型"},
                    "b": {"type": "number", "description": "第二个加数,必须是数字类型"}
                },
                "required": ["a", "b"]  # 必传参数,避免调用时缺失参数
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "multiply",
            "description": "计算两个数字的积,适用于乘法运算场景",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {"type": "number", "description": "第一个乘数,必须是数字类型"},
                    "b": {"type": "number", "description": "第二个乘数,必须是数字类型"}
                },
                "required": ["a", "b"]
            }
        }
    }
]

# 定义本地可执行函数(与工具 Schema 中的 name 一一对应)
available_functions = {
    "add": lambda a, b: a + b,
    "multiply": lambda a, b: a * b
}
1.3.2 核心执行循环(The Loop)

执行循环是 Function Call 的“心脏”,负责串联“思考决策→工具执行→结果反馈”的全流程,我们在 run_conversation 函数中实现这一核心逻辑:

def run_conversation(user_query):
    # 初始化对话历史,存储用户输入、模型响应、工具反馈
    messages = [{"role": "user", "content": user_query}]
    
    while True:
        # 2. 思考与决策:调用大模型,让其自主判断是否需要调用工具
        response = client.chat.completions.create(
            model="deepseek-v3",  # 可替换为 GPT-4、Claude 等支持 Function Call 的模型
            messages=messages,
            tools=tools,
            tool_choice="auto"  # 让模型自主决定是否调用工具、调用哪个工具
        )
        
        response_message = response.choices[0].message
        # 将模型的响应(思考结果/工具调用指令)追加到对话历史
        messages.append(response_message)
        
        # 3. 判断模型是否需要调用工具(若有 tool_calls 则需要执行工具)
        if not response_message.tool_calls:
            break  # 无需调用工具,直接退出循环,返回最终回答
        
        # 4. 执行工具并反馈结果
        print("LLM 决定调用工具,开始执行...")
        for tool_call in response_message.tool_calls:
            function_name = tool_call.function.name
            # 解析工具调用的参数(JSON 字符串转字典)
            function_args = json.loads(tool_call.function.arguments)
            
            # 执行本地函数(根据函数名称匹配 available_functions 中的函数)
            if function_name in available_functions:
                function_response = available_functions[function_name](
                    a=function_args.get("a"),
                    b=function_args.get("b")
                )
            else:
                function_response = f"错误:未找到函数 {function_name}"
            
            # 5. 反馈结果:将工具执行结果追加到对话历史(role 设为 tool)
            messages.append({
                "tool_call_id": tool_call.id,
                "role": "tool",
                "name": function_name,
                "content": str(function_response)  # 工具结果转换为字符串,便于模型理解
            })
    
    # 6. 返回最终响应
    return response_message.content

1.4 实战案例:构建算术助手(运行效果与优化)

1.4.1 运行方式

在终端执行以下命令,即可启动计算器 Agent,接收用户的算术运算需求:

python 01_function_calling/demo_calculator.py
1.4.2 运行效果(多步骤运算示例)

当用户输入需求:“计算 12345 加上 67890,然后乘以 2”时,Agent 会通过两次工具调用完成运算,流程如下:

  1. 第一轮思考:LLM 解析需求后,判断需要先执行加法运算,输出 JSON 指令调用 add 函数(参数:a=12345,b=67890);

  2. 工具执行:本地 Python 函数执行 add(12345, 67890),得到结果 80235;

  3. 第二轮思考:LLM 接收加法结果 80235 后,发现还需要执行乘法运算,输出 JSON 指令调用 multiply 函数(参数:a=80235,b=2);

  4. 工具执行:本地 Python 函数执行 multiply(80235, 2),得到结果 160470;

  5. 最终回答:LLM 整合两次工具执行结果,输出自然语言回答:“最终结果是 160470”。

1.4.3 性能优化策略(开发者必备)

在实际开发中,为了提升 Function Call 的效率、节省 Token 成本,可采用以下两个核心优化策略:

  • Token 节省:精简工具 Schema 中的 description 字段,只保留核心功能描述,避免冗余文本占用过多 Token;同时,工具执行结果尽量简洁,无需额外格式化。

  • 并发执行:若 LLM 一次性返回多个独立的 tool_calls(如同时查询北京、上海两地天气),可使用 asyncio 或多线程实现并发执行,替代顺序执行,提升响应速度。

1.5 典型场景、局限与总结

除了计算器 Agent,Function Call 的典型应用场景还包括:实时天气查询、数据库查询、邮件发送、API 调用(如 Github 接口、CSDN 发布接口)等,核心都是解决大模型“无法触达现实世界”的问题。

核心局限:尽管 Function Call 是 Agent 的基石,但依然存在两个致命问题,也正是这些问题推动着技术向 MCP 演进:① 无统一交互标准,不同工具、不同模型的调用格式混乱(如 GPT 与 Claude 的工具调用 Schema 存在差异),开发者需要为每一个工具、每一个模型单独适配,集成成本极高;② 仅能完成工具调用的基础逻辑,缺乏统一的流程编排能力,多工具协同、多步骤运算(如上述算术案例)的顺序的需要模型自主判断,无标准化的流程管控,且异常处理(如参数错误、工具调用失败)需人工单独开发,扩展性极差。

总结:Function Call 的核心价值是“将非结构化自然语言转换为结构化程序指令”,为大模型装上了“手脚”,实现了大模型与现实世界的初步连接。掌握 Function Call 的 JSON Schema 定义、执行循环逻辑,是后续构建 MCP 标准化交互、Skill 流程封装、Sub-Agent 自主协作体系的核心基础——而解决其“交互不标准、无流程编排”的局限,正是 MCP 技术出现的核心意义。

Function Call(函数调用)的核心,是为LLM提供一套“结构化指令规范”,让大模型能够将用户的非结构化自然语言需求,转换为计算机可识别、可执行的结构化函数调用指令(通常是JSON格式),实现LLM与外部工具的标准化交互,搭建起“非结构化需求→结构化指令→工具执行→结果反馈”的闭环链路。

简单来说,Function Call让AI从“只会说”变成了“会指挥”——它不用亲自完成具体操作,只需生成清晰的“工具调用指令”,由系统解析指令后调用对应工具,再将工具返回的结果整合为自然语言反馈给用户。这是AI具备“行动力”的基础,也是后续所有Agent进阶技术的前提。

1.6 典型场景与局限示例

典型应用场景:用户提问“查询北京今日天气并生成温度趋势图”,LLM通过Function Call生成两个指令——调用天气API获取实时数据(函数名:get_weather,参数:city=北京,date=今日)、调用绘图工具生成趋势图(函数名:generate_chart,参数:data=天气数据,type=趋势图),系统执行后,LLM再将结果整理成自然语言回答。

一个具体的函数调用示例(JSON格式)如下:

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_abc123",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{\"city\": \"北京\", \"date\": \"today\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ]
}

核心局限:虽然Function Call实现了工具调用的基础能力,但存在两个致命问题:① 无统一交互标准,不同工具、不同模型的调用格式混乱,开发者需要为每一个工具单独适配调用逻辑,集成成本极高;② 仅能完成“单一工具调用”,无法应对多工具协同、多步骤流程化的复杂任务,缺乏流程编排能力,所有工具调用的顺序、条件判断都需要人工提前定义,AI无法自主规划。

正是这些局限,推动着技术从Function Call向MCP演进——核心目标是解决“工具交互标准化”和“多工具协同成本”问题。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐