AI Agent智能体进化之路:从Workflow到ReAct框架再到MCP协议
本文系统梳理AI Agent智能体从传统的workflow模式,到具备动态决策能力的 ReAct框架,再到最终走向标准化工具调用协议的MCP的完整演进路径。结合运维实战案例与代码示例,我们将带您深入理解这些核心概念以及它们之间的本质区别。
一、 AI Agent的定义与两种主流模式
我们先回顾一下AI Agent的标准定义。简单来说,AI Agent(智能体)是一种具备自主决策与执行能力的智能实体,能够通过感知环境、动态调整行为以实现预设目标。其本质是通过融合大语言模型(LLM)的推理能力和工具调用机制,将传统AI的被动响应升级为主动任务执行能力。
这个定义的核心在于 “感知环境-思考决策-行动执行” 的闭环逻辑,也就是要符合 ReAct框架(Reasoning+Action 的缩写)。然而,在实际应用中,Agent的实现方式却呈现出两种不同的模式:Workflow模式 和 ReAct框架模式。

二、 深入解析Workflow模式的Agent
Workflow模式的核心特征是:Agent的执行步骤和逻辑是预先在流程图中定义好的,是“固化”的。
2.1 运维案例:故障拍照智能检索
我们之前介绍过一个用Dify工具实现的运维神器,它用于针对故障拍照进行智能检索。在这个案例中,Agent就是使用了典型的Workflow方式配置出来。“先进行OCR文字识别,然后检索知识库,最后生成答案”,这个执行步骤是我们预先定义好的。类似的,网上很多Agent文章中的案例也大多如此。
2.2 这种Agent的“智能”体现在哪里?
既然步骤是预设的,那么这种Agent的“智能”又从何而来呢?答案是:智能的核心在于其中用到的LLM(大语言模型)。 具体来说,LLM在Workflow中扮演了以下几个关键角色:
- 文字生成和整合能力:在运维案例中,即使前序知识检索环节找到了答案,但这些答案往往比较简略。此时,LLM会根据Prompt指令,“按【原因分析】、【影响范围】、【处置建议】结构化输出”。并且,如果检索环节没有找到答案,LLM还能自行分析并生成解决办法。
- 语义理解和意图识别能力:在另一个“中考小助手”案例中,LLM用于区分用户的问题是在问“某个学校的分数线”,还是在问“某个分数能上什么学校”,或是其他问题。然后,Workflow根据LLM识别出的不同意图,走不同分支的处理逻辑。
小提示: 在大多数实际场景中,使用Workflow这种模式,再结合LLM的语义理解、意图识别、文字生成和整合能力,就已经能够实现一个功能相当不错的Agent了。
三、 实现真正智能:ReAct框架与Function Call
Workflow模式虽然好用,但它的执行逻辑是可预设的。然而,有些业务场景中,执行逻辑是不确定的,需要依据前序环节的执行结果,动态决策下一步该怎么做。这正是 ReAct框架 的用武之地。
3.1 ReAct框架的核心思想
ReAct框架(Reasoning + Acting)是一种结合推理与行动的多步骤高阶任务执行范式。 其核心是一个 “思考-行动-观察” 的闭环。具体流程是:LLM首先“思考”并决定下一步“行动”(比如调用哪个工具),然后系统执行该“行动”并获取结果,最后LLM“观察”这个结果,作为下一步思考的输入。如此循环,直到达成最终目标。

3.2 Function Call:支撑ReAct框架的关键技术
实现ReAct框架中LLM与外部工具交互的底层支撑技术,就是 Function Call(函数调用)。
Function Call 是大型语言模型(LLM)通过语义理解与结构化输出调用外部工具的核心能力。整个流程如下:
- 定义函数:开发者预先定义好一些外部功能函数,比如
get_current_weather、calculate等。 - 生成函数描述Schema:将每个函数的名称、用途、参数等信息,翻译成LLM能理解的JSON Schema格式。
- 输入给LLM:将用户的输入和所有函数的描述Schema一起,发送给LLM。
- LLM决策:LLM根据上下文,判断是否需要调用某个函数。如果需要,它就能输出一个结构化的JSON文本,其中包含了要调用的函数名和相应的参数。
- 执行函数:Agent的代码(而非LLM)解析LLM的输出,找到对应的函数并执行。
- 反馈结果:将函数的执行结果返馈给LLM,让它进行下一步的推理和决策。
常见问题: LLM是否直接调用了外部工具?
答案: 不是。这是一个常见误区。LLM本质上是语言模型,它的输入和输出始终是文本。它只是通过语义理解“决定”需要调用哪个工具,并以JSON格式输出工具名称和参数。真正去“执行”函数调用的是Agent的本地代码。
3.3 代码示例:Function Call的实现
为了更直观地理解这个过程,我们来看一段Python示例代码:
import openai
import json
from typing import get_type_hints
# 示例函数定义
def get_current_weather(location: str, unit: str = "celsius") -> str:
"""获取指定地区的当前天气情况"""
# 模拟天气数据
weather_data = {
"beijing": {"celsius": 22, "fahrenheit": 72},
"new york": {"celsius": 18, "fahrenheit": 64}
}
return f"{location}天气:{weather_data.get(location.lower(), {}).get(unit, '未知')}°{unit}"
def calculate(expression: str) -> float:
"""执行数学计算(支持加减乘除)"""
try:
return eval(expression.replace("^", "**"))
except:
return "计算错误"
# 生成函数描述JSON Schema
def generate_function_schema(func):
hints = get_type_hints(func)
doc = func.__doc__.split("n") if func.__doc__ else ""
return {
"name": func.__name__,
"description": doc,
"parameters": {
"type": "object",
"properties": {
param: {
"type": "string" if hints.get(param) == str else "number",
"description": f"{param}参数"
} for param in list(hints.keys())[:-1]
},
"required": list(get_type_hints(func).keys())[:-1]
}
}
# 可用函数列表
a vailable_functions = {
"get_current_weather": get_current_weather,
"calculate": calculate
}
# 生成函数描述列表
functions = [generate_function_schema(func) for func in a vailable_functions.values()]
# 与LLM交互的核心函数
def run_conversation(user_query: str):
# 第一次LLM调用(选择函数)
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[{"role": "user", "content": user_query}],
functions=functions,
function_call="auto"
)
response_message = response["choices"]["message"]
# 如果LLM选择调用函数,就会在输出response_message中,把要调用的函数和对应参数都输出
if response_message.get("function_call"):
function_name = response_message["function_call"]["name"]
function_args = json.loads(response_message["function_call"]["arguments"])
print(f"LLM选择调用函数: {function_name}")
print(f"参数: {function_args}")
# 执行对应函数
if function_name in a vailable_functions:
function_to_call = a vailable_functions[function_name]
# 参数类型转换
try:
args = {k: str(v) for k,v in function_args.items()}
if function_name == "calculate":
args["expression"] = args["expression"].replace(" ", "")
# 注意:实际执行函数还是本地代码,并不是LLM直接去调用
result = function_to_call(**args)
return f"执行结果: {result}"
except Exception as e:
return f"执行错误: {str(e)}"
else:
return "未知函数调用"
else:
return "未触发函数调用"
# 测试用例
if __name__ == "__main__":
test_cases = [
"北京现在的气温是多少?",
"帮我计算(3 + 5) * 2^3的值",
"今天纽约的天气怎么样?用华氏度"
]
for query in test_cases:
print(f"\n用户问:{query}")
print("->", run_conversation(query))
四、 Function Call的演进:从本地到统一的MCP协议
Function Call虽然强大,但它是一种本地的、非标准化的实现方式。为了解决这个问题,MCP(Model Context Protocol,大模型上下文协议)应运而生。
4.1 MCP与Function Call的根本区别
MCP本质上是对Function Call的规范和标准化。 它的核心思想是:将工具的描述信息(Schema)和工具的执行,从本地Agent代码中剥离出来,放到一个远程的 MCP Server 中去。
在ReAct框架中,使用Function Call和MCP的主要区别如下:
- 工具描述来源不同:Function Call的工具描述由开发者在Agent代码中本地生成。MCP的工具描述则是Agent中的MCP Client从远程的MCP Server主动拉取的。
- 工具执行地点不同:Function Call由Agent本地代码执行。MCP则是Agent本地代码通过MCP Client,将请求发送给远程的MCP Server来执行。
常见问题: 网上很多文章用Claude Desktop、Cursor等工具作为MCP的示例,容易让人混淆,Agent的Host到底是什么?
答案: 这些工具只是Host,它们内部集成了MCP Client。但更常见的Host是你自己开发的Agent代码。在实际开发中,你会在自己的代码中引入MCP Client包,让它去连接远程的MCP Server并执行工具。
4.2 MCP和Function Call的执行流程对比
无论使用哪种方式,LLM的核心作用都没有改变:它只是根据上下文“决策”要调用哪个工具,并输出工具名称和参数。
- Function Call:LLM输出 -> Agent代码解析并调用本地函数。
- MCP:LLM输出 -> Agent代码中的MCP Client解析并发送请求 -> 远程MCP Server执行工具并返回结果。

五、 未来展望:从MCP到A2A(Agent-to-Agent)
MCP解决了智能体工具调用的标准化问题,而谷歌在4月10日推出的开源协议 A2A(Agent-to-Agent),则旨在解决智能体之间的相互通信与协作问题。它使得基于不同底层框架和供应商平台创建的AI Agent能够实现互联互通。
从本质上讲,如果你将MCP Server的后端对接另一个Agent,也已经可以实现多智能体的协作。因此可以推测,A2A可能是对“Host Agent中的LLM通过MCP Client调用MCP Server端的另一个Agent”这一过程进行了简化和封装,使得智能体之间的协作更加直接和高效。这无疑是AI Agent领域最近最火热的发展方向。
六、 总结
以上就是AI Agent从Workflow固化流程到基于Function Call的ReAct框架,再从Function Call到统一标准的MCP的一个发展过程。这个生态正在以前所未有的速度向前发展,理解和掌握这些核心概念,将有助于我们更好地应用和落地AI技术。
