Agent 是 2024 年最热也最被滥用的词。"AI Agent""LangGraph Agent""自主 Agent""Multi-Agent" —— 听起来花样很多,但拆开看,所有 Agent 系统的核心都是同一个循环:感知 → 决策 → 行动 → 观察 → 再决策。这篇文章把 Agent 从最基础的 ReAct 模式讲到 Plan-and-Execute、Multi-Agent、Reflective Agent,讲清楚不同模式适合什么场景,以及生产级 Agent 必须解决的工程问题。
什么是 Agent
简化定义:能自主决策"下一步做什么"的 AI 程序。区别于:
- 普通 LLM 对话:用户问一句,LLM 答一句,没有"做事"。
- Workflow:固定流程,A → B → C,LLM 只是在某些节点参与。
- Agent:LLM 决定整个流程,根据上下文自主选择工具、决定下一步、判断何时停止。
Anthropic 在《Building Effective Agents》里给的判断标准最实用:"当任务的解决路径不能预先确定时,才需要 Agent;路径确定时,用 Workflow 更可靠"。
最简单的 Agent:ReAct 模式
ReAct = Reasoning + Acting。Google 2022 年提出。基本流程:
循环:
Thought:LLM 思考"接下来该做什么"
Action:LLM 选择一个工具调用
Observation:程序执行工具,把结果给 LLM
(再循环)
Final Answer:LLM 决定任务完成,给出最终答案
def react_agent(question, tools, max_steps=10):
messages = [
{"role": "system", "content": REACT_SYSTEM_PROMPT},
{"role": "user", "content": question}
]
for step in range(max_steps):
response = llm(messages, tools=tools)
if response.tool_calls:
for call in response.tool_calls:
result = execute(call)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result),
})
messages.append(response.message)
else:
# LLM 没调工具,说明它认为任务完成了
return response.message.content
return "达到最大步数,任务未完成"
REACT_SYSTEM_PROMPT = """
你是一个 AI 助手,可以使用工具完成任务。
工作流程:
1. 思考用户问题需要哪些信息
2. 调用合适的工具获取信息
3. 基于工具返回的结果继续思考或得出最终答案
4. 不要编造工具不返回的信息
如果你已经有足够信息回答,直接给出最终回答,不再调用工具。
"""
ReAct 简单但强大。Cursor、Claude Code、ChatGPT 的 GPT-4 都是 ReAct 的变体。
实战:做一个能查文档、查代码、查数据库的 Agent
tools = [
{
"type": "function",
"function": {
"name": "search_docs",
"description": "在内部文档库搜索。用于查找概念、规范、流程类信息。",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string"}
},
"required": ["query"]
}
}
},
{
"type": "function",
"function": {
"name": "search_code",
"description": "在代码库搜索。用于查找函数定义、类实现、代码示例。",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string"},
"file_pattern": {"type": "string", "description": "如 *.py"}
},
"required": ["query"]
}
}
},
{
"type": "function",
"function": {
"name": "query_db",
"description": "查询业务数据库。返回数据用于回答业务问题。",
"parameters": {
"type": "object",
"properties": {
"sql": {"type": "string", "description": "只允许 SELECT 语句"}
},
"required": ["sql"]
}
}
},
]
def execute(call):
name = call.function.name
args = json.loads(call.function.arguments)
if name == "search_docs":
return rag_search(args["query"])
elif name == "search_code":
return ripgrep_search(args["query"], args.get("file_pattern", "*"))
elif name == "query_db":
if not args["sql"].strip().upper().startswith("SELECT"):
return {"error": "只允许 SELECT"}
return db.execute(args["sql"])
# 用户问:"上个月有多少订单是 VIP 用户下的?"
react_agent("上个月有多少订单是 VIP 用户下的?", tools)
# Agent 内部:
# Step 1: query_db("SELECT user_level FROM users LIMIT 1") - 探索表结构
# Step 2: query_db("SELECT COUNT(*) FROM orders WHERE user_level='VIP' AND created_at >= ...")
# Final Answer: "上个月有 1234 单 VIP 订单"
Plan-and-Execute:先规划再执行
ReAct 是"边想边做",对复杂任务可能走偏。Plan-and-Execute 是"先做完整计划,再逐步执行":
# 第 1 步:Planner 生成计划
plan_prompt = f"""
任务:{user_task}
请生成完成这个任务的步骤列表,每个步骤可以调一个工具。
可用工具:{tool_descriptions}
输出 JSON:
{{
"steps": [
{{"step_id": 1, "description": "...", "tool": "..."}},
...
]
}}
"""
plan = llm(plan_prompt).parse_json()
# 第 2 步:Executor 逐个执行
results = []
for step in plan["steps"]:
result = execute_step(step, prev_results=results)
results.append(result)
# 第 3 步:Synthesizer 整合
final = llm(f"基于以下结果总结答案:{results}")
适用场景:
- 任务步骤多、依赖明确(行程规划、研究报告生成)。
- 每步成本高,需要先看到全局再决定要不要执行。
缺点:计划可能不完整,执行中遇到意外难以调整。改进:做"动态 replan" —— 每执行一步,检查"原计划还合理吗?",不合理就重新 plan。
Reflective Agent:让 Agent 自我反思
Agent 执行完任务后,让它自己检查是否真的完成了:
def reflective_agent(question, tools):
answer = react_agent(question, tools)
# 反思
reflect_prompt = f"""
任务:{question}
当前回答:{answer}
请检查:
1. 回答是否完整解决了用户问题?
2. 是否有信息缺失或不准确?
3. 是否需要进一步操作?
如果回答不够好,说明缺什么,并给出改进方向(不要直接改答案)。
如果回答 OK,输出 "OK"。
"""
critique = llm(reflect_prompt)
if "OK" in critique:
return answer
# 用批评作为新的 prompt,让 agent 再做一轮
return react_agent(f"{question}\n\n之前的回答不够好,问题:{critique}\n请重新解决。", tools)
这种"反思 + 重做"在写代码、写报告、做研究等开放性任务上效果显著。代价是 token 翻倍。
Multi-Agent:多个角色协作
当任务涉及多种专业能力,可以让多个 Agent 协作:
# 例:写技术文章
agents = {
"researcher": "你是研究员,负责搜集资料、确认事实",
"writer": "你是作者,基于资料撰写连贯文章",
"reviewer": "你是审稿人,挑出文章里的问题",
"editor": "你是编辑,基于审稿意见改稿",
}
# 协作流程
draft_topic = "如何配置 K8s HPA"
facts = run_agent("researcher", f"研究 {draft_topic} 的关键事实", tools=[search, rag])
draft = run_agent("writer", f"基于以下资料写一篇关于 {draft_topic} 的文章:\n{facts}")
critique = run_agent("reviewer", f"审查这篇文章:\n{draft}")
final = run_agent("editor", f"基于审稿意见改稿:\n原文:{draft}\n意见:{critique}")
Multi-Agent 适合:
- 角色专业化能提升质量(代码生成 + 安全审计 + 性能优化分开)。
- 视角多样性能减少偏见(支持方 + 反对方辩论)。
但代价:
- Token 成本几倍。
- 调试困难(一个 bug 可能源于多个 agent 之间的交互)。
- 容易"无限对话",Agent 之间互相挑刺、改稿不收敛。
实战经验:能用单 Agent 就用单 Agent。Multi-Agent 在复杂任务有价值,但简单任务上往往是过度设计。
Agent 的关键工程挑战
1. 内存管理
长会话 / 多步骤 Agent 的对话历史会膨胀。策略:
- 滑动窗口:只保留最近 N 轮。
- 摘要:超过阈值时,把早期对话摘要为短文本。
- 向量记忆:把对话历史 embed 进向量库,需要时检索回来。
2. 状态持久化
Agent 执行可能跨越多次请求(用户上次说一半,过几分钟回来继续)。需要把 Agent 状态(对话历史、中间结果、当前计划)持久化到数据库,重新拉起来时能恢复。LangGraph、Inngest 都提供 checkpoint 机制。
3. 可观测性
Agent 走了几十步,出错时不知道哪一步出问题。必须有:
- 每一步的 trace:输入、输出、tool call、token 数、耗时。
- 可视化界面:LangSmith / Weave / Helicone 等工具能展示 Agent 执行链。
- 关键指标告警:总 token、总耗时、错误率、用户反馈。
4. 成本控制
Agent 平均一次任务调 5-20 次 LLM,token 成本累积快。控制方法:
- 小任务用便宜模型(Haiku / GPT-4o-mini),复杂决策才用大模型。
- 限制每次任务的最大循环数 + 最大 token 数。
- 缓存常见请求结果。
- 用 Prompt Caching 减少重复 system prompt 的成本。
5. 安全
Agent 能调危险工具(执行代码、改数据库、发邮件)。必须:
- 权限隔离:每个 Agent 只能调它该调的工具,数据库只读、文件系统沙箱。
- 人工审批:破坏性操作要 human-in-the-loop 确认。
- Prompt Injection 防御:用户输入 / 外部数据可能包含恶意指令,要清洗或用 system prompt 加固。
主流 Agent 框架
- LangGraph(LangChain 出品):基于图的 Agent 编排,支持复杂控制流、checkpoint、人工干预。最灵活也最重。
- CrewAI:专注 Multi-Agent 角色协作,API 简单。
- AutoGen(Microsoft):Multi-Agent 对话框架,擅长"群聊式协作"。
- OpenAI Assistants API:OpenAI 官方的轻量 Agent 框架,内置 thread / file search / code interpreter。
- Anthropic Claude with MCP:用 MCP 协议接入工具,简单清晰。
不到必要不要急着上框架。最简 ReAct 循环 100 行代码就能跑,先用裸代码理解清楚再考虑框架。
常见错误
错误 1:用 Agent 解决简单问题。 用户问"现在几点",ReAct 转一圈也只是 get_time —— 但启用 Agent 框架后系统复杂度暴涨,debug 成本暴涨。简单问题用 Workflow / 函数。
错误 2:Agent 一直走但不收敛。 工具数量多 + 任务边界模糊 + 没有明确终止条件 → Agent 不知道什么时候停。修复:明确"什么算完成",在 prompt 里写清。
错误 3:把 Agent 当万能。 Agent 不是 LLM 的"放大器" —— 它是 LLM 决策能力的延伸。如果 LLM 本身能力差,Agent 框架只会放大它的失败。
错误 4:不做评估。 Agent 上线后凭感觉调,无数据支撑。必须有自动化评估集:典型任务 50 个,每次改动跑一遍,看完成率、平均步数、token 成本。
Agent 设计的几个反直觉经验
1. 给 Agent 越少工具越好
新手常犯错误:把 30 个工具一股脑给 Agent,期待它"自动选对的"。实际上工具越多,LLM 选错的概率越高。把工具限制在 5-10 个,任务范围对应缩窄,Agent 表现反而更好。需要更多工具时,用 sub-agent 拆分。
2. Prompt 里"指导推理"而不是"指导动作"
不要写"调用 search 工具",而是写"先理解用户的真实意图,再判断什么信息需要查询,然后选合适的工具"。LLM 自己会想到工具,但你要引导它的推理过程。
3. 失败信号要明确
工具返回空、404、参数错 —— 必须以 LLM 能立刻理解的方式呈现:
# 不好:返回 None
def search_docs(query):
results = vector_db.query(query)
if not results:
return None # LLM 看到 null,不知所措
# 好:返回结构化的明确信息
def search_docs(query):
results = vector_db.query(query)
if not results:
return {
"status": "no_results",
"message": f"未找到关于 '{query}' 的文档。建议:换个关键词或尝试更宽泛的查询。"
}
return {"status": "ok", "results": results}
Human-in-the-Loop:Agent 不该全自动
对涉及钱、对外发消息、修改重要数据的操作,设计"暂停 + 等用户确认"机制:
def execute_with_approval(call):
if call.function.name in HIGH_STAKES_TOOLS:
# 暂停 Agent,把意图展示给用户
approval = await ask_human(
action=call.function.name,
args=call.function.arguments,
preview=f"即将向 {args['to']} 发送邮件:'{args['subject']}'"
)
if not approval:
return {"status": "cancelled_by_user"}
return execute(call)
LangGraph 的 interrupt 机制就是为这个设计的 —— Agent 流到某个节点时挂起,等外部信号(用户点了批准按钮)再继续。这是生产级 Agent 必备能力。
写在最后
Agent 不是魔法,它是"LLM + Function Calling + 循环"的工程组合。所有看似神奇的 Agent(Devin、Cursor、Claude Code)拆开看,都是这套机制的精心打磨 —— 工具设计、prompt 调优、错误处理、状态管理、可观测性。理解这一点,你看到任何新 Agent 框架都能快速判断它在解决什么、值不值得用。
给一个工程心得:Agent 项目的成败,80% 在"工具设计"和"评估机制",20% 才在"用什么框架"。把工具的描述、参数、返回值都设计成"LLM 容易理解、不易调错"的形式;建一组真实场景的评估集,每次改动有数据反馈。把这两件事做扎实,Agent 自然能跑起来。下一篇我们看 LangChain / LlamaIndex 这些框架的实际用法。
—— 别看了 · 2026