Solo Unicorn Club logoSolo Unicorn
2,850

LangChain vs CrewAI vs 从零搭建 — 我的经验

AI AgentLangChainCrewAI框架选型对比评测实战
LangChain vs CrewAI vs 从零搭建 — 我的经验

LangChain vs CrewAI vs 从零搭建 — 我的经验

开场

过去一年我用 LangChain 搭过 3 个项目,用 CrewAI 搭过 2 个,还从零写过一个不依赖任何框架的 Agent 系统。最终的结论可能会让你意外:框架不是越重越好,也不是完全不用框架就最好——关键在于你的项目处在什么阶段,团队有什么样的技术能力。

问题背景

2026 年的 AI Agent 框架市场,LangChain(含 LangGraph)和 CrewAI 是最活跃的两个选手。LangChain 在 PyPI 上月下载量超过 4700 万次,是最大的生态系统。CrewAI 增长最快,尤其在 multi-agent 场景。

但还有第三条路:从零搭建。直接调用 Claude 或 GPT 的 API,自己写 Agent 循环、Tool 调用、状态管理。听起来复杂,但在某些场景下反而是最高效的选择。

我把三种方式都跑过实际项目,这篇文章分享真实的对比数据和选型建议。

核心对比

LangChain + LangGraph

LangChain 是 2023 年起步的 Agent 框架,到 2026 年已经进化出了 LangGraph——一个基于有向图的 Agent 编排引擎。核心思路是:你用节点(Node)表示每个处理步骤,用边(Edge)定义步骤之间的流转关系。

from langgraph.graph import StateGraph, MessagesState, START, END
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool

# 定义工具
@tool
def search_database(query: str) -> str:
    """搜索产品数据库"""
    # 实际的数据库查询逻辑
    return f"找到 3 条关于 '{query}' 的结果"

@tool
def calculate_price(product_id: str, quantity: int) -> str:
    """计算商品总价"""
    # 实际的价格计算逻辑
    prices = {"SKU001": 99.0, "SKU002": 149.0}
    total = prices.get(product_id, 0) * quantity
    return f"总价: ¥{total}"

# 初始化模型
model = ChatAnthropic(
    model="claude-sonnet-4-5-20250514"
).bind_tools([search_database, calculate_price])

# 定义图节点
def call_model(state: MessagesState):
    response = model.invoke(state["messages"])
    return {"messages": [response]}

def call_tools(state: MessagesState):
    """执行工具调用"""
    last_message = state["messages"][-1]
    results = []
    for tool_call in last_message.tool_calls:
        if tool_call["name"] == "search_database":
            result = search_database.invoke(tool_call["args"])
        elif tool_call["name"] == "calculate_price":
            result = calculate_price.invoke(tool_call["args"])
        results.append({"role": "tool", "content": result, "tool_call_id": tool_call["id"]})
    return {"messages": results}

# 构建图
def should_continue(state: MessagesState):
    last = state["messages"][-1]
    if hasattr(last, "tool_calls") and last.tool_calls:
        return "tools"
    return END

graph = StateGraph(MessagesState)
graph.add_node("agent", call_model)
graph.add_node("tools", call_tools)
graph.add_edge(START, "agent")
graph.add_conditional_edges("agent", should_continue, {"tools": "tools", END: END})
graph.add_edge("tools", "agent")

app = graph.compile()

LangGraph 的优势:

  • 状态管理清晰——每一步的输入输出都有明确定义
  • 支持循环和条件分支——适合复杂的 Agent 逻辑
  • 内置 checkpoint 机制——可以持久化中间状态,支持断点恢复
  • 社区生态大——各种 integration 和示例代码很多

LangGraph 的问题:

  • 抽象层太多——一个简单的 tool call 需要经过 LangChain Core、LangGraph、Provider 三层封装
  • 版本迭代太快——我去年的代码今年跑不了,API breaking change 频繁
  • Debug 困难——报错信息经常指向框架内部,不容易定位问题

CrewAI

CrewAI 的核心抽象是 "角色"。你不需要思考节点和边,只需要定义谁来做什么:

from crewai import Agent, Task, Crew, Process

# 定义 Agent(按角色)
researcher = Agent(
    role="市场调研员",
    goal="收集竞品的价格、功能和用户评价数据",
    backstory="你是一个资深的市场分析师,擅长从公开信息中提取关键洞察",
    llm="anthropic/claude-sonnet-4-5-20250514",
    verbose=True
)

writer = Agent(
    role="内容写手",
    goal="基于调研数据撰写分析报告",
    backstory="你是一个技术内容专家,擅长把复杂信息写成可读性强的文章",
    llm="anthropic/claude-sonnet-4-5-20250514",
    verbose=True
)

reviewer = Agent(
    role="质量审核员",
    goal="确保报告的准确性和可读性",
    backstory="你是一个严格的编辑,关注数据准确性和逻辑一致性",
    llm="anthropic/claude-haiku-4-5-20250514",  # 审核用便宜模型
    verbose=True
)

# 定义任务
research_task = Task(
    description="调研以下竞品的最新定价和核心功能: {products}",
    expected_output="结构化的竞品分析数据(JSON 格式)",
    agent=researcher
)

writing_task = Task(
    description="基于调研数据,写一篇 2000 字的竞品分析报告",
    expected_output="Markdown 格式的分析报告",
    agent=writer,
    context=[research_task]  # 依赖调研任务的输出
)

review_task = Task(
    description="审核报告的质量,检查数据准确性和逻辑性",
    expected_output="审核意见和修改建议",
    agent=reviewer,
    context=[writing_task]
)

# 组建团队并执行
crew = Crew(
    agents=[researcher, writer, reviewer],
    tasks=[research_task, writing_task, review_task],
    process=Process.sequential,  # 顺序执行
    verbose=True
)

result = crew.kickoff(inputs={"products": "ChatGPT, Claude, Gemini"})

CrewAI 的优势:

  • 抽象直观——角色 + 任务的模型符合人的思维方式
  • 上手快——30 分钟可以跑通一个 multi-agent 流程
  • 内置 Agent 间通信——不需要手动传数据

CrewAI 的问题:

  • 底层仍然依赖 LangChain——CrewAI 建立在 LangChain 的基础上,继承了它的一些复杂性
  • 灵活性受限——复杂的条件分支和循环很难实现
  • 生产特性不足——缺少内置的错误重试、速率限制、监控

从零搭建

当你需要完全控制 Agent 的行为,或者项目逻辑简单到不需要框架的抽象时,直接写是最高效的:

import anthropic
from dataclasses import dataclass

@dataclass
class AgentConfig:
    name: str
    system_prompt: str
    model: str = "claude-sonnet-4-5-20250514"
    max_tokens: int = 4096

class SimpleAgent:
    """一个不依赖任何框架的 Agent 实现"""

    def __init__(self, config: AgentConfig):
        self.config = config
        self.client = anthropic.Anthropic()
        self.tools: dict[str, callable] = {}

    def register_tool(self, name: str, description: str, schema: dict, func: callable):
        """注册一个工具"""
        self.tools[name] = {
            "definition": {
                "name": name,
                "description": description,
                "input_schema": schema
            },
            "func": func
        }

    def run(self, user_input: str) -> str:
        """执行 Agent 循环"""
        messages = [{"role": "user", "content": user_input}]
        tool_defs = [t["definition"] for t in self.tools.values()]

        # Agent 循环:调用 LLM → 执行工具 → 再调用 LLM
        for _ in range(10):  # 最多 10 轮,防止无限循环
            response = self.client.messages.create(
                model=self.config.model,
                max_tokens=self.config.max_tokens,
                system=self.config.system_prompt,
                tools=tool_defs if tool_defs else None,
                messages=messages
            )

            # 如果模型直接回复(没有 tool call),返回结果
            if response.stop_reason == "end_turn":
                return self._extract_text(response)

            # 处理 tool call
            messages.append({"role": "assistant", "content": response.content})
            tool_results = []
            for block in response.content:
                if block.type == "tool_use":
                    result = self.tools[block.name]["func"](**block.input)
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": str(result)
                    })
            messages.append({"role": "user", "content": tool_results})

        return "达到最大循环次数,请简化问题"

    def _extract_text(self, response) -> str:
        return "".join(b.text for b in response.content if b.type == "text")


# 多 Agent 编排(极简版)
class AgentPipeline:
    """顺序执行多个 Agent"""

    def __init__(self):
        self.steps: list[tuple[SimpleAgent, str]] = []

    def add_step(self, agent: SimpleAgent, prompt_template: str):
        self.steps.append((agent, prompt_template))

    def run(self, initial_input: str) -> str:
        current_output = initial_input
        for agent, template in self.steps:
            prompt = template.format(input=current_output)
            current_output = agent.run(prompt)
        return current_output

从零搭建的优势:

  • 零依赖——不用担心框架版本更新导致代码失效
  • 完全可控——每一行代码都是你写的,debug 直接定位
  • 性能最优——没有框架的抽象开销

从零搭建的问题:

  • 基础设施要自己造——错误处理、重试、日志、监控全要自己写
  • 复杂编排时代码量大——条件分支、并行执行、状态持久化需要大量代码
  • 团队协作成本高——没有统一的抽象,每个人可能写出不同风格的 Agent 代码

实战经验

三个项目的真实对比

维度 项目 A (LangGraph) 项目 B (CrewAI) 项目 C (从零)
项目类型 客服 Agent 内容生产 数据分析
开发时间 3 周 1 周 2 周
代码行数 2,400 行 800 行 1,600 行
运行延迟 4.2s/请求 12.5s/任务 3.1s/请求
框架开销 ~200ms ~800ms 0ms
维护难度 中(版本升级频繁) 中(自建组件多)
可扩展性 高(但要自己写)

注意运行延迟的数据:CrewAI 在执行 3 个 Agent 顺序任务时耗时 12.5 秒,其中约 800ms 是框架本身的 overhead(Agent 角色初始化、内部通信协议)。LangGraph 的 overhead 约 200ms,从零搭建的 overhead 为 0。

选型决策框架

经过这三个项目,我总结了一个选型决策树:

问 1:你的 Agent 逻辑有多复杂?

  • 简单线性流程(A → B → C)→ CrewAI 或从零搭建
  • 有条件分支和循环 → LangGraph
  • 极简单(一个 Agent + 几个 Tool)→ 从零搭建

问 2:你的团队技术水平?

  • 产品/运营团队 → CrewAI(抽象最直观)
  • 工程团队 → LangGraph 或从零搭建
  • 一个人干 → 看项目复杂度决定

问 3:你对生产稳定性的要求?

  • 高(面向客户的产品)→ LangGraph(成熟度最高)或从零搭建(完全可控)
  • 中(内部工具)→ 三种都行
  • 低(原型验证)→ CrewAI(最快)

问 4:你需要多少 integration?

  • 大量第三方集成 → LangChain(生态最大)
  • 少数几个 API → 从零搭建(自己写 tool 更直接)

我的真实选择

在我自己的项目中:

  • 内容生产 Agent 团队(就是你正在读的这个项目)→ 从零搭建。因为流程固定,我需要精确控制每个 Agent 的 prompt 和输出格式。
  • 客户 Demo:CrewAI。因为可以快速搭建一个看起来很酷的 multi-agent 演示。
  • 企业客户的生产系统:LangGraph。因为客户需要持久化状态、断点恢复、审计日志,这些 LangGraph 内置支持。

总结

三条核心 takeaway:

  1. 没有"最好"的框架,只有最合适的框架——选型取决于项目复杂度、团队能力和生产要求,不取决于 GitHub stars。

  2. 框架的价值在于你用到了多少——如果你只用了 LangChain 的 ChatModel 和 Tool,那你其实不需要 LangChain。框架的价值在于它的高级特性(状态管理、checkpoint、可视化),如果你用不到,它就是纯负担。

  3. 从简单开始,必要时才引入框架——我的建议是先用原生 API 把 Agent 逻辑跑通,确认需要框架提供的某个特定能力后再引入。不要因为 "大家都在用" 就选了一个框架。

你现在在用哪个框架搭 Agent?踩过什么坑?欢迎分享你的经验。