title: AI Agent开发入门------从ReAct到Tool Calling,拆解Agent的底层运行逻辑
tags: AI Agent,ReAct,Tool Calling,Agent架构,Function Calling,MCP,Agent开发,LLM,智能体
category: 人工智能
AI Agent开发入门------从ReAct到Tool Calling,拆解Agent的底层运行逻辑
本文是《AI编程与Agent实战》系列第08篇。前7篇完成了AI编程工具到全栈实战的完整闭环。第07篇结尾留了一个问题:项目里的AI调用还是「一次问答」,怎么让AI拥有推理、记忆和工具调度能力,从一个会回答的模型变成一个能自主干活的Agent。
系列前置阅读:第01篇:工具横评 | 第02篇:Cursor入门 | 第03篇:Claude Code实战 | 第04篇:本地模型编程 | 第05篇:Agentic Engineering | 第06篇:AI代码安全 | 第07篇:全栈项目实战
Gartner预测2026年底40%的企业应用将嵌入任务级AI Agent,而2025年这个数字还不到5%。全球Agentic AI市场预计从2025年的57亿美元增长到2033年的654亿美元,年均复合增长率35.7%。
数字很热闹,但热闹背后有一个尴尬的事实:88%的Agent试点项目从未进入生产环境(Forrester 2026)。大多数开发者知道Agent这个词,却不清楚它到底是什么、怎么运行、什么时候该用。
这篇从最底层拆解Agent的运行逻辑:ReAct循环怎么转、Tool Calling怎么调、从Function Calling到MCP的标准化进程怎么走。不堆术语,只讲本质。
来源:Gartner 2025.08, Grand View Research 2026, Forrester Agentic AI Wave Q1 2026
目录
- [什么是AI Agent:它和一个会回答的模型到底差在哪](#什么是AI Agent:它和一个会回答的模型到底差在哪)
- Agent的五大核心组件:一张图说清楚
- [ReAct模式:Reason + Act的推理循环](#ReAct模式:Reason + Act的推理循环)
- [Tool Calling:让模型调用外部工具的标准方式](#Tool Calling:让模型调用外部工具的标准方式)
- [从Function Calling到MCP:工具调用的标准化进程](#从Function Calling到MCP:工具调用的标准化进程)
- [实战:用Python写一个最小ReAct Agent](#实战:用Python写一个最小ReAct Agent)
- Agent设计的选择:什么时候用ReAct,什么时候不用
- 辩证看待:Agent的幻觉、成本与信任问题
- 总结与下一篇预告
1. 什么是AI Agent:它和一个会回答的模型到底差在哪
1.1 一个直观的对比
一个标准的LLM对话:
用户:北京今天天气怎么样?
模型:抱歉,我无法获取实时天气数据。
一个Agent的对话:
用户:北京今天天气怎么样?
Agent思考:我需要查天气。调用 get_weather("北京")。
Agent行动:调用天气API → 返回 {"temperature": 32, "condition": "晴"}
Agent回答:北京今天晴天,32°C。需要我帮你查未来三天的预报吗?
差别在三个字:「能动性」。标准LLM是静态的知识库,Agent是一个能感知环境、自主决策、调用工具的运行时系统。它不只是在回答,它在做事。
1.2 严格定义
Anthropic在2024年12月的「Building Effective Agents」指南中给出了一个被行业广泛接受的定义:
Agent是一个运行时系统,它围绕一个LLM构建,能自主决定下一步做什么、调用哪些工具、什么时候停下来。它不是一个模型,而是一个编排层。
这个定义的核心洞察是:Agent ≠ 模型。模型是引擎,Agent是整车。引擎决定了动力上限,但能不能上路、会不会翻车,取决于整车的设计。
1.3 关键数据:Agent的真实战况
数字比定义更能说明问题。以下是2026年Q1的行业数据:
| 指标 | 数值 | 来源 |
|---|---|---|
| 企业应用嵌入Agent比例 | 80%(Q1 2026新发布/更新应用) | Gartner |
| 有Agent在生产环境中运行的企业比例 | 31% | S&P Global |
| Agent试点进入生产的转化率 | 12%(88%失败) | Forrester |
| 多Agent(3+)协作的生产采用率 | 22% | Digital Applied |
| 指定了「Agent负责人」的企业比例 | 56% | Gartner |
| MCP协议月下载量 | 9700万+ | Anthropic |
来源:Gartner Q1 2026 CIO Agenda, S&P Global 451 Research, Forrester Agentic AI Wave Q1 2026, Digital Applied 2026
80%的应用「声称」嵌入了Agent,但只有31%的企业真正跑起来了。这个49个百分点的差距,就是「Agent Washing」:把聊天机器人、RPA、传统规则引擎重新打上Agent标签,实则没有自主决策能力。Gartner专门用一个词描述这种现象。
2. Agent的五大核心组件:一张图说清楚
一个生产级Agent由五个组件构成。缺一个,它就不再是Agent。
推理引擎(Reasoning Engine)。 LLM本身。负责理解输入、生成推理链路、决定下一步行动。这是Agent的「大脑」,但不是唯一的智能来源。
记忆系统(Memory System)。 短期记忆是当前会话的上下文窗口,长期记忆是外部存储(向量数据库、知识图谱)。没有记忆,Agent就是金鱼------每次对话都从头开始。
工具调度(Tool Orchestration)。 把模型输出的「我想查天气」翻译成实际的API调用,再把API返回结果喂回模型。这是Agent区别于聊天机器人的核心能力。
感知层(Perception)。 接收外部输入并理解其结构。文本、图片、API响应、错误信息------感知层决定了Agent能从环境中提取什么信息。
行动层(Action)。 执行工具调用并产生外部效果。发送邮件、操作数据库、调用API、写文件------行动层是Agent连接虚拟推理和物理世界的桥梁。
可以用一句话概括它们的关系:感知层接收信息,推理引擎做出判断,工具调度找到对应的工具,行动层执行,结果进入记忆系统,下一轮循环开始。
开发者最常犯的错误是过度投资推理引擎(换更大的模型)而忽略工具调度和记忆系统。事实是:一个有15个精良工具的Qwen2.5-7B Agent,在特定任务上的完成率远超一个只有3个工具的GPT-4 Agent。模型能力有上限,但工具和记忆的上限几乎不存在。
3. ReAct模式:Reason + Act的推理循环
3.1 ReAct是什么
ReAct = Reasoning(推理) + Acting(行动),由Yao等人2022年在论文中提出,如今是AI Agent的基础控制循环。
它的运行方式是一个三步循环:Thought(思考)→ Action(行动)→ Observation(观察)→ Thought → Action → Observation → ... 直到任务完成。
每一步的「Thought」让Agent明确说出它现在知道什么、接下来要做什么。这一步看似浪费token,实际上让整个决策链路可追溯、可调试、可审计。
来源:Yao et al., "ReAct: Synergizing Reasoning and Acting in Language Models", 2022
3.2 一个完整的ReAct轨迹
以下是一个真实Agent处理「查一下马斯克最近在忙什么」这个问题的轨迹:
Thought 1: 用户想知道马斯克最近的动态。我需要先搜索新闻。
Action 1: web_search("Elon Musk latest news July 2026")
Observation 1: [返回5条新闻摘要:Starship试飞成功、xAI发布Grok-4、DOGE部门裁撤...]
Thought 2: 搜索结果涵盖了三个方向。用户问的是"在忙什么",我应该整理出主要业务线。
Action 2: web_search("Elon Musk xAI Grok-4 July 2026")
Observation 2: [Grok-4于7月发布,性能超过GPT-5 mini,xAI估值突破800亿...]
Thought 3: 信息量够了。我可以按业务线组织回答。
Final Answer: 马斯克7月主要精力在三条线:SpaceX的Starship刚完成第8次试飞并成功回收助推器;xAI发布了Grok-4,在多项基准上超越GPT-5 mini,公司估值突破800亿美元;政府效率部(DOGE)因争议在上月被裁撤,目前他已退出政府事务。此外特斯拉Cybertruck产能爬坡至周产2500辆。
注意三个要点。第一,每一步的Thought都明确说出了推理方向。第二,两步搜索指向不同的信息缺口,不是盲目重复。第三,Final Answer的每一条事实都能在Observation里找到来源。这就是可追溯性。
3.3 ReAct的成本与收益
ReAct有价值,但也有代价。一个6步ReAct循环的输入token消耗通常是单次完成的8-14倍,因为每一步都要回放完整的Thought/Action/Observation历史。在月均1000万次调用的生产场景中,这是数千美元的月度差额。
ReAct在三种情况下物超所值:任务路径不可预测(下一步依赖上一步的观察结果)、需要可解释性(审计要求能回溯每一步决策)、需要容错(上一步失败了需要换策略)。在另外三种情况下是浪费:所有步骤可以提前确定、任务不需要外部信息验证、单次推理就能得出正确答案。
来源:mindmapdigital.ai, zarifautomates.com
3.4 生产环境中的ReAct调优
纯ReAct在生产中几乎没人用。三种常见的工程化改造:
模式一:ReAct规划 + 紧凑格式执行。 一个贵模型用ReAct做任务拆解,产生结构化的执行计划;一个便宜的模型按计划执行,不再输出冗长的Thought。成本压到纯ReAct的40-55%,任务质量不变。
模式二:硬限制。 设置最大步数(通常10-20步)和最大token预算。超过任一阈值,Agent强制终止并输出「未能完成,以下是当前进度」。这比Agent死循环烧掉几万token好得多。
模式三:摘要压缩。 在ReAct循环中定期压缩历史推理轨迹,只保留关键的事实结论,丢弃冗长的推理过程。类似操作系统的内存分页机制。
4. Tool Calling:让模型调用外部工具的标准方式
4.1 Function Calling是什么
Function Calling是OpenAI在2023年6月引入的机制,让模型生成结构化的函数调用而不是自由文本。这不是模型真的「调用」了函数,而是模型输出了一个结构化的JSON,由你的代码去执行这个调用,再把结果返回给模型。
模型输出(不是自由文本,是结构化JSON):
{
"name": "get_weather",
"arguments": {
"city": "北京",
"unit": "celsius"
}
}
你的代码收到这个JSON,调用真正的天气API,把结果拼回去:
json
{
"role": "tool",
"tool_call_id": "call_abc123",
"content": "{\"temperature\": 32, \"condition\": \"晴\"}"
}
模型读到这个tool响应,继续推理。
4.2 OpenAI格式的Tool定义
任何兼容OpenAI API的模型(DeepSeek、Qwen、GLM)都支持这套格式:
python
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的实时天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如'北京'、'上海'"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度单位"
}
},
"required": ["city"]
}
}
}
]
模型拿到这个定义后,会在需要时输出一个tool_calls数组而不是普通的文本回复。Tool定义的质量直接决定了Agent的工具使用准确率。描述写得太模糊,模型不知道该什么时候调;参数约束太松,模型可能生成不合法的输入。
生产环境的一条铁律:给每个工具的description里加上「什么时候该调这个工具,什么时候不该调」。 这不是可选优化,是必须。没有这条,Agent会在不需要的时候也乱调工具。
4.3 Tool Calling的完整流程
用户输入
→ LLM判断需要工具调用
→ 输出 tool_calls: [{name: "get_weather", arguments: {...}}]
→ 代码执行实际的函数调用
→ 返回 tool 角色消息: {content: "结果数据"}
→ LLM阅读tool结果,继续推理或输出最终回答
值得注意的一点:Tool Calling的可靠性取决于模型本身对「什么时候需要外部信息」的判断。 这个判断可能出错。可能幻觉出工具名,可能在不该调的时候调了,可能在需要调的时候认为不需要。降级策略(fallback)是生产Agent的标配:调不到工具给默认回复、参数有问题重试一次、三步还走不通就转人工。
5. 从Function Calling到MCP:工具调用的标准化进程
5.1 Function Calling的局限性
Function Calling解决了「让模型描述它想调什么函数」的问题,但它遗留了三个更大的问题:
工具定义与模型耦合。 每个Agent应用都要在自己的代码里硬编码tool定义。换一个Agent,重写一遍。
工具实现与调用分离。 模型输出「调用get_weather」,但谁来提供这个函数的实际实现?你写的。100个Agent需要100份实现。
跨Agent互操作不存在。 Agent A的工具Agent B用不了,因为工具定义和实现都是私有的。
这就像每个电脑都自带USB接口,但每个接口的形状、电压、协议都不一样。你需要一个标准。
5.2 MCP怎么解决
MCP(Model Context Protocol)由Anthropic在2024年11月发布,2025年12月加入Linux基金会。它的核心思路:
- Resources:Agent可以读取的数据(文件、数据库记录、API文档)
- Tools:Agent可以执行的操作(查询天气、发送邮件、操作数据库)
- Prompts:预定义的提示词模板(标准化的Agent行为模式)
一个MCP Server把这三样东西封装成一个标准化的HTTP/SSE服务。任何支持MCP的Agent客户端(Claude Desktop、Cursor、VS Code)都能直接连接和使用,不需要在每个客户端里重新写一遍工具定义。
json
// MCP Server暴露的工具定义(客户端自动发现)
{
"name": "get_weather",
"description": "获取指定城市的实时天气信息。当用户询问天气时调用,当用户询问历史天气时不要调用(应调get_historical_weather)。",
"inputSchema": { ... }
}
来源:Anthropic MCP官方文档, github.com/modelcontextprotocol
5.3 为什么MCP需要专文讲(09篇预告)
这篇只讲MCP在Agent架构中的定位。下一篇(第09篇)会用完整代码演示从零写一个MCP Server:定义Resources/Tools/Prompts三大原语、用Python/TypeScript实现、在Claude Desktop和Cursor里接入测试。那篇会更像第07篇的实战风格,这篇先建好认知基础。
6. 实战:用Python写一个最小ReAct Agent
理论到这里,键盘该响了。下面是一个不到150行的最小ReAct Agent,用DeepSeek API(OpenAI兼容)驱动,工具是计算器和天气查询。
python
import json, os, re
from openai import OpenAI
# ---- 工具定义 ----
def calculator(expression: str) -> str:
"""安全的数学表达式计算器"""
try:
allowed = set("0123456789+-*/().% ")
if not all(c in allowed for c in expression):
return "错误:表达式包含不允许的字符"
result = eval(expression, {"__builtins__": {}}, {})
return str(result)
except Exception as e:
return f"计算错误:{e}"
# 工具注册表:名称 → (函数, 描述)
TOOLS = {
"calculator": (calculator, "计算数学表达式,如'2+3*4'。当用户要求计算时使用。"),
"get_time": (lambda _: __import__('datetime').datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"获取当前日期和时间。当用户询问时间时使用。"),
}
# ---- 核心循环 ----
client = OpenAI(
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com/v1",
)
SYSTEM_PROMPT = """你是一个能使用工具的AI Agent。用以下格式响应:
如果你想使用工具:
THOUGHT: <你的推理过程>
ACTION: <工具名称>
ARGUMENTS: <JSON格式的参数>
OBSERVATION: <等待工具返回结果>
如果你想给出最终答案:
THOUGHT: <你的推理过程>
FINAL_ANSWER: <给用户的答案>
可用工具:
- calculator: 计算数学表达式。参数: {"expression": "数学表达式"}
- get_time: 获取当前时间。参数: {}
规则:
1. 每一步必须输出THOUGHT
2. 使用工具时输出ACTION和ARGUMENTS,然后等待OBSERVATION
3. 完成时输出FINAL_ANSWER
4. 同一工具不要重复调用两次"""
MAX_STEPS = 5
def run_agent(user_input: str):
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
print(f"👤 用户: {user_input}\n")
for step in range(1, MAX_STEPS + 1):
messages.append({"role": "user", "content": user_input}) if step == 1 else None
response = client.chat.completions.create(
model="deepseek-chat", messages=messages, temperature=0.1
)
agent_output = response.choices[0].message.content
messages.append({"role": "assistant", "content": agent_output})
# 解析Agent输出
thought = re.search(r"THOUGHT:\s*(.+?)(?=\n(?:ACTION|FINAL_ANSWER)|$)",
agent_output, re.DOTALL)
if "FINAL_ANSWER:" in agent_output:
answer = agent_output.split("FINAL_ANSWER:")[1].strip()
print(f"💭 {thought.group(1).strip() if thought else '...'}")
print(f"\n✅ 最终回答: {answer}")
return answer
if "ACTION:" in agent_output:
action = re.search(r"ACTION:\s*(\w+)", agent_output).group(1)
args_str = re.search(r"ARGUMENTS:\s*(\{.*?\})", agent_output, re.DOTALL)
args = json.loads(args_str.group(1)) if args_str else {}
print(f"💭 {thought.group(1).strip() if thought else '...'}")
print(f"🔧 步骤{step}: 调用 {action}({args})")
if action in TOOLS:
func, _ = TOOLS[action]
result = func(**(args if args else {}))
else:
result = f"错误:未知工具 '{action}'"
print(f"📊 步骤{step}: 结果 → {result[:100]}\n")
messages.append({"role": "user", "content": f"OBSERVATION: {result}"})
return "Agent达到最大步数限制,未能完成任务。"
# ---- 测试 ----
if __name__ == "__main__":
run_agent("现在是几点?然后帮我算一下 (135 + 267) * 0.85")
6.1 逐行解析
SYSTEM_PROMPT是Agent的行为约束。 它定义输出格式(THOUGHT/ACTION/OBSERVATION/FINAL_ANSWER),告诉模型什么时候用工具、什么时候给答案。这段prompt本质上就是一个用自然语言写的状态机。
TOOLS字典是工具注册表。 每个工具有一个名称、一个函数实现、一段描述。函数实现的输入输出类型必须与prompt描述的JSON Schema一致。不一致就是前面的「接口契约漂移」,Agent调用会失败。
核心循环是状态机。 每一步:调用LLM → 解析输出 → 如果是ACTION就执行工具并把结果追加到对话 → 如果是FINAL_ANSWER就返回。MAX_STEPS=5是为了防止死循环------ReAct如果没有硬限制,可能推下去永不停止。
eval的安全限制。 {"__builtins__": {}} 剥夺了eval的所有内置函数访问权限,只允许纯数学表达式。给Agent暴露eval不设限制等于提供远程代码执行漏洞。
6.2 预期输出
👤 用户: 现在是几点?然后帮我算一下 (135 + 267) * 0.85
💭 用户问了两个问题:当前时间和计算。先获取时间。
🔧 步骤1: 调用 get_time({})
📊 步骤1: 结果 → 2026-07-20 19:30:00
💭 已获得时间。接下来计算 (135+267)*0.85 = 402*0.85 = 341.7
🔧 步骤2: 调用 calculator({"expression": "(135 + 267) * 0.85"})
📊 步骤2: 结果 → 341.7
💭 两个任务都完成了。整理结果回答用户。
✅ 最终回答: 现在是2026年7月20日19:30。计算结果:(135 + 267) × 0.85 = 341.7
7. Agent设计的选择:什么时候用ReAct,什么时候不用
不是所有任务都配得上一个Agent。判断标准很简单:
| 场景 | 该不该用Agent | 替代方案 |
|---|---|---|
| 路径可预测、步骤固定(如KYC流程) | 不用 | 工作流引擎+模型嵌入 |
| 下一步依赖上一步的观察结果(如多跳搜索) | 用ReAct | - |
| 需要跨多个外部系统(数据库+API+文件) | 用ReAct | - |
| 单次推理就能回答(如摘要、翻译) | 不用 | 单次LLM调用 |
| 需要可追溯的决策链条(如合规审计) | 用ReAct | - |
| 高频、低延迟、确定性要求高(如支付) | 不用 | 传统API+规则引擎 |
一个可操作的决策流程:先问自己「完成这个任务需要调用外部工具吗」。不需要,就别用Agent。需要,再问「调用顺序是提前确定的还是动态的」。确定顺序,用一个简单的顺序管道。动态不确定,再上ReAct。
Anthropic的官方建议与此一致:「从最简单的方案开始,只在实测失败时升级复杂度。」这条规则在2026年仍然成立。
来源:Anthropic "Building Effective Agents", 2024.12; mindmapdigital.ai
8. 辩证看待:Agent的幻觉、成本与信任问题
8.1 幻觉没有消失,只是换了地方
LLM的幻觉是输出不符合事实的文本。Agent的幻觉是调用了不该调的工具、编造了不存在的工具名、对工具返回结果做出了错误推理。
Peivaste和Belouettar(2026)在一项科学预测任务上测得ReAct Agent的准确率为94.66%(F1=0.896)。这个数字不差,但它意味着每20次任务有1次出错。在客户服务里这可能只是打扰,在金融交易里这可能是灾难。
来源:Peivaste & Belouettar, arXiv:2603.11068, 2026
8.2 成本是可预测的,但常被低估
一个6步ReAct循环的输入token可能是单次完成的8-14倍。月均1000万次调用,纯ReAct比pipe方案每月多烧几千美元。而且Agent的第一步就做错的概率是5%,越是长链路串联失败概率越高。20步任务的成功率只有35%(假设每步95%正确率)。
成本控制的核心不是换更便宜的模型,而是只在必要的步骤上支付推理成本。前文提到的「ReAct规划+紧凑执行」模式就是这个思路的落地。
8.3 Gartner的警告:40%的Agent项目将被取消
Gartner预测到2027年底,超过40%的Agent项目将因成本失控、价值不清晰和风险管控不足而被取消。这个数字和88%的试点转化失败率是同一枚硬币的两面:能进生产的Agent和能活过一年的Agent,是两个不同的概念。
来源:Gartner 2025
8.4 信任只能靠工程手段建立
Agent输出的可信赖度不是prompt工程能解决的。三条工程防线:
- 每条FINAL_ANSWER里的每条事实声明,都必须在某条OBSERVATION中找到出处。做不到的,标注「置信度低」。
- 调用参数加类型校验。模型输出
{"amount": "100"}(字符串)而工具要int,不是Agent的错,是你的校验没写。 - 日志链路完整。从用户输入到最终输出,每一步的THOUGHT/ACTION/OBSERVATION全部记录。出事才能追溯。
9. 总结与下一篇预告
9.1 核心要点
Agent不是一个模型,是一个运行时系统。它的五个组件是推理引擎、记忆系统、工具调度、感知层、行动层。模型是引擎,工具是轮胎,记忆是油箱------缺哪个都跑不远。
ReAct(Reason + Act)是Agent的基础控制循环。Thought让推理可追溯,Action让模型能做事,Observation把外部世界的信息注入循环。不是所有任务都需要ReAct,可预测路径的任务用地道的管道更省。
Tool Calling让模型输出结构化的函数调用。MCP把工具定义从「每个应用自己写」升级为「一个Server被所有客户端共享」。下一篇专写MCP Server开发。
Agent的问题不在模型能力,在工程实践。幻觉通过结果追溯来控制,成本通过压缩推理历史来控制,信任通过日志链路来建立。这些不是可选的优化,是生产Agent的基础设施。
9.2 下一篇预告
第09篇:MCP Server开发实战------从零写一个自己的MCP工具,让AI调用你的API
这篇讲清楚了Agent「为什么能调用工具」和「怎么调工具」。下一篇动手:用Python写一个完整的MCP Server,定义Resources/Tools/Prompts三大原语,让Claude Desktop和Cursor直接连接使用。MCP月下载9700万+,15926个GitHub仓库,现在是入局的最好时机。
系列推荐阅读:
本文数据来源:Gartner "40% of Enterprise Apps Will Feature Task-Specific AI Agents by 2026" (2025.08)、Gartner Q1 2026 CIO Agenda、Forrester Agentic AI Wave Q1 2026、S&P Global 451 Research、Digital Applied "AI Agent Adoption 2026: 120+ Enterprise Data Points"、Grand View Research Agentic AI Market Report 2026、Yao et al. "ReAct: Synergizing Reasoning and Acting in Language Models" (2022)、Anthropic "Building Effective Agents" (2024.12)、mindmapdigital.ai "ReAct in Production" (2026)、zarifautomates.com "AI Agent Architecture Patterns 2026"、Peivaste & Belouettar arXiv:2603.11068 (2026)。
作者:Ai学长,专注 AI 编程与 Agent 实战。从本地部署到 AI 编程再到 Agent 开发,带你走完从「装 AI」到「用 AI 赚钱」的全流程。
觉得有用就收藏,有问题评论区见。