AI Agent 开发框架与工程实践:从 ReAct 循环到生产级智能体
一、Agent 到底解决了什么问题
过去调用大模型是"一问一答":你提问,它回答。但真实业务很少是一次问答能搞定的——“帮我查一下上个月华东区的销售数据,画成图表,写一段分析结论,发到群里”——这需要理解意图、调用多个工具、按顺序执行、汇总结果。Agent(智能体)的本质,就是把"模型 + 工具 + 循环"组合起来:模型负责推理决策,工具负责执行动作,循环负责反复"思考—行动—观察"直到任务完成。
这个模式的祖师爷是 ReAct 论文:交替输出 Thought(推理)与 Action(行动),观察工具返回结果后继续思考,直到得出 Final Answer。今天所有主流 Agent 框架,无论包装得多花哨,核心循环都是这一套。理解这一点很重要:框架只是工程脚手架,思想才是地基。
二、Agent 的核心组成部件
一个可工作的 Agent 系统,无论用什么框架,都由四个部件构成。
模型层负责推理。这里的工程要点是"一个 Agent 不一定只用一个模型":规划用强模型,摘要用轻模型,不同环节按成本与能力分配,是降本增效最直接的手段。
工具层是 Agent 能力的边界。工具注册表要管理工具的名称、描述、参数 Schema,描述写得越准确,模型越不会乱调用。工具必须可观测——入参、出参、耗时、错误全记录,因为 Agent 的每次决策都依赖工具反馈。
记忆层解决上下文问题。短期记忆是当前任务里的对话与工具结果,长期记忆是跨会话的知识沉淀。记忆不是把所有历史都塞给模型,而是有选择地注入最相关的部分。
规划层负责任务分解。简单任务一步完成,复杂任务要拆成子步骤,甚至让 Agent 动态决定下一步做什么。规划能力决定 Agent 的上限,也是最难调优的部分。
三、框架选型:主流方案的坐标系
当前生态里,框架大致分三类。
LangChain / LangGraph:生态最全、概念最多的路线。LangChain 提供组件库,LangGraph 在其上提供状态图编排——把 Agent 流程画成有向图,节点是处理步骤,边是状态流转,支持条件分支、循环、并行、人工介入。适合流程明确、需要精细控制的场景,也是我最推荐作为学习起点的框架。
CrewAI:角色化分工路线。把 Agent 定义成"研究员""审核员"等角色,每个角色有目标、背景故事和工具,用流程(Process)把它们串起来协作。上手极快,适合固定流程的自动化——报告生成、代码审查、内容流水线。
AutoGen / AG2:对话驱动路线。多个 Agent 通过对话协作,支持人类以参与者身份混入。适合开放式的多角色讨论、辩论、谈判类场景,但在控制性上不如状态图方案。
选型建议遵循一条原则:**流程确定性越高,越适合显式状态图;协作开放性越强,越适合对话驱动。**另外,国内团队还要考虑模型兼容性和私有化部署成本,这些往往比框架本身的特性更早成为瓶颈。
四、动手构建:一个带工具的 Agent
抛开复杂框架,先用原生方式理解核心循环。一个最小 Agent 可以这样实现:
import json
class MinimalAgent:
def __init__(self, llm, tools):
self.llm = llm # 模型调用封装
self.tools = {t["name"]: t for t in tools}
def run(self, task: str, max_steps: int = 8) -> str:
messages = [{"role": "user", "content": task}]
for _ in range(max_steps):
resp = self.llm.chat(
messages,
tools=list(self.tools.values()),
)
msg = resp["choices"][0]["message"]
messages.append(msg)
if msg.get("tool_calls"):
for call in msg["tool_calls"]:
result = self.tools[call["function"]["name"]]["func"](
**json.loads(call["function"]["arguments"])
)
messages.append({
"role": "tool",
"tool_call_id": call["id"],
"content": json.dumps(result, ensure_ascii=False),
})
else:
return msg["content"]
raise TimeoutError("超过最大步数")
```
这段代码不足三十行,却包含了 Agent 的全部骨架:模型循环、工具调用、结果回填、步数上限。看懂它,再去看任何框架文档都会觉得似曾相识——框架只是把骨架做成了可配置的工程组件。
## 五、生产级 Agent 的工程清单
demo 与生产之间隔着一整条工程清单,逐条过一遍:
**1. 步数上限与预算控制。**Agent 循环可能失控,必须设置最大步数、最大 token、最大成本三个闸门。任何一条触顶就终止并返回当前进度,而不是无限烧钱。
**2. 工具权限最小化。**Agent 拥有的工具就是它能造成的破坏面。文件系统、数据库、支付接口这类高风险工具要单独授权、单独审计。生产系统里,"Agent 能执行任意命令"是事故高发设计。
**3. 失败恢复与重试。**工具调用失败时,把错误信息回喂给模型让它换一种方式再试,是 Agent 的基本功。但重试要有上限,且连续失败要触发降级路径。
**4. 人工审批节点。**高风险动作(发送邮件、下单、删除数据)要插入确认环节。流程图上画一个人工审核节点,成本极低,收益是防止 Agent 在错误方向上越走越远。
**5. 可观测性。**Agent 的每一步——思考内容、调用工具、耗时、成本——都要有日志。调 Agent 本质上是调一个黑盒决策系统,没有完整轨迹就无从优化。轨迹回放(Trace)是调试 Agent 最重要的手段。
**6. 评测体系。**准备一批典型任务,定义"成功"标准,每次改动模型、提示词、工具定义后跑一遍回归。Agent 系统的退化往往是渐进的,评测是唯一能早期发现的机制。
**7. 防 Prompt 注入。**工具返回的外部内容可能夹带恶意指令。隔离系统提示词与外部内容,对不可信输入做标记,是安全底线。
## 六、工程上最容易踩的坑
最后说几个反复出现的坑。第一个是"工具描述写得太随意",模型理解不了工具的用途和边界,自然乱调用;工具描述值得像 API 文档一样认真写。第二个是"上下文无限膨胀",每轮循环都把全部历史塞回去,很快就超出窗口且注意力涣散,要有摘要和裁剪策略。第三个是"迷信单一大模型",把所有环节都交给最强模型,成本高不说,还忽略了小模型在格式稳定任务上的性价比。第四个是"没有终止条件之外的人工兜底",Agent 卡死、绕圈、自说自话时,系统必须有人能打断的入口。
## 七、实战:用 LangGraph 编排一个带人工审核的流程
理解了最小循环,再看框架就是锦上添花。以 LangGraph 为例,它把 Agent 流程建模成状态图:节点是处理步骤,边是状态流转,支持条件分支、循环、并行与人工介入。一个典型场景——"调研→写方案→审核→发布"——可以这样组织:
```python
from typing import TypedDict, Literal
from langgraph.graph import StateGraph, END
class AgentState(TypedDict):
topic: str
research: str
draft: str
review: str
approved: bool
def research_node(state: AgentState) -> dict:
# 调用检索工具收集资料,写入 state["research"]
return {"research": run_search(state["topic"])}
def draft_node(state: AgentState) -> dict:
return {"draft": llm_write(state["research"])}
def review_node(state: AgentState) -> dict:
# 调用审查 Agent 或人工接口,返回意见
return {"review": review_draft(state["draft"]), "approved": True}
def should_rewrite(state: AgentState) -> Literal["draft", "publish"]:
return "publish" if state["approved"] else "draft"
graph = StateGraph(AgentState)
graph.add_node("research", research_node)
graph.add_node("draft", draft_node)
graph.add_node("review", review_node)
graph.set_entry_point("research")
graph.add_edge("research", "draft")
graph.add_edge("draft", "review")
graph.add_conditional_edges("review", should_rewrite, {"draft": "draft", "publish": END})
app = graph.compile()
这段代码展示了状态图的两大优势:一是显式控制,审核不通过就回到草稿节点重写,不会无限发散;二是可中断可恢复,人工审核节点可以等待外部确认后再继续,这在生产系统里是刚需。LangGraph 的 checkpointer 机制还支持跨节点保存状态快照,进程重启后能从断点续跑。
选型时值得留意一点:LangGraph 概念密度高,学习曲线偏陡;如果团队里没有熟悉状态机的人,或者业务流程很简单,直接用自带工具循环的轻量框架甚至手写循环,反而更可控。框架服务于流程复杂度,不是越重越好。
八、评测与监控:Agent 系统的体检机制
Agent 系统上线后最大的风险是"渐进式退化"——模型升级、工具接口变更、数据分布漂移,都可能让成功率悄悄下滑。对抗它只有一套机制:持续评测与监控。
评测侧,维护一个任务集,覆盖典型场景与边界场景,每次变更跑回归。任务集要包含"成功路径"“失败恢复”"拒绝执行"三类样本——不仅要测 Agent 能不能完成任务,还要测它会不会在不该行动时乱动。指标上,任务完成率是核心,单步工具调用成功率、平均步数、平均成本、超时率作为辅助维度。
监控侧,生产环境记录每条轨迹的结构化日志:思考内容、工具调用参数与返回值、耗时、token 消耗、最终结果。有了轨迹,就能做失败聚类——把日志按错误类型聚合,看 Top 失败原因是什么。实践中大量 Agent 事故的根因,都是靠回放轨迹定位的:某次工具返回了异常结构、某轮提示词被污染、某次重试逻辑死循环,一目了然。
最后,给 Agent 系统设置"闸门":单任务最大成本、最大步数、单日总预算,超限自动熔断。Agent 的失控往往不是一次大事故,而是无数小浪费的累积,预算闸门能让异常在造成损失前被拦住。
Agent 不是玄学,它是一套"推理—行动—观察"的工程循环。框架会不断迭代,但把模型当决策者、把工具当手、把记忆当笔记本、把评测当体检这套思维,会一直有效。先把最小循环跑通,再逐步加工程保障,是每个 Agent 项目最务实的路径。
更多推荐


所有评论(0)