从零构建AI Agent:基于LangChain与ReAct框架的智能体开发实战 最近在项目里尝试接入大模型时发现一个普遍现象很多开发者热衷于讨论AI Agent的宏大前景但真要动手实现一个能调用工具、处理复杂任务的智能体时却往往不知从何下手。市面上的Coze、Dify等平台虽然降低了门槛但如果不理解其背后的工作机制一旦遇到定制化需求或线上问题排查起来会非常困难。本文将从零开始带你深入理解AI Agent的核心机制——ReAct并基于LangChain框架手把手构建一个能自主调用工具、完成复杂任务的智能体。无论你是想为现有业务增加AI能力还是单纯对Agent技术好奇这篇文章都将提供一套可运行、可调试的完整方案。1. 什么是AI Agent从概念到本质在深入代码之前我们有必要先厘清几个核心概念。很多人将AI Agent简单理解为“聊天机器人升级版”这种理解虽然直观但不够准确。AI Agent智能体的本质是一个能够感知环境、自主决策并执行行动以达成目标的系统。我们可以用一个简单的类比来理解如果把大语言模型LLM看作一个人的“大脑”那么AI Agent就是这个配备了“大脑”的完整“机器人”。这个机器人不仅会思考推理还拥有“手”和“眼睛”工具可以与环境互动。一个典型的AI Agent通常包含以下几个核心组件规划模块Planner负责分解任务、制定步骤。例如当用户问“帮我订一张明天北京到上海的机票”时规划模块会将其分解为查询航班、比价、选择航班、填写信息、确认支付等子任务。记忆模块Memory存储对话历史、工具调用结果、用户偏好等为后续决策提供上下文。工具集ToolsAgent可以调用的外部能力如计算器、搜索引擎、数据库查询API、代码执行环境等。行动模块Action根据规划调用具体的工具。反思模块Reflection评估行动结果判断是否达成目标是否需要调整策略。而LangChain正是将这些组件标准化、模块化并提供了一套优雅编排框架的“脚手架”。它不是一个具体的Agent实现而是一个让你能够快速构建、测试和部署Agent的开发工具包。那么如何让LLM这个“大脑”知道在什么情况下该调用哪个“工具”呢这就是ReAct机制要解决的核心问题。2. ReAct机制让LLM学会“三思而后行”ReActReasoning Acting是一种让大模型将“推理”和“行动”结合起来解决复杂任务的框架。其灵感来源于人类的思考过程我们遇到问题时通常会先思考分析问题、制定计划然后行动执行计划再根据行动结果观察反馈并进一步思考调整。2.1 为什么需要ReAct大模型虽然知识渊博但存在两个固有局限知识滞后性训练数据有截止日期无法获取最新信息如今天的天气、股价。专业能力不足不擅长精确计算、实时查询、操作外部系统等。ReAct通过让LLM主动调用外部工具完美地弥补了这些缺陷。它让LLM从“全知但被动”的知识库转变为“会思考、会求助”的智能体。2.2 ReAct的核心工作流程ReAct的工作流程是一个典型的循环推理Reason→ 行动Act→ 观察Observe→ 再推理...直到任务完成。我们通过一个具体例子来拆解这个过程。假设用户提问“2024年周杰伦上海演唱会门票多少钱”一个基于ReAct的Agent处理流程如下推理1用户需要查询2024年周杰伦上海演唱会的门票价格。这是一个需要实时信息的问题我的内部知识无法回答需要调用网络搜索工具。行动1调用网络搜索工具关键词为“2024 周杰伦 上海 演唱会 门票 价格”。观察1工具返回了搜索结果列表其中包含几个票务网站链接和新闻页面。推理2搜索结果较多需要提取关键信息。第一个结果是“大麦网-周杰伦2024上海演唱会”这很可能是一个官方票务平台应优先查看。行动2调用网页内容提取工具访问第一个结果的URL。观察2工具返回了网页内容显示演唱会时间为2024年8月10日看台票价格从580元到1680元不等内场票从2280元起。推理3已获取到用户所需的价格信息。需要整理并清晰地呈现给用户同时注明信息来源和不同档位的价格。最终回答根据观察2的信息组织语言回复用户。可以看到ReAct通过一步步的“思考-行动-观察”引导LLM像人类一样使用工具解决问题而不是盲目地生成可能错误的答案。2.3 ReAct在LangChain中的实现形式在LangChain中ReAct机制通常通过Agent类来实现。LangChain的Agent不是一个预先训练好的模型而是一个决策框架。它包含以下几个关键部分Agent决策核心根据当前对话历史和工具描述决定下一步是直接回答还是调用某个工具。Tools可供调用的工具列表每个工具都有名称和功能描述。Toolkit工具集合。AgentExecutor驱动Agent运行的执行器负责循环运行“推理-行动-观察”的流程直到Agent决定结束任务。3. 环境准备与项目搭建理论讲得再多不如一行代码。接下来我们开始动手搭建环境实现第一个AI Agent。3.1 环境与依赖本项目基于Python建议使用Python 3.8及以上版本。我们将使用LangChain框架并接入一个开源的LLM API作为“大脑”。首先创建项目目录并初始化虚拟环境mkdir my_first_ai_agent cd my_first_ai_agent python -m venv venv # Windows venv\Scripts\activate # Linux/Mac source venv/bin/activate然后安装核心依赖。LangChain生态正在快速发展包名可能有变化以下是当前请注意版本可能更新的稳定安装方式pip install langchain langchain-community langchain-openailangchain: LangChain核心框架。langchain-community: 社区维护的第三方工具、模型集成。langchain-openai: OpenAI模型官方集成我们也可以使用其他兼容OpenAI API的模型服务。由于我们需要调用大模型这里以使用一个兼容OpenAI API的国内服务为例请注意你需要自行获取可用的API Key和Base URL。我们同时安装python-dotenv来管理敏感信息pip install python-dotenv requests3.2 项目结构规划一个清晰的目录结构有助于后续开发和维护my_first_ai_agent/ ├── .env # 环境变量存放API密钥等敏感信息 ├── requirements.txt # 项目依赖 ├── src/ │ ├── __init__.py │ ├── tools/ # 自定义工具目录 │ │ ├── __init__.py │ │ ├── calculator.py # 计算器工具 │ │ └── searcher.py # 搜索工具示例 │ ├── agents/ # Agent定义目录 │ │ ├── __init__.py │ │ └── react_agent.py # ReAct Agent核心逻辑 │ └── main.py # 主程序入口 └── README.md创建基础文件mkdir -p src/tools src/agents touch .env requirements.txt src/main.py src/agents/__init__.py src/agents/react_agent.py src/tools/__init__.py src/tools/calculator.py在.env文件中配置你的API信息请替换为你的实际信息# .env OPENAI_API_KEYsk-your-api-key-here OPENAI_API_BASEhttps://api.your-llm-provider.com/v1 MODEL_NAMEgpt-3.5-turbo # 或 gpt-4, qwen-plus等4. 实战第一步打造你的第一个工具工具Tool是Agent能力的延伸。我们从一个最简单的工具开始——一个能进行精确计算的工具。为什么需要这个工具因为大语言模型尤其是早期版本在数学计算上并不精确它们可能生成看似合理但实际错误的答案。将计算任务交给专门的工具能保证结果的准确性。创建文件src/tools/calculator.py# src/tools/calculator.py from langchain.tools import BaseTool from typing import Union, Optional, Type from pydantic import BaseModel, Field # 定义工具的输入参数模型 class CalculatorInput(BaseModel): 计算器工具的输入参数。 a: Union[int, float] Field(description第一个数字) b: Union[int, float] Field(description第二个数字) operator: str Field(description运算符支持 , -, *, /, **) class CalculatorTool(BaseTool): 一个能执行基础算术运算的计算器工具。 name calculator description 当需要执行精确的数学计算时使用此工具。 支持加法()、减法(-)、乘法(*)、除法(/)、乘方(**)。 输入必须是数字和运算符。 args_schema: Optional[Type[BaseModel]] CalculatorInput def _run(self, a: Union[int, float], b: Union[int, float], operator: str) - str: 执行计算。 try: if operator : result a b elif operator -: result a - b elif operator *: result a * b elif operator /: if b 0: return 错误除数不能为零。 result a / b elif operator **: result a ** b else: return f错误不支持的运算符 {operator}。支持的操作符为, -, *, /, ** # 返回格式化的结果便于Agent理解 return f计算结果{a} {operator} {b} {result} except Exception as e: return f计算过程中发生错误{str(e)} async def _arun(self, a: Union[int, float], b: Union[int, float], operator: str) - str: 异步执行计算本例中与同步相同。 return self._run(a, b, operator)代码解析继承BaseTool所有LangChain工具都必须继承自BaseTool类。定义工具元信息name: 工具的唯一标识Agent通过这个名字来调用它。description: 工具的功能描述。这是最关键的部分。LLM根据这个描述来判断是否以及何时调用该工具。描述要清晰、准确说明工具的用途、输入和输出。定义输入模式args_schema使用Pydantic模型CalculatorInput来严格定义工具的输入参数。这能帮助LangChain将Agent的自然语言决策解析成结构化的参数。实现_run方法这是工具的核心逻辑执行具体的操作并返回结果。实现_arun方法异步版本用于支持异步调用。5. 构建你的第一个ReAct Agent有了工具我们就可以组装Agent了。我们将使用LangChain提供的create_react_agent函数它封装了标准的ReAct逻辑。创建文件src/agents/react_agent.py# src/agents/react_agent.py import os from dotenv import load_dotenv from langchain import hub from langchain.agents import create_react_agent, AgentExecutor from langchain.agents.format_scratchpad import format_log_to_str from langchain.agents.output_parsers import ReActSingleInputOutputParser from langchain.tools.render import render_text_description from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory from langchain.prompts import PromptTemplate # 导入我们自定义的工具 from src.tools.calculator import CalculatorTool # 加载环境变量 load_dotenv() def build_react_agent(): 构建并返回一个配置了ReAct Agent的执行器。 # 1. 初始化LLM # 使用环境变量中的配置 llm ChatOpenAI( modelos.getenv(MODEL_NAME, gpt-3.5-turbo), openai_api_keyos.getenv(OPENAI_API_KEY), openai_api_baseos.getenv(OPENAI_API_BASE), temperature0, # 温度设为0使输出更确定更适合工具调用 streamingFalse, ) # 2. 准备工具集 tools [CalculatorTool()] # 将工具列表转换为格式化的字符串描述供提示词使用 tool_names , .join([tool.name for tool in tools]) tool_descriptions render_text_description(tools) # 3. 定义提示词Prompt # ReAct Agent的提示词比较复杂我们从LangChain Hub拉取一个社区维护的优秀版本 # 也可以自定义但Hub上的版本经过大量测试更稳定 prompt hub.pull(hwchase17/react) # 提示词中需要动态替换的部分我们通过Partial来提前填充 prompt prompt.partial( toolstool_descriptions, tool_namestool_names, ) # 4. 构建Agent # create_react_agent 将LLM、提示词、工具绑定在一起形成决策逻辑 agent create_react_agent( llmllm, toolstools, promptprompt, ) # 5. 配置记忆Memory # 让Agent能记住对话历史处理多轮对话 memory ConversationBufferMemory( memory_keychat_history, return_messagesTrue, output_keyoutput ) # 6. 创建Agent执行器AgentExecutor # 这是驱动Agent运行的核心引擎负责循环执行“思考-行动-观察” agent_executor AgentExecutor.from_agent_and_tools( agentagent, toolstools, memorymemory, verboseTrue, # 设为True可以看到Agent详细的思考过程调试时非常有用 handle_parsing_errorsTrue, # 优雅处理Agent输出解析错误 max_iterations10, # 限制最大迭代次数防止死循环 early_stopping_methodgenerate, # 当Agent连续两次生成最终答案时停止 ) return agent_executor if __name__ __main__: # 本地测试 agent_executor build_react_agent() print(AI Agent 已启动输入退出或quit结束对话。\n) while True: try: user_input input(\n您: ) if user_input.lower() in [退出, quit, exit]: print(再见) break if not user_input.strip(): continue # 调用Agent执行器 response agent_executor.invoke({input: user_input}) print(f\nAgent: {response[output]}) except KeyboardInterrupt: print(\n\n程序被中断。) break except Exception as e: print(f\n发生错误: {e})关键点解析AgentvsAgentExecutor这是初学者最容易混淆的概念。Agent是一个决策函数。它接收用户输入和对话历史输出一个AgentAction表示要调用哪个工具及参数或AgentFinish表示任务完成输出最终答案。AgentExecutor是运行引擎。它循环调用Agent执行Agent决定的工具调用将结果Observation作为新的输入反馈给Agent直到Agent输出AgentFinish。提示词PromptReAct Agent的提示词模板非常关键它定义了Agent的“思考格式”。我们从LangChain Hub拉取hwchase17/react这个经过验证的模板它已经内置了ReAct的标准格式Thought, Action, Observation。记忆MemoryConversationBufferMemory将对话历史保存在内存中使Agent具备上下文感知能力。verboseTrue在开发阶段务必开启这个选项。它会打印出Agent完整的思考链Chain of Thought让你清晰地看到它是如何推理、决定调用工具、以及如何处理工具返回结果的。这是调试和理解Agent行为的最重要手段。安全限制max_iterations和early_stopping_method是防止Agent陷入死循环或无限递归的重要保障。6. 运行与测试见证Agent的思考过程现在让我们运行这个Agent看看它是如何工作的。首先确保你的.env文件已正确配置API信息。然后运行主程序python src/agents/react_agent.py你会看到类似以下的启动信息然后进入交互模式。测试场景1数学计算您: 请帮我计算一下 3.1415926 乘以 2.7182818 等于多少开启verboseTrue后你将在控制台看到Agent的详细思考过程 进入新的AgentExecutor链... 思考用户要求进行乘法计算。我有一个计算器工具可以处理这个。我需要使用计算器工具。 行动调用计算器工具。 行动输入{a: 3.1415926, b: 2.7182818, operator: *} 观察计算结果3.1415926 * 2.7182818 8.53973422232268 思考我已经得到了计算结果可以回答用户了。 最终答案3.1415926 乘以 2.7182818 等于 8.53973422232268。 Agent: 3.1415926 乘以 2.7182818 等于 8.53973422232268。关键观察Agent识别出这是一个计算任务自动选择了calculator工具并正确地将自然语言问题解析成了工具调用参数(a3.1415926, b2.7182818, operator*)。测试场景2无需工具的一般对话您: 你好请介绍一下你自己。思考过程 进入新的AgentExecutor链... 思考用户让我自我介绍。这是一个简单的问候和介绍不需要使用任何工具。我可以直接回答。 最终答案你好我是一个基于LangChain和ReAct框架构建的AI助手。我可以通过调用工具比如计算器来帮助你处理一些需要精确计算的任务。有什么我可以帮你的吗 Agent: 你好我是一个基于LangChain和ReAct框架构建的AI助手。我可以通过调用工具比如计算器来帮助你处理一些需要精确计算的任务。有什么我可以帮你的吗关键观察Agent正确判断出这个问题不需要调用工具直接利用LLM的知识生成了回答。这体现了ReAct机制的智能性——按需调用工具而非盲目调用。测试场景3多轮对话依赖记忆您: 我们刚才计算的结果是多少思考过程假设紧接着场景1的对话 进入新的AgentExecutor链... 思考用户问“刚才计算的结果”。我需要查看聊天历史来理解上下文。从历史记录看我们刚才计算了3.1415926 * 2.7182818结果是8.53973422232268。这个问题不需要使用工具。 最终答案刚才我们计算了3.1415926乘以2.7182818结果是8.53973422232268。 Agent: 刚才我们计算了3.1415926乘以2.7182818结果是8.53973422232268。关键观察ConversationBufferMemory发挥了作用Agent能够访问之前的对话历史从而理解“刚才”的指代给出准确的回答。7. 扩展能力集成更多工具一个只有计算器的Agent显然不够强大。让我们为它添加一个“获取当前时间”的工具模拟与外部世界的交互。创建src/tools/current_time.py# src/tools/current_time.py from langchain.tools import BaseTool from datetime import datetime from typing import Optional, Type from pydantic import BaseModel, Field class CurrentTimeInput(BaseModel): 获取当前时间的输入参数本例中无需参数但结构保留。 timezone: Optional[str] Field(defaultAsia/Shanghai, description时区例如Asia/Shanghai, UTC) class CurrentTimeTool(BaseTool): 一个获取当前日期和时间的工具。 name get_current_time description 当用户询问当前时间、今天日期或类似关于时间的问题时使用此工具。 此工具返回系统的当前日期和时间。 可以指定时区默认为Asia/Shanghai。 args_schema: Optional[Type[BaseModel]] CurrentTimeInput def _run(self, timezone: str Asia/Shanghai) - str: 获取指定时区的当前时间。 try: # 这是一个简化版实际应用中应使用pytz或zoneinfo处理时区 # 这里仅作演示 now_utc datetime.utcnow() if timezone Asia/Shanghai: # 模拟UTC8 now_local now_utc.replace(hournow_utc.hour8) else: now_local now_utc return f当前时间{timezone}: {now_local.strftime(%Y-%m-%d %H:%M:%S)} except Exception as e: return f获取时间失败: {str(e)} async def _arun(self, timezone: str Asia/Shanghai) - str: return self._run(timezone)修改src/agents/react_agent.py中的工具列表# 在 build_react_agent 函数中修改工具准备部分 from src.tools.calculator import CalculatorTool from src.tools.current_time import CurrentTimeTool # 新增导入 def build_react_agent(): # ... 前面的代码不变 ... # 2. 准备工具集 (现在有两个工具了) tools [CalculatorTool(), CurrentTimeTool()] # 修改这行 # ... 后面的代码不变 ...重启Agent并进行测试您: 现在几点了思考过程 进入新的AgentExecutor链... 思考用户询问当前时间。我有一个获取当前时间的工具。 行动调用 get_current_time 工具。 行动输入{timezone: Asia/Shanghai} 观察当前时间Asia/Shanghai: 2024-05-27 14:30:15 思考我已经得到了当前时间可以回答用户了。 最终答案现在是北京时间2024年5月27日下午2点30分15秒。 Agent: 现在是北京时间2024年5月27日下午2点30分15秒。现在你的Agent已经具备了两种不同的能力。通过这种方式你可以不断集成新的工具如网络搜索工具查询实时信息。数据库查询工具访问内部业务数据。代码执行工具运行Python代码片段。文件操作工具读写本地文件。API调用工具与任何外部服务通信。8. 核心机制深度解析LangChain Agent如何工作通过上面的实践我们已经看到了Agent的运行效果。现在让我们深入LangChain内部理解其工作机制。下图展示了LangChain Agent的核心工作流程用户输入 │ ▼ [ AgentExecutor ] │ ▼ [ 格式化输入 ] (结合用户输入、工具描述、对话历史) │ ▼ [ LLM调用 ] (生成包含Thought/Action的文本) │ ▼ [ 输出解析器 ] (解析LLM输出为AgentAction或AgentFinish) │ ├───────────── 如果是 AgentFinish ──────────────┐ │ ▼ │ [ 返回最终答案 ] │ │ │ ▼ │ 用户收到回复 │ ▼ [ 提取工具名和参数 ] │ ▼ [ 调用对应工具 ] │ ▼ [ 获取观察结果 ] │ ▼ [ 将观察加入历史 ] │ └─────────────────────────────────────────────┘ 循环关键组件详解提示词模板的魔力ReAct提示词模板通常包含以下部分你是一个有帮助的助手可以使用以下工具 {tool_descriptions} 使用格式 思考你需要思考现在要做什么 行动要调用的工具名 行动输入工具的输入 观察工具返回的结果 ... (这个循环可以重复多次) 最终答案给用户的最终回复 开始 之前的对话 {chat_history} 用户{input} {agent_scratchpad}{tool_descriptions}: 被替换为所有工具的详细描述。{chat_history}: 被替换为之前的对话记录。{agent_scratchpad}: 这是一个特殊变量在运行过程中它会动态填充之前步骤的“思考-行动-观察”记录让LLM知道已经发生了什么。输出解析器Output ParserLLM生成的是文本如“思考... 行动calculator ...”ReActSingleInputOutputParser负责将这段文本解析成结构化的AgentAction对象包含tool和tool_input或AgentFinish对象包含最终答案。工具调用与观察AgentExecutor根据解析出的AgentAction找到对应的工具实例传入参数并执行。工具的返回结果被包装成Observation然后和之前的记录一起被格式化成新的agent_scratchpad送入下一轮LLM调用。这个循环会一直持续直到LLM输出“最终答案”开头的文本被解析器识别为AgentFinish循环结束。9. 常见问题与排查指南在开发AI Agent的过程中你一定会遇到各种问题。以下是几个最常见的问题及其解决方案9.1 Agent不调用工具直接胡编乱造现象对于明显应该使用工具的问题如计算、查询时间Agent直接用LLM的知识生成一个可能错误的答案。可能原因及解决方案工具描述不清晰检查工具的description字段。描述必须清晰、无歧义明确指出工具的用途和适用场景。例如“用于数学计算”比“一个工具”要好得多。提示词模板不匹配确保你使用的提示词模板如hwchase17/react是专为ReAct Agent设计的。错误的模板可能无法引导LLM正确格式化输出。LLM温度Temperature过高在工具调用场景下建议将temperature设为0或接近0的值以减少输出的随机性使Agent更稳定地遵循指令。工具描述过长或过短描述需要精炼且包含关键词。可以进行A/B测试调整描述看效果。9.2 Agent陷入死循环或达到最大迭代次数现象Agent反复调用同一个工具或者在不同工具间来回切换始终无法输出最终答案。可能原因及解决方案工具返回结果格式不佳工具返回的观察Observation应该是清晰、简洁的文本。如果返回了过于复杂或混乱的JSON/HTMLLLM可能无法理解导致决策错误。确保工具输出是纯文本且信息明确。任务过于复杂或定义不清LLM可能无法规划出清晰的解决路径。尝试将用户问题拆解得更简单或者为复杂任务设计专门的“规划工具”。调整max_iterations和early_stopping_method可以适当增加max_iterations例如到15或尝试不同的停止方法。在提示词中加强指令在系统提示词中明确加入“如果你认为已经得到足够信息来回答问题请输出‘最终答案’”之类的指令。9.3 解析错误Parsing LLM output produced both final answer and actions现象控制台报错提示无法解析LLM的输出。可能原因及解决方案LLM输出格式不符合预期ReAct要求严格的“思考... 行动... 行动输入...”格式。有时LLM会自由发挥。确保提示词模板正确并考虑使用能力更强的模型如GPT-4。启用handle_parsing_errorsTrue正如我们在代码中做的这个参数能让AgentExecutor在解析失败时尝试修复或给出友好错误而不是直接崩溃。9.4 如何调试Agent的思考过程最佳实践设置verboseTrue这是最重要的调试手段所有中间步骤一览无余。记录日志将Agent的运行日志包括思考、行动、观察保存到文件便于离线分析。使用LangSmith如果你有LangChain的商业版LangSmith它提供了强大的Agent跟踪和可视化调试工具。10. 工程实践与进阶建议当你掌握了基础构建方法后以下建议可以帮助你将AI Agent应用到实际项目中10.1 工具设计原则单一职责每个工具只做一件事并把它做好。避免创建“瑞士军刀”式的工具。清晰的输入输出使用Pydantic模型严格定义输入输出应为结构化的字符串。健壮的错误处理工具内部必须处理异常并返回对人类和LLM都友好的错误信息。添加语义描述在description中尽可能使用自然语言描述工具能解决哪类“用户问题”而不仅仅是技术功能。10.2 提示词工程优化Few-Shot示例在提示词中加入几个工具调用的完整示例Thought/Action/Observation循环能显著提升Agent的格式遵循能力和决策质量。系统角色设定在提示词开头明确Agent的角色和能力边界例如“你是一个专业的数学和查询助手擅长使用工具来获取精确信息。”约束指令明确告诉Agent什么不能做例如“不要猜测信息如果不知道或需要最新数据请使用搜索工具。”10.3 生产环境部署考量超时与重试为工具调用和LLM调用设置合理的超时和重试机制。限流与降级对LLM API和关键工具进行限流防止过度调用。在工具失败时有降级方案如返回缓存数据或友好提示。可观测性记录每一次Agent运行的完整轨迹包括工具调用、耗时、结果这对于监控、审计和优化至关重要。安全性工具权限隔离危险操作如文件删除、数据库写入的工具需要更严格的权限控制和用户确认。输入验证与清理对所有用户输入和工具输入进行严格的验证和清理防止注入攻击。敏感信息过滤在日志和观察结果中过滤掉API密钥、个人信息等敏感数据。10.4 探索更强大的Agent类型LangChain提供了多种Agent类型适用于不同场景create_react_agent标准ReAct适合大多数需要推理和工具调用的场景。create_structured_chat_agent使用聊天模型支持更复杂的多工具调用和参数结构是当前的主流推荐。create_json_agent要求LLM输出JSON格式的动作解析更稳定。create_openai_tools_agent专为OpenAI的Function Calling功能优化兼容性最好。你可以根据需求尝试不同的Agent类型观察其表现差异。从理解ReAct的核心思想到用LangChain构建第一个能调用工具的AI Agent我们完成了一次从理论到实践的完整穿越。关键在于AI Agent不是魔法而是一套设计良好的系统它将LLM的推理能力与外部工具的执行能力通过ReAct这样的机制有机结合。真正的挑战往往在后续如何设计更智能的工具如何优化提示词以提升稳定性如何将多个Agent组合成复杂的工作流这些问题就留待你在具体的项目中去探索和解决了。