ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI Agent开发速查清单:LangGraph、AutoGen、CrewAI与MCP核心要点

AI Agent开发速查清单:LangGraph、AutoGen、CrewAI与MCP核心要点

1. 这份速查清单到底解决什么问题

做AI应用开发的人大概都有过这种体验:项目里同时用着LangGraph编排流程、AutoGen跑多智能体对话、CrewAI做角色分工,还要接MCP协议打通外部工具,结果每隔两周回头看自己的代码,就得重新翻文档确认某个API到底叫什么、参数怎么传。更麻烦的是,这些框架的迭代速度极快,上个月还能跑的写法这个月可能就废弃了。我自己的做法是维护一份"活页速查表",把每个框架的核心概念、最小可运行代码、常见坑点都记下来,用的时候直接翻,不用每次都去啃官方文档。

这份速查清单就是基于这个思路整理的。它覆盖了当前主流的几个AI Agent开发框架——LangGraph、AutoGen、CrewAI,以及正在快速普及的MCP协议,同时把OpenAI API的接入要点、工具链配置、资源获取渠道都串在一起。适合两类人看:一类是刚接触Agent开发、面对一堆框架不知道从哪下手的新手;另一类是用过其中一两个框架、但需要横向对比或者补齐知识盲区的开发者。我不会写成官方文档的复读机,而是按"实际项目里怎么用、哪里容易翻车"的角度来组织内容。

先说清楚一个前提:这些框架没有绝对的优劣,选型取决于你的场景。LangGraph适合需要精细控制流程和状态的项目,AutoGen适合快速搭建多Agent对话系统,CrewAI在角色分工明确的协作任务上更顺手,MCP则是解决"Agent怎么调用外部工具"这个通用问题的协议层方案。下面逐个拆。

2. LangGraph:状态图编排的核心逻辑与实操

2.1 为什么LangGraph用"图"而不是"链"

LangChain早期的Chain是线性的,A调用B、B调用C,流程固定。但真实Agent场景里经常需要循环、条件分支、人工介入后回到某一步,线性结构表达起来很别扭。LangGraph把流程建模成有向图,节点是处理函数,边是流转条件,状态在节点间传递和累积。这个设计的好处是:你可以随时在图上加一个"检查点",让流程暂停等人工确认,确认完再从断点继续。我在做一个客服工单分类Agent时,就靠这个机制实现了"AI初判→人工复核→AI执行"的混合流程,比硬编码状态机清爽得多。

核心概念就三个:State(贯穿全图的数据结构,通常是个TypedDict)、Node(接收State返回State更新的函数)、Edge(决定下一个走哪个节点)。条件边用add_conditional_edges注册,配合一个返回节点名的路由函数。

2.2 最小可运行示例与关键参数

from langgraph.graph import StateGraph, END from typing import TypedDict class AgentState(TypedDict): messages: list next_step: str def classify(state: AgentState): # 实际项目里这里调LLM做意图识别 return {"next_step": "search"} def search(state: AgentState): return {"messages": state["messages"] + ["搜索结果"]} def route(state: AgentState): return state["next_step"] graph = StateGraph(AgentState) graph.add_node("classify", classify) graph.add_node("search", search) graph.set_entry_point("classify") graph.add_conditional_edges("classify", route, {"search": "search", "end": END}) graph.add_edge("search", END) app = graph.compile() result = app.invoke({"messages": [], "next_step": ""})

这段代码跑通只需要装langgraph一个包。注意compile()之后得到的是可调用对象,invoke传初始State,返回最终State。如果要支持中断恢复,compile(checkpointer=MemorySaver())加上checkpointer,然后调用时传config={"configurable": {"thread_id": "xxx"}}。

2.3 工具调用在LangGraph里的正确姿势

LangGraph本身不绑定工具调用方式,但和LangChain的Tool体系配合最顺。定义工具用@tool装饰器,然后有两种接法:一种是把工具绑到LLM上让模型自己决定调不调(llm.bind_tools(tools)),另一种是在节点里手动判断该调哪个工具。前者适合开放式任务,后者适合流程可控的场景。我踩过的坑是:用bind_tools时如果模型返回的tool_call参数格式不对,节点里直接执行会报错,稳妥做法是加一层参数校验,校验不过就回退到让模型重新生成。

还有一个容易忽略的点:LangGraph的State如果包含不可序列化的对象(比如数据库连接),用checkpointer持久化时会失败。解决办法是把连接放在节点函数内部创建,State里只存必要的数据。

3. AutoGen与CrewAI:多Agent协作的两种思路

3.1 AutoGen的对话驱动模型

AutoGen的核心抽象是ConversableAgent,一切皆对话。你定义几个Agent,给它们不同的system message和角色,然后让它们互相发消息。最典型的是AssistantAgent(负责生成方案)加UserProxyAgent(负责执行代码或调用工具),两者循环对话直到任务完成。这个模式在代码生成场景特别顺手,因为UserProxy可以直接执行Assistant写的代码并把结果反馈回去。

from autogen import AssistantAgent, UserProxyAgent assistant = AssistantAgent("assistant", llm_config={"model": "gpt-4"}) user_proxy = UserProxyAgent("user_proxy", code_execution_config={"work_dir": "coding"}) user_proxy.initiate_chat(assistant, message="写一个快速排序并测试")

AutoGen的坑主要在code_execution_config上。默认它会在本地执行代码,生产环境必须换成Docker容器执行,否则模型生成的代码可能删你的文件。配置use_docker=True并指定镜像,虽然启动慢一点,但安全边界清晰。

3.2 CrewAI的角色分工范式

CrewAI把多Agent协作抽象成"团队":每个Agent有role、goal、backstory,Task有description和expected_output,Crew把Agent和Task绑在一起按顺序或层级执行。它的优势是语义清晰,写出来的代码像在描述一个组织架构,非技术人员也能看懂。比如做一个市场调研任务,你可以定义"研究员"负责搜集信息、"分析师"负责提炼洞察、"写手"负责出报告,三个Task串起来。

from crewai import Agent, Task, Crew researcher = Agent(role="研究员", goal="搜集竞品信息", backstory="资深市场分析师") task = Task(description="调研三款竞品的功能差异", agent=researcher, expected_output="对比表格") crew = Crew(agents=[researcher], tasks=[task]) result = crew.kickoff()

CrewAI的expected_output字段很关键,它直接影响Agent的输出质量。我试过写"一份报告"和写"包含五个维度的对比表格,每维度至少三条数据",后者产出质量明显更高。另外CrewAI默认用顺序执行,如果要并行得用Process.hierarchical并指定manager。

3.3 三个框架怎么选

维度LangGraphAutoGenCrewAI
核心模型状态图对话循环角色团队
流程控制精细中等粗粒度
上手难度中低低
适合场景复杂分支流程代码生成、对话角色分工任务
状态持久化原生支持需自行实现有限支持

我的经验是:如果流程里有大量条件判断和循环,选LangGraph;如果核心是让几个Agent聊出结果,选AutoGen;如果任务能清晰拆成几个角色的职责,选CrewAI。三者也能混用,比如用LangGraph做外层流程控制,某个节点内部起一个CrewAI团队干活。

4. MCP协议:Agent调用外部工具的统一接口

4.1 MCP到底解决什么问题

在没有MCP之前,每个Agent框架调工具的方式都不一样:LangChain有Tool、OpenAI有function calling、各家IDE插件有自己的扩展机制。结果是同一个数据库查询工具,你要为每个框架写一遍适配。MCP(Model Context Protocol)的思路是定义一套标准协议,工具提供方实现一次MCP Server,任何支持MCP的客户端都能调用。这就像USB-C统一了充电接口,之前每个品牌一个口,现在一根线通吃。

MCP的核心概念:Server(暴露工具、资源、提示词)、Client(Agent侧,连接Server并调用)、Transport(通信方式,常见的是stdio和HTTP+SSE)。一个MCP Server可以暴露多个tool,每个tool有name、description、inputSchema。

4.2 写一个最小MCP Server

from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent app = Server("demo-server") @app.list_tools() async def list_tools(): return [Tool(name="query_db", description="查询数据库", inputSchema={"type": "object", "properties": {"sql": {"type": "string"}}})] @app.call_tool() async def call_tool(name, arguments): if name == "query_db": # 实际执行查询 return [TextContent(type="text", text="查询结果")] async def main(): async with stdio_server() as (read, write): await app.run(read, write, app.create_initialization_options())

这个Server通过stdio通信,客户端启动它作为子进程,通过标准输入输出交换JSON-RPC消息。如果要走网络,换成SSE transport。

4.3 客户端接入的常见问题

把MCP接入Codex、通义灵码这类工具时,最容易卡在授权和路径上。stdio类型的Server需要在客户端配置里写清楚启动命令和参数,比如{"command": "python", "args": ["server.py"]},路径要用绝对路径,相对路径在不同工作目录下会找不到。HTTP类型的Server要确认端口没被占用,以及客户端是否支持该transport。

热词里提到的"codex无法找到mcp"这类问题,九成是配置文件路径或格式问题。建议先用MCP官方的inspector工具单独测试Server能不能正常列出工具,确认Server没问题再排查客户端配置。另外注意:不同客户端对MCP协议版本的支持程度不一样,Server端尽量用稳定版本的SDK。

5. OpenAI API接入与工具链配置要点

5.1 API Key获取与环境变量管理

OpenAI的API Key在平台后台的API Keys页面创建,创建后只显示一次,务必立即保存。管理上绝对不要硬编码在代码里,用环境变量:export OPENAI_API_KEY="sk-...",代码里用os.environ["OPENAI_API_KEY"]读取。团队协作时用.env文件配合python-dotenv,但.env要加进.gitignore。我见过有人把key提交到公开仓库,几小时内就被刷爆额度,这个教训很贵。

5.2 模型选择与成本控制

不同任务用不同模型是基本操作。复杂推理用能力强的模型,简单分类、格式化输出用便宜的小模型。设置max_tokens限制输出长度,设置temperature控制随机性(做数据提取时设0,做创意生成时设0.7以上)。批量任务用Batch API能省一半成本,代价是延迟高。另外记得在代码里加token计数和费用日志,不然月底账单会让你措手不及。

5.3 依赖安装的坑

热词里出现的"missing optional dependency @openai/codex-win32-x64"这类报错,本质是平台相关的可选依赖没装上。解决办法通常是删掉node_modules和lock文件重新npm install,或者显式安装对应平台的包。Python侧类似的问题常见于某些包对特定Python版本或系统库有要求,用虚拟环境隔离能减少这类冲突。我的习惯是每个项目独立venv,requirements.txt里锁定版本号,避免"昨天还能跑今天就不行"。

6. 资源清单与日常维护习惯

工具和框架的文档更新很快,与其收藏一堆可能过期的链接,不如建立自己的信息获取渠道。官方文档永远是第一手资料,GitHub的release notes能提前知道哪些API要变,issue区能看到别人踩的坑。我每周花半小时扫一遍常用框架的更新日志,把影响自己项目的变更记到速查表里。

速查表本身建议用Markdown维护,按框架分节,每节包含:核心概念一句话、最小示例、常见错误、版本注意事项。放在项目仓库里,团队共享。这样新人入职不用从零摸索,老手也不用凭记忆猜API。工具是死的,维护习惯是活的,这份清单的价值不在于它现在写了什么,而在于你能持续往里补充自己踩过的坑。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进