Python AI Agent 框架对比——LangGraph vs AutoGen vs CrewAI 选型指南
Python AI Agent 框架对比——LangGraph vs AutoGen vs CrewAI 选型指南
适读人群:要构建 AI Agent 系统的工程师 | 阅读时长:约16分钟 | 核心价值:搞清三大 Agent 框架的核心差异,给你一个明确的选型决策框架,不再迷茫
去年底,我参加了一个技术分享会。现场有个工程师小吴分享他们团队的 AI Agent 选型经历,一开口就把我逗乐了:"我们当时同时在三个框架上写了 Demo,开会的时候三个人各吹各的,争了两个小时没结论,最后领导拍板说先用 LangChain,结果又过了一周,有人说 LangGraph 才是正确答案,这时候原型代码已经写了一半了。"
台下笑声一片,因为几乎所有人都有类似的经历。
Agent 框架的选型确实不好做,不像数据库那样有清晰的对比维度。每个框架都声称自己能做"自主决策、多智能体协作、工具调用",但实际用起来差别很大。
我前后用这三个框架各做过真实项目,今天给你一个有实际参考价值的对比。
一、三个框架的核心定位
先说结论,再展开讲:
- LangGraph:图结构的工作流引擎,状态机思维,适合流程可控、需要人工干预节点的复杂 Agent
- AutoGen(微软):多智能体对话框架,多个 AI 角色互相对话协作,适合代码生成、协作研究
- CrewAI:角色扮演式多智能体,用"团队"和"角色"的隐喻组织 Agent,上手快,适合快速原型
二、LangGraph 深度实战
LangGraph 是 LangChain 团队出的,把 Agent 的执行流程抽象成有向图,每个节点是一个处理步骤,每条边是状态转移条件。
2.1 LangGraph 基础用法
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain.tools import tool
from typing import TypedDict, Annotated, List
import operator
# 定义状态结构(贯穿整个图的共享状态)
class AgentState(TypedDict):
messages: Annotated[List, operator.add] # 消息列表,每次追加
user_input: str
search_results: str
final_answer: str
iteration_count: int
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 定义各个节点函数
def search_node(state: AgentState) -> AgentState:
"""搜索节点:根据用户问题搜索相关信息"""
query = state["user_input"]
# 模拟搜索
results = f"关于 '{query}' 的搜索结果:找到3条相关文档"
return {
"messages": [f"搜索完成:{results}"],
"search_results": results,
"iteration_count": state.get("iteration_count", 0) + 1
}
def analyze_node(state: AgentState) -> AgentState:
"""分析节点:分析搜索结果,决定是否需要继续搜索"""
response = llm.invoke(
f"基于以下搜索结果,判断信息是否足够回答问题:\n"
f"问题:{state['user_input']}\n"
f"结果:{state['search_results']}\n"
f"只输出 'sufficient' 或 'insufficient'"
)
judgment = response.content.strip().lower()
return {
"messages": [f"分析判断:{judgment}"],
"search_results": state["search_results"] + f"\n[判断:{judgment}]"
}
def answer_node(state: AgentState) -> AgentState:
"""回答节点:生成最终答案"""
response = llm.invoke(
f"基于以下信息回答问题:\n"
f"问题:{state['user_input']}\n"
f"信息:{state['search_results']}"
)
return {
"messages": [f"最终回答:{response.content}"],
"final_answer": response.content
}
# 路由函数:决定下一步走哪条边
def route_after_analyze(state: AgentState) -> str:
"""分析后的路由:信息足够就回答,不够就继续搜索"""
# 防止无限循环
if state.get("iteration_count", 0) >= 3:
return "answer"
last_message = state["messages"][-1] if state["messages"] else ""
if "sufficient" in last_message:
return "answer"
return "search"
# 构建图
workflow = StateGraph(AgentState)
# 添加节点
workflow.add_node("search", search_node)
workflow.add_node("analyze", analyze_node)
workflow.add_node("answer", answer_node)
# 添加边(连接节点)
workflow.set_entry_point("search") # 入口
workflow.add_edge("search", "analyze") # search → analyze
workflow.add_conditional_edges( # 条件边
"analyze",
route_after_analyze,
{
"search": "search", # 信息不足 → 继续搜索
"answer": "answer" # 信息足够 → 生成回答
}
)
workflow.add_edge("answer", END) # answer → 结束
# 编译
app = workflow.compile()
# 运行
result = app.invoke({
"user_input": "Python 的 GIL 是什么",
"messages": [],
"search_results": "",
"final_answer": "",
"iteration_count": 0
})
print("最终回答:", result["final_answer"])2.2 LangGraph 的核心优势:Human-in-the-loop
from langgraph.checkpoint.memory import MemorySaver
# 添加断点,让人类审查关键步骤
checkpointer = MemorySaver()
# 在关键节点前设置断点
app_with_interrupt = workflow.compile(
checkpointer=checkpointer,
interrupt_before=["answer"] # 在生成答案前暂停,等待人工确认
)
config = {"configurable": {"thread_id": "session-001"}}
# 第一阶段:运行到断点
result = app_with_interrupt.invoke(
{"user_input": "请删除数据库中的所有用户数据", "messages": [], ...},
config=config
)
print("Agent 准备执行,请审查:", result)
# 人工审查...
human_approved = input("确认执行?(yes/no): ").lower() == "yes"
if human_approved:
# 继续执行
final_result = app_with_interrupt.invoke(None, config=config)
print("执行完成:", final_result["final_answer"])
else:
print("人工拒绝,操作已取消")三、AutoGen 深度实战
AutoGen 的核心思想是:让多个 AI 角色互相对话来完成任务。典型场景是一个 AI 写代码,另一个 AI 审查代码,来回几轮直到代码通过测试。
import autogen
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager
# 配置 LLM
llm_config = {
"config_list": [{
"model": "gpt-4o-mini",
"api_key": "your-api-key"
}],
"temperature": 0.3
}
# 定义角色
programmer = AssistantAgent(
name="程序员",
system_message="""你是一个专业的 Python 程序员。
你的任务是编写高质量的 Python 代码。
每次只写一个函数或一个小模块,等待代码审查。
""",
llm_config=llm_config
)
code_reviewer = AssistantAgent(
name="代码审查员",
system_message="""你是一个严格的代码审查专家。
审查代码时关注:正确性、安全性、可读性、性能。
发现问题时,给出具体的修改建议。
如果代码没有问题,输出 "APPROVED"。
""",
llm_config=llm_config
)
# UserProxy 是代表人类的代理,可以执行代码
user_proxy = UserProxyAgent(
name="用户",
human_input_mode="NEVER", # 全自动,不需要人工介入
code_execution_config={
"work_dir": "/tmp/autogen_code",
"use_docker": False # 生产环境建议用 Docker 隔离
},
max_consecutive_auto_reply=10
)
# 多智能体对话
groupchat = GroupChat(
agents=[user_proxy, programmer, code_reviewer],
messages=[],
max_round=15,
speaker_selection_method="round_robin" # 轮流发言
)
manager = GroupChatManager(
groupchat=groupchat,
llm_config=llm_config
)
# 启动对话
user_proxy.initiate_chat(
manager,
message="请编写一个 Python 函数,实现快速排序,要有类型注解和完整的单元测试"
)四、CrewAI 深度实战
CrewAI 用"公司团队"的隐喻:有 Agent(员工)、Task(任务)、Crew(团队),代码读起来最像自然语言。
from crewai import Agent, Task, Crew, Process
from crewai_tools import SerperDevTool, WebsiteSearchTool
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.3)
# 定义智能体(像定义员工一样)
researcher = Agent(
role="市场研究员",
goal="深入研究指定技术主题,收集全面、准确的信息",
backstory="""你是一个有10年经验的技术研究员,擅长快速理解新技术,
能从海量信息中找到关键要点。你的研究报告以准确、全面著称。""",
tools=[SerperDevTool()], # 给研究员搜索工具
llm=llm,
verbose=True,
max_iter=5 # 最多迭代5次
)
writer = Agent(
role="技术文档撰写人",
goal="将研究成果转化为清晰、实用的技术文档",
backstory="""你是一个资深技术作家,擅长把复杂的技术内容写得通俗易懂。
你的文章逻辑清晰,代码示例丰富,深受开发者喜爱。""",
llm=llm,
verbose=True
)
# 定义任务
research_task = Task(
description="""研究 Python 异步编程的最新最佳实践(2024-2025年)。
重点关注:
1. asyncio 的新特性和改进
2. 常见的异步编程陷阱
3. 与主流框架(FastAPI、aiohttp)的集成
输出格式:结构化的研究笔记,包含关键技术点和示例""",
agent=researcher,
expected_output="一份包含5个以上核心要点的研究报告,每个要点有具体说明"
)
writing_task = Task(
description="""基于研究员的报告,撰写一篇技术文章。
要求:
- 面向有 Python 基础但不熟悉异步编程的读者
- 包含至少3个可运行的代码示例
- 总字数 1500-2000 字
- 格式:Markdown""",
agent=writer,
expected_output="一篇完整的 Markdown 格式技术文章",
context=[research_task] # 依赖研究任务的输出
)
# 组建团队
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential, # 顺序执行(也可以用 Process.hierarchical 层级管理)
verbose=True
)
# 执行
result = crew.kickoff()
print(result)五、踩坑实录一:LangGraph 状态更新不符合预期
现象:节点函数明明返回了新的状态值,但在后续节点里拿到的还是旧值。
原因:LangGraph 中,节点函数返回的字典是增量更新而不是覆盖。对于使用 Annotated[List, operator.add] 的字段,会追加而不是替换。
解法:
# 如果你想替换整个列表,不要用 operator.add
class AgentState(TypedDict):
messages: List[str] # 直接替换
# vs
messages: Annotated[List[str], operator.add] # 追加
# 替换时,节点函数直接返回新的完整列表
def reset_messages_node(state: AgentState) -> dict:
return {"messages": ["新的消息"]} # 完全替换 messages六、踩坑实录二:AutoGen 代码执行安全问题
现象:AutoGen 的代码执行功能非常强大,但也非常危险——AI 生成的代码在本地执行,如果 AI 写出了 rm -rf / 这样的代码,会直接执行。
解法:
# 生产环境必须用 Docker 隔离代码执行
code_execution_config = {
"work_dir": "/tmp/autogen_sandbox",
"use_docker": "python:3.11-slim", # 指定 Docker 镜像
"timeout": 30, # 最多执行30秒
}
# 或者用更严格的沙箱
user_proxy = UserProxyAgent(
human_input_mode="ALWAYS", # 每次执行代码前要人工确认
code_execution_config=code_execution_config
)七、踩坑实录三:CrewAI Agent 无限循环
现象:CrewAI 的 Agent 一直在搜索信息,迭代了十几次都没完成任务,消耗了大量 Token 和时间。
原因:任务描述太模糊,Agent 不确定"完成"的标准是什么,一直在"完善"信息。
解法:
# 在 Task 的 expected_output 中明确定义完成标准
research_task = Task(
description="研究 Python 最新特性",
agent=researcher,
expected_output="""一份 JSON 格式的研究报告,包含以下字段:
{
"summary": "100字以内的摘要",
"key_points": ["要点1", "要点2", ...], // 3-5个要点
"sources": ["来源1", ...]
}
完成标准:JSON 格式完整且有效,包含所有字段""",
# 设置最大执行时间
# max_execution_time=120 # 秒
)
# 同时给 Agent 设置最大迭代次数
researcher = Agent(
...
max_iter=4, # 最多4次迭代
max_rpm=10 # 每分钟最多10次 LLM 调用(防止超速)
)八、选型决策矩阵
| 维度 | LangGraph | AutoGen | CrewAI |
|---|---|---|---|
| 学习曲线 | 高(需理解图结构) | 中 | 低(最易上手) |
| 流程可控性 | 极高 | 中 | 低 |
| 多智能体协作 | 支持 | 原生设计 | 原生设计 |
| 代码执行 | 需自定义 | 原生支持 | 通过 Tool |
| 生产稳定性 | 高(确定性强) | 中(对话可能发散) | 中 |
| 适合场景 | 复杂流程、需要 Human-in-loop | 代码生成、研究协作 | 快速原型、内容生成 |
我的建议:
- 刚入门 Agent 开发 → 从 CrewAI 开始,最快出效果
- 需要生产级稳定性 → 用 LangGraph,流程可控、可调试
- 做代码生成或技术研究类应用 → 考虑 AutoGen
三个框架可以混用:用 CrewAI 快速验证想法,用 LangGraph 重写生产版本。
