单智能体(Single Agent)落地实践全指南:从 ReAct 到 Tool Use,构建真正可靠的 AI Agent
单智能体(Single Agent)落地实践全指南:从 ReAct 到 Tool Use,构建真正可靠的 AI Agent
导语:2025-2026 年,AI Agent 成为技术圈最热词汇,但"Agent 落地难"同样成为共识——幻觉、循环调用、工具滥用、输出不可控……诸多问题让开发者望而却步。本文聚焦单智能体落地实践,系统梳理 ReAct 执行框架、工具调用设计、可靠性工程和典型应用场景,帮助你把 Agent 从 Demo 推向生产。
一、什么是真正可用的 AI Agent?
首先澄清一个常见误区:不是所有会调用工具的 LLM 应用都是 Agent。
| 类型 | 特征 | 典型场景 |
|---|---|---|
| 普通 LLM 调用 | 单次推理,固定输入输出 | 文本分类、摘要生成 |
| RAG 应用 | 检索 + 生成,流程固定 | 知识库问答 |
| AI Agent | 自主规划、动态调用工具、多步执行 | 复杂任务自动化 |
真正的 AI Agent 核心特征:
- 规划能力:将复杂目标分解为可执行步骤
- 工具使用:动态调用外部工具(API、数据库、代码执行器)
- 反馈循环:根据执行结果调整下一步行动
- 记忆管理:维护任务上下文和历史状态
二、ReAct:单智能体的核心执行框架
ReAct(Reasoning + Acting)是目前最广泛使用的 Agent 执行框架,由 Google Research 于 2022 年提出。
2.1 ReAct 执行循环
用户问题 ↓ [Thought] 我需要先查询XX,再计算YY... ↓ [Action] 调用 search_tool(query="XX") ↓ [Observation] 搜索结果:{...} ↓ [Thought] 根据结果,我需要进一步... ↓ [Action] 调用 calculator(expression="...") ↓ [Observation] 计算结果:42 ↓ [Thought] 现在我可以回答了 ↓ [Final Answer] 最终答案是...2.2 ReAct 的工程实现
fromlangchain.agentsimportcreate_react_agent,AgentExecutorfromlangchain.toolsimportToolfromlangchain_core.promptsimportPromptTemplate# 定义工具tools=[Tool(name="SearchWeb",func=web_search.run,description="搜索互联网获取最新信息。输入:搜索查询字符串"),Tool(name="Calculator",func=calculator.run,description="执行数学计算。输入:数学表达式字符串,如 '2 * 3 + 1'"),Tool(name="QueryDatabase",func=db_query.run,description="查询内部数据库。输入:SQL 查询语句(仅支持 SELECT)"),]# ReAct Prompt 模板react_prompt=PromptTemplate.from_template("""你是一个智能助手,可以使用以下工具完成任务: {tools} 使用格式: Question: 需要回答的问题 Thought: 你应该先思考怎么做 Action: 工具名称(必须是以下之一:{tool_names}) Action Input: 工具的输入 Observation: 工具的返回结果 ... (Thought/Action/Action Input/Observation 可以重复多次) Thought: 现在我知道最终答案了 Final Answer: 对原始问题的最终答案 开始! Question: {input} Thought: {agent_scratchpad}""")# 创建 Agentagent=create_react_agent(llm=llm,tools=tools,prompt=react_prompt)agent_executor=AgentExecutor(agent=agent,tools=tools,max_iterations=10,# 防止无限循环verbose=True,handle_parsing_errors=True,# 处理解析错误return_intermediate_steps=True)三、工具设计:决定 Agent 上限的关键
3.1 工具设计的黄金法则
好的工具设计应遵循以下原则:
① 原子性:每个工具只做一件事
# ❌ 不好的设计:一个工具做太多事defget_user_and_orders(user_id:str)->dict:"""获取用户信息和所有订单"""...# ✅ 好的设计:拆分为独立工具defget_user_info(user_id:str)->dict:"""获取用户基本信息。输入:用户ID(如 'usr_123')"""...defget_user_orders(user_id:str,status:str="all")->list:"""获取用户订单列表。输入:用户ID,可选订单状态('pending'/'completed'/'all')"""...② 描述清晰:工具 description 要精确告诉 LLM 什么时候用、怎么用:
# ❌ 不好的描述description="查询数据库"# ✅ 好的描述description="""查询产品库存信息。 适用场景:需要查询特定产品的当前库存数量时使用。 输入格式:产品SKU代码(如 'SKU-ABC123') 输出格式:返回 JSON,包含 sku、quantity、warehouse_location 字段 注意:仅支持查询,不支持修改操作"""③ 幂等性:只读操作优先,写操作需要确认机制
defsend_email(to:str,subject:str,body:str,dry_run:bool=True)->dict:""" 发送邮件。 dry_run=True 时仅返回预览,不实际发送(默认值,安全)。 确认无误后设置 dry_run=False 执行发送。 """ifdry_run:return{"status":"preview","to":to,"subject":subject,"body":body}# 实际发送逻辑...④ 错误友好:工具返回的错误信息要让 LLM 能理解并调整策略
defquery_database(sql:str)->dict:try:result=db.execute(sql)return{"success":True,"data":result,"row_count":len(result)}exceptPermissionError:return{"success":False,"error":"无权限执行此操作,仅支持 SELECT 语句"}exceptSyntaxErrorase:return{"success":False,"error":f"SQL 语法错误:{str(e)},请检查语法"}exceptExceptionase:return{"success":False,"error":f"查询失败:{str(e)}"}3.2 Function Calling vs 提示词工具调用
现代 LLM 原生支持Function Calling(工具调用),相比基于提示词的 ReAct 更可靠:
# OpenAI Function Calling 格式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"]}}}]response=client.chat.completions.create(model="gpt-4o",messages=messages,tools=tools,tool_choice="auto"# auto/required/none)Function Calling 相比 ReAct 的优势:
- 结构化输出,不依赖 LLM 的文本格式稳定性
- 参数验证由框架层保证,减少解析错误
- 支持并行工具调用(parallel tool use)
四、记忆管理:让 Agent 记住关键信息
单智能体的记忆分四层:
┌─────────────────────────────────────┐ │ Sensory Memory(感知记忆) │ │ 当前输入的原始信息,瞬时处理 │ ├─────────────────────────────────────┤ │ Working Memory(工作记忆) │ │ 当前对话上下文 + 任务执行状态 │ │ 存储位置:LLM Context Window │ ├─────────────────────────────────────┤ │ Episodic Memory(情节记忆) │ │ 历史对话摘要 + 任务执行记录 │ │ 存储位置:向量数据库 / Redis │ ├─────────────────────────────────────┤ │ Semantic Memory(语义记忆) │ │ 领域知识 / 用户偏好 / 实体信息 │ │ 存储位置:知识库 / 结构化数据库 │ └─────────────────────────────────────┘4.1 会话记忆管理
fromlangchain.memoryimportConversationSummaryBufferMemory# 结合总结与缓冲的混合记忆策略memory=ConversationSummaryBufferMemory(llm=llm,max_token_limit=2000,# 超过此 token 数时自动总结return_messages=True,memory_key="chat_history")4.2 长期记忆存储
# 使用向量数据库存储 Agent 长期记忆fromlangchain.memoryimportVectorStoreRetrieverMemoryimportfaissfromlangchain_community.vectorstoresimportFAISS embedding_size=1536index=faiss.IndexFlatL2(embedding_size)vectorstore=FAISS(embeddings.embed_query,index,InMemoryDocstore({}),{})retriever=vectorstore.as_retriever(search_kwargs={"k":5})memory=VectorStoreRetrieverMemory(retriever=retriever)# 保存重要信息到长期记忆memory.save_context({"input":"用户偏好使用 Python"},{"output":"已记录:用户代码示例优先使用 Python"})五、可靠性工程:让 Agent 在生产环境稳定运行
5.1 防护栏设计(Guardrails)
fromguardrailsimportGuardfromguardrails.hubimportToxicLanguage,DetectPII guard=Guard().use_many(ToxicLanguage(on_fail="exception"),# 过滤有害内容DetectPII(pii_entities=["EMAIL","PHONE_NUMBER"],on_fail="fix")# 脱敏 PII)defsafe_agent_run(user_input:str)->str:# 输入验证validated_input=guard.validate(user_input)# Agent 执行result=agent_executor.invoke({"input":validated_input})# 输出验证validated_output=guard.validate(result["output"])returnvalidated_output5.2 循环检测与中断机制
classLoopDetector:def__init__(self,max_same_action:int=3):self.action_history=[]self.max_same=max_same_actiondefcheck(self,action:str,action_input:str)->bool:"""如果相同行动重复超过阈值,返回 True(需要中断)"""key=f"{action}:{action_input}"self.action_history.append(key)recent=self.action_history[-self.max_same:]iflen(recent)==self.max_sameandlen(set(recent))==1:returnTrue# 检测到循环returnFalse5.3 超时与资源限制
importasynciofromfunctoolsimportwrapsdeftimeout(seconds:int):"""工具调用超时装饰器"""defdecorator(func):@wraps(func)asyncdefwrapper(*args,**kwargs):try:returnawaitasyncio.wait_for(asyncio.coroutine(func)(*args,**kwargs),timeout=seconds)exceptasyncio.TimeoutError:return{"error":f"工具执行超时({seconds}s),请简化查询或稍后重试"}returnwrapperreturndecorator@timeout(30)asyncdefweb_search(query:str)->str:# 搜索逻辑...六、典型落地场景与方案
场景 1:企业内部知识助手
工具集:RAG检索 + 日历查询 + 邮件发送(dry_run) 记忆:用户偏好 + 历史问答摘要 防护:PII 过滤 + 权限校验(员工级别)场景 2:代码 Debug Agent
工具集:代码执行 + 文档搜索 + 日志查询 + Git历史 记忆:Bug上下文 + 已尝试方案 防护:沙箱代码执行 + 危险操作拦截场景 3:数据分析 Agent
工具集:SQL查询(只读)+ Python代码执行 + 图表生成 记忆:数据表 Schema + 分析目标 防护:SQL注入检测 + 执行时间限制 + 结果行数限制七、常见问题排查指南
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| Agent 不调用工具 | 工具描述不清晰 | 优化 description,添加使用示例 |
| Agent 循环调用 | 工具无法完成目标,Agent 陷入循环 | 添加循环检测 + max_iterations |
| 工具参数格式错误 | LLM 生成参数不符合预期 | 使用 Function Calling,添加 JSON Schema 验证 |
| 答案忽略工具结果 | Observation 不够显著 | 在 Prompt 中强调"必须基于工具结果回答" |
| 执行时间过长 | 工具调用链过长 | 并行工具调用 + 工具超时限制 |
八、总结
构建可靠的单智能体,核心要素:
- 执行框架:ReAct 或 Function Calling,后者在生产环境更稳定
- 工具设计:原子性、清晰描述、幂等性、错误友好
- 记忆管理:工作记忆 + 长期记忆分层设计
- 可靠性工程:防护栏 + 循环检测 + 超时限制
单智能体是多智能体的基础单元,只有把单 Agent 打磨稳定,才能构建可靠的多 Agent 系统。
参考文献
- Yao, S., et al. (2022).ReAct: Synergizing Reasoning and Acting in Language Models. ICLR 2023. https://arxiv.org/abs/2210.03629
- Schick, T., et al. (2023).Toolformer: Language Models Can Teach Themselves to Use Tools. NeurIPS. https://arxiv.org/abs/2302.04761
- LangChain Agents 文档. https://python.langchain.com/docs/modules/agents/
- OpenAI Function Calling 文档. https://platform.openai.com/docs/guides/function-calling
- Chase, H. (2023).LangGraph: Building Stateful, Multi-Actor Applications with LLMs. https://github.com/langchain-ai/langgraph
- Guardrails AI 文档. https://www.guardrailsai.com/docs
- 掘金. (2026).2026年AI Agent开发实战:MCP协议深度解析与多智能体架构. https://juejin.cn/post/7628131346834063410
