CrewAI 完全学习手册

CrewAI 完全学习手册

版本 : 2026.09 · 适用 CrewAI 1.0+

目标读者 : 有 LLM 应用基础,想系统掌握多 Agent 编排的中级开发者

文档定位: 完整学习手册(原理 + API + 实战 + 源码 + 生产化)


目录

  • [第一篇 · 入门与定位](#第一篇 · 入门与定位)
    • [1.1 什么是 CrewAI](#1.1 什么是 CrewAI)
    • [1.2 为什么需要多 Agent 框架](#1.2 为什么需要多 Agent 框架)
    • [1.3 CrewAI vs AutoGen vs LangGraph](#1.3 CrewAI vs AutoGen vs LangGraph)
  • [第二篇 · 核心概念精讲](#第二篇 · 核心概念精讲)
    • [2.1 Agent(智能体)](#2.1 Agent(智能体))
    • [2.2 Task(任务)](#2.2 Task(任务))
    • [2.3 Crew(团队)](#2.3 Crew(团队))
    • [2.4 Process(执行流程)](#2.4 Process(执行流程))
    • [2.5 Tools(工具系统)](#2.5 Tools(工具系统))
    • [2.6 Memory(记忆机制)](#2.6 Memory(记忆机制))
  • [第三篇 · 快速上手](#第三篇 · 快速上手)
    • [3.1 环境搭建](#3.1 环境搭建)
    • [3.2 第一个示例:研究报告生成](#3.2 第一个示例:研究报告生成)
  • [第四篇 · 进阶特性](#第四篇 · 进阶特性)
    • [4.1 层级流程与委派机制](#4.1 层级流程与委派机制)
    • [4.2 自定义工具开发](#4.2 自定义工具开发)
    • [4.3 记忆系统深度使用](#4.3 记忆系统深度使用)
    • [4.4 Flow:状态化编排](#4.4 Flow:状态化编排)
  • [第五篇 · 实战案例](#第五篇 · 实战案例)
    • 案例一:竞品分析报告(顺序流程)
    • [案例二:自动代码评审(层级流程 + 自定义工具)](#案例二:自动代码评审(层级流程 + 自定义工具))
    • [案例三:智能客服系统(RAG + 长期记忆)](#案例三:智能客服系统(RAG + 长期记忆))
  • [第六篇 · 源码解析](#第六篇 · 源码解析)
    • [6.1 Crew 类核心调度逻辑](#6.1 Crew 类核心调度逻辑)
    • [6.2 Agent 的 ReAct 循环](#6.2 Agent 的 ReAct 循环)
    • [6.3 Hierarchical Manager 委派实现](#6.3 Hierarchical Manager 委派实现)
  • [第七篇 · 生产化](#第七篇 · 生产化)
    • [7.1 可观测性](#7.1 可观测性)
    • [7.2 评估体系](#7.2 评估体系)
    • [7.3 成本与性能优化](#7.3 成本与性能优化)
    • [7.4 错误处理与重试](#7.4 错误处理与重试)
  • 附录
    • [A. 常见问题 FAQ](#A. 常见问题 FAQ)
    • [B. 推荐学习资源](#B. 推荐学习资源)

第一篇 · 入门与定位

1.1 什么是 CrewAI

CrewAI 是一个基于角色的多智能体协作框架,把"团队(Crew)"的隐喻引入 LLM 应用开发。每个 Agent 是有专长的"员工",Task 是"工单",Crew 是"项目经理",Process 是"工作制度"。

核心理念:让多个各司其职的 Agent 通过协作完成任务,而不是让一个"全能 Agent"包打天下。

适用场景:

场景 典型分解
报告生成 研究员 → 分析师 → 撰写员 → 审核员
自动化测试 用例设计 → 脚本生成 → 执行 → 报告
客服工单 分类 → 知识库检索 → 答复 → 复核
竞品调研 信息收集 → 特征对比 → SWOT → 战略建议

1.2 为什么需要多 Agent 框架

单一 Agent 处理复杂任务时会遇到三个核心问题:

  1. 上下文过载:所有工具、规则、历史都塞进同一个 Prompt,超出模型容量
  2. 角色冲突:要求"既是工程师又是产品经理又是 UX"会让 LLM 推理混乱
  3. 难以审计:谁做了什么、用了什么工具、为什么这么决策,无法清晰追溯

多 Agent 框架通过职责分离 + 显式协作解决这些问题。

1.3 CrewAI vs AutoGen vs LangGraph

维度 CrewAI AutoGen LangGraph
思维模型 角色团队 对话协商 状态图
核心抽象 Agent + Task + Crew ConversableAgent + GroupChat StateGraph 节点/边
协作模式 顺序/层级/委派 群聊动态编排 节点跳转、分支、循环
状态管理 隐式(上下文传递) 会话历史缓存 显式 Checkpoint
上手难度 最低 中等 最陡峭
生产成熟度 中(Enterprise 版可用) 中(微软背书) 高
Token 效率 良好 较差 最佳
适用场景 快速原型、角色分工明确 代码生成、研究探索 复杂流程、生产部署

经验法则:

  • 2 小时内跑通原型 → CrewAI
  • 需要循环重试、暂停恢复、人机协同 → LangGraph
  • 需要 Agent 之间"辩论碰撞" → AutoGen
  • 实际项目常混用:LangGraph 监督 + CrewAI 子团队

第二篇 · 核心概念精讲

2.1 Agent(智能体)

Agent 是执行单元,每个 Agent 都有自己的"身份卡"。

核心属性
python 复制代码
from crewai import Agent

researcher = Agent(
    role="高级行业研究员",                          # 角色定位
    goal="挖掘 2026 年 AI Agent 行业的关键趋势",      # 个人目标
    backstory="""                                  # 背景故事
        你在硅谷有 10 年技术研究经验,
        擅长从海量信息中提炼结构化洞察,
        偏好用数据说话,避免空泛预测。
    """,
    tools=[search_tool, scrape_tool],              # 可调用工具
    llm="gpt-4o",                                  # 底层模型
    memory=True,                                   # 启用记忆
    allow_delegation=True,                         # 允许委派
    max_iter=15,                          # 最大推理轮次(防死循环)
    verbose=True                                   # 打印思考过程
)
关键设计原则

1. Backstory 决定行为风格

Backstory 不是装饰,而是 prompt 的一部分,会被拼到 system message 中。模糊的 backstory 会得到模糊的行为。

python 复制代码
# ❌ 模糊
backstory="你是研究员"

# ✅ 具体
backstory="""你在 Gartner 工作 8 年,
专注于 AI 与企业级软件赛道,
习惯用波特五力模型分析行业竞争结构,
输出必须包含至少 3 个可验证的引用源。"""

2. allow_delegation 控制协作能力

取值 行为
False(默认) Agent 只能自己完成,无法委派
True Agent 可把任务委派给 crew 中其他 Agent(会产生额外 LLM 调用)

3. max_iter 防止死循环

Agent 的 ReAct 循环默认上限 15 轮。遇到顽固任务会终止并返回当前最佳结果。

2.2 Task(任务)

Task 是工作的最小单元,描述"做什么、产出什么"。

核心属性
python 复制代码
from crewai import Task

research_task = Task(
    description="""深入研究 2026 年 AI Agent 行业趋势。
    重点关注:1) 多 Agent 框架之争;2) 企业落地情况;3) 成本结构变化。
    必须引用至少 3 个权威信息源。""",
    expected_output="""一份 Markdown 报告,包含:
    - 5 个核心趋势,每个趋势有数据
    - 关键玩家对比表
    - 未来 12 个月预测""",
    agent=researcher_agent,                        # 分配 Agent
    tools=[search_tool],                           # 该任务专用工具
    context=[previous_task],            # 依赖的上游任务输出
    output_file="report.md",                       # 保存到文件
    async_execution=False,                         # 是否异步执行
    human_input=False                              # 是否需要人类确认
)
上下文传递机制(Context 是关键)

Task 的 context 参数是 CrewAI 最强大的特性之一:

python 复制代码
# Task B 依赖 Task A 的输出
task_b = Task(
    description="基于研究结果撰写最终文章",
    expected_output="一篇 1500 字的深度文章",
    agent=writer_agent,
    context=[task_a]  # task_a 的输出会自动注入到 task_b 的 prompt
)

底层机制 :执行 task_b 时,Crew 会把 task_a 的 raw_output 拼到 task_b 的 prompt 里,Agent 就能"看到"上一步的产出。

2.3 Crew(团队)

Crew 是编排容器,把 Agents 和 Tasks 装配成可执行的工作流。

python 复制代码
from crewai import Crew, Process

crew = Crew(
    agents=[researcher, writer, reviewer],
    tasks=[research_task, write_task, review_task],
    process=Process.sequential,        # 执行流程
    memory=True,                       # 启用跨任务记忆
    cache=True,                        # 启用工具结果缓存
    verbose=2,                         # 日志级别 0/1/2
    max_rpm=10,                        # 每分钟最大请求数(限流)
    share_crew=False                   # 是否匿名分享到 CrewAI 平台
)

# 触发执行
result = crew.kickoff(inputs={"topic": "AI Agent"})
print(result.raw)        # 最终输出
print(result.tasks_output)  # 每个 Task 的输出
kickoff 的三种用法
python 复制代码
# 1. 标准用法:传入初始变量
result = crew.kickoff(inputs={"topic": "AI", "year": 2026})

# 2. 异步用法(适合长任务)
result = await crew.kickoff_async(inputs={...})

# 3. 单 Task 触发(调试用)
result = crew.kickoff_for_each([inputs1, inputs2, inputs3])

2.4 Process(执行流程)

Process 决定任务如何流转,这是 CrewAI 的"灵魂"。

Sequential(顺序流程)

最常用,任务按顺序执行,前一个输出作为后一个的上下文。

复制代码
Task1 → Task2 → Task3 → 输出
Hierarchical(层级流程)

自动派生一个 Manager Agent,动态委派任务给 Worker Agents。Manager 会根据 worker 的能力匹配任务。

复制代码
       Manager(管理者)
       /     |     \
   Worker1 Worker2 Worker3

适用场景:任务依赖关系不明确、需要动态决策的工作流。

代价:Manager 的委派决策会产生额外 LLM 调用,Token 消耗约为 Sequential 的 2~3 倍。

Process 选择决策树
复制代码
任务依赖关系是否明确?
├── 是 → Sequential
└── 否
    ├── 任务数量 > 5 且角色清晰 → Hierarchical
    └── 任务数量少但需要动态决策 → Hierarchical

2.5 Tools(工具系统)

Tools 扩展 Agent 的能力边界,让 Agent 能与外部世界交互。

内置工具

CrewAI 提供了大量开箱即用的工具(来自 crewai_tools 包):

python 复制代码
from crewai_tools import (
    SerperDevTool,           # Google 搜索
    ScrapeWebsiteTool,       # 网页抓取
    PDFSearchTool,           # PDF 检索
    GithubSearchTool,        # GitHub 搜索
    CodeDocsSearchTool,      # 代码文档搜索
    WebsiteSearchTool,       # 网站内搜索
    YoutubeVideoSearchTool,  # YouTube 搜索
)
自定义工具(详见 4.2 节)

2.6 Memory(记忆机制)

Memory 让 Agent 拥有"跨任务、跨会话"的记忆能力。

三种记忆类型
类型 作用范围 存储 适用场景
Short-term 单次 Crew 执行内 上下文窗口 当前会话的任务协作
Long-term 跨会话 SQLite/外部向量库 用户偏好、历史交互
Entity 跨会话 向量库 记住特定实体(如客户档案)
启用方式
python 复制代码
crew = Crew(
    agents=[...],
    tasks=[...],
    memory=True,  # 一键启用三种记忆
)

注意:启用 memory 会引入额外的存储依赖(默认 SQLite + 向量库)。生产环境建议用外部存储(Redis + Qdrant)。


第三篇 · 快速上手

3.1 环境搭建

安装
bash 复制代码
# 核心库
pip install crewai

# 工具库
pip install 'crewai[tools]'

# 如需 Flow(第四篇会讲)
pip install crewai-flow
配置 LLM API Key
bash 复制代码
# .env 文件
OPENAI_API_KEY=sk-...
SERPER_API_KEY=...  # 如使用搜索工具
验证安装
python 复制代码
import crewai
print(crewai.__version__)  # 应输出 1.x.x

3.2 第一个示例:研究报告生成

目标:用研究员 + 撰写员两个 Agent,输出一篇 AI Agent 趋势报告。

完整代码:

python 复制代码
# examples/01_research_report.py
"""
示例 1: AI 趋势研究报告生成
- Sequential 流程
- 2 个 Agent
- 2 个 Task
- 启用搜索和抓取工具
"""
from crewai import Agent, Task, Crew, Process
from crewai_tools import SerperDevTool, ScrapeWebsiteTool
from dotenv import load_dotenv

load_dotenv()

# === 1. 定义工具 ===
search_tool = SerperDevTool()
scrape_tool = ScrapeWebsiteTool()

# === 2. 定义 Agent ===
researcher = Agent(
    role="高级行业研究员",
    goal="挖掘 2026 年 AI Agent 行业的关键趋势和数据",
    backstory="""你曾在 Gartner 工作 8 年,专注于 AI 与企业级软件赛道。
    习惯用波特五力模型分析行业竞争结构,
    偏好用数据说话,所有结论必须可验证。""",
    tools=[search_tool, scrape_tool],
    allow_delegation=False,
    verbose=True
)

writer = Agent(
    role="技术内容撰写员",
    goal="把研究结果转化为通俗易懂的深度文章",
    backstory="""你是《连线》杂志前主编,擅长把复杂技术讲清楚。
    文字生动有画面感,避免学术化表达,
    善于用类比帮助读者理解抽象概念。""",
    allow_delegation=False,
    verbose=True
)

# === 3. 定义 Task ===
research_task = Task(
    description="""研究 {topic} 领域的最新发展。
    重点关注:
    1. 主要玩家的最新动态
    2. 技术架构演进
    3. 2026 年的关键数据和预测
    4. 至少 3 个权威信息源的引用""",
    expected_output="""一份结构化研究报告,包含:
    - 5 个核心发现
    - 关键玩家对比表
    - 数据来源引用列表""",
    agent=researcher,
    tools=[search_tool, scrape_tool]
)

write_task = Task(
    description="""基于研究报告,撰写一篇 1500 字的深度文章。
    要求:
    - 面向技术从业者
    - 结构清晰,有小标题
    - 关键数据要保留
    - 结尾给出对未来 12 个月的预测""",
    expected_output="一篇 1500 字左右的 Markdown 文章",
    agent=writer,
    context=[research_task],  # 关键:依赖研究结果
    output_file="output/ai_trends_article.md"
)

# === 4. 组装 Crew 并执行 ===
crew = Crew(
    agents=[researcher, writer],
    tasks=[research_task, write_task],
    process=Process.sequential,
    verbose=2
)

# === 5. 启动 ===
if __name__ == "__main__":
    result = crew.kickoff(inputs={"topic": "AI Agent 行业"})
    print("\n=== 最终输出 ===\n")
    print(result.raw)

运行:

bash 复制代码
python examples/01_research_report.py

预期输出 :在 output/ai_trends_article.md 中生成一篇结构化的深度文章。


第四篇 · 进阶特性

4.1 层级流程与委派机制

什么是委派(Delegation)

Agent A 收到一个超出自身能力的任务时,可以把任务委派 给更适合的 Agent B。这是通过 Agent 的 allow_delegation=True + LLM 自主决策实现的。

层级流程示例
python 复制代码
from crewai import Agent, Task, Crew, Process

# Worker Agents
developer = Agent(
    role="Python 开发者",
    goal="写出可运行的代码",
    backstory="5 年 Python 开发经验,擅长 FastAPI",
    allow_delegation=False
)

tester = Agent(
    role="QA 工程师",
    goal="发现代码中的 bug",
    backstory="3 年自动化测试经验",
    allow_delegation=False
)

reviewer = Agent(
    role="技术审查员",
    goal="评估代码质量与可维护性",
    backstory="资深架构师,关注 SOLID 原则",
    allow_delegation=False
)

# Manager Agent(自动由 Hierarchical 派生)
# 不需要手动创建,Crew 会基于 worker 自动生成

# Tasks
code_task = Task(
    description="实现一个用户注册 API",
    expected_output="可运行的 FastAPI 代码",
    agent=developer
)

test_task = Task(
    description="为 API 编写单元测试",
    expected_output="pytest 测试用例",
    agent=tester
)

review_task = Task(
    description="审查代码质量",
    expected_output="审查报告",
    agent=reviewer
)

crew = Crew(
    agents=[developer, tester, reviewer],
    tasks=[code_task, test_task, review_task],
    process=Process.hierarchical,  # 关键:层级流程
    manager_llm="gpt-4o",          # 指定 Manager 的模型
    verbose=True
)

result = crew.kickoff()

执行流程:

  1. Manager 接收所有 Task 和 Agent 列表
  2. Manager 用 LLM 决策"任务 X 应该分给哪个 Worker"
  3. Worker 执行后,Manager 检查结果,决定下一步

4.2 自定义工具开发

当内置工具不够用时,可以开发自定义工具。

方式一:继承 BaseTool
python 复制代码
from crewai.tools import BaseTool
from pydantic import Field
import requests

class WeatherQueryTool(BaseTool):
    name: str = "天气查询工具"
    description: str = "查询指定城市的当前天气,返回温度、湿度、天气状况"

    api_key: str = Field(..., description="OpenWeatherMap API Key")

    def _run(self, city: str) -> str:
        """实现工具逻辑"""
        url = f"https://api.openweathermap.org/data/2.5/weather"
        params = {
            "q": city,
            "appid": self.api_key,
            "units": "metric",
            "lang": "zh_cn"
        }
        response = requests.get(url, params=params, timeout=10)
        data = response.json()

        return f"{city} 当前天气:{data['weather'][0]['description']}," \
               f"温度 {data['main']['temp']}°C,湿度 {data['main']['humidity']}%"

# 使用
weather_tool = WeatherQueryTool(api_key="your_key")

agent = Agent(
    role="旅行规划师",
    goal="为用户规划完美的旅行行程",
    tools=[weather_tool],
    ...
)
方式二:用 @tool 装饰器(更轻量)
python 复制代码
from crewai.tools import tool

@tool("计算器")
def calculator(expression: str) -> str:
    """计算数学表达式的值,例如:(2+3)*4"""
    try:
        return str(eval(expression))
    except Exception as e:
        return f"计算错误: {str(e)}"

# 直接作为工具传入
agent = Agent(tools=[calculator], ...)
工具设计最佳实践
  1. 原子化:一个工具只做一件事
  2. 强类型参数:用 Pydantic Field 描述参数约束
  3. 清晰的 description:Agent 靠 description 决定何时调用,描述要包含"何时用 + 怎么用 + 返回什么"
  4. 错误处理:工具失败返回明确错误信息,不要抛异常
python 复制代码
# ❌ 反例
@tool("搜索")
def search(query):
    return requests.get(f"https://api.com?q={query}").text

# ✅ 正例
@tool("Google 搜索")
def google_search(query: str, num_results: int = 5) -> str:
    """
    使用 Google 搜索查询信息,返回前 N 条结果的标题和摘要。
    适用于需要获取最新信息的场景。

    参数:
        query: 搜索关键词
        num_results: 返回结果数量,默认 5

    返回:
        格式化的搜索结果列表
    """
    try:
        # ... 实现
        return formatted_results
    except Exception as e:
        return f"搜索失败:{str(e)}"

4.3 记忆系统深度使用

自定义记忆存储
python 复制代码
from crewai import Crew
from crewai.memory import LongTermMemory

# 使用外部向量库(生产推荐)
import chromadb

custom_storage = chromadb.PersistentClient(path="./chroma_db")

crew = Crew(
    agents=[...],
    tasks=[...],
    memory=True,
    long_term_memory=LongTermMemory(storage=custom_storage),
)
查询记忆
python 复制代码
from crewai.memory import LongTermMemory

ltm = LongTermMemory()

# 查询某个 Agent 的历史记忆
relevant_memories = ltm.search(
    query="用户偏好",
    agent_id="researcher",
    limit=5
)

4.4 Flow:状态化编排

Flow 是 CrewAI 1.0 引入的新特性,用于构建有状态、可持久化的多步骤工作流。

python 复制代码
from crewai.flow.flow import Flow, listen, start, persist
from pydantic import BaseModel

class ReportState(BaseModel):
    topic: str = ""
    research_data: str = ""
    final_report: str = ""

class ReportFlow(Flow[ReportState]):

    @start()
    def get_topic(self):
        # 第一个步骤:收集主题
        self.state.topic = "AI Agent 行业"

    @listen(get_topic)
    def do_research(self):
        # 依赖上一步的状态
        crew = research_crew
        result = crew.kickoff(inputs={"topic": self.state.topic})
        self.state.research_data = result.raw

    @listen(do_research)
    def write_report(self):
        # 基于研究结果撰写
        crew = write_crew
        result = crew.kickoff(
            inputs={"research": self.state.research_data}
        )
        self.state.final_report = result.raw

# 执行
flow = ReportFlow()
flow.kickoff()

Flow vs Crew 何时用哪个:

场景 用 Crew 用 Flow
一次性多 Agent 协作 ✅
多步骤、跨会话、需要持久化状态 ✅
需要条件分支、循环 ✅
与外部系统集成(Webhooks、DB) ✅

第五篇 · 实战案例

案例一:竞品分析报告(顺序流程)

业务场景:为一家 SaaS 公司自动生成竞品分析报告,输入竞品列表,输出 SWOT 分析。

完整代码:

python 复制代码
# examples/02_competitor_analysis.py
"""
案例 1: 竞品分析报告生成
业务价值:替代人工 2 天的调研工作,2 小时内输出结构化报告
"""
from crewai import Agent, Task, Crew, Process
from crewai_tools import SerperDevTool, ScrapeWebsiteTool
from pydantic import BaseModel
from typing import List
import json

# === 数据模型 ===
class CompetitorInfo(BaseModel):
    name: str
    positioning: str
    pricing: str
    strengths: List[str]
    weaknesses: List[str]

# === 工具 ===
search = SerperDevTool()
scrape = ScrapeWebsiteTool()

# === Agents ===
market_researcher = Agent(
    role="市场调研员",
    goal="收集竞品的公开信息,形成结构化数据",
    backstory="""你擅长从官网、新闻、用户评论中提炼关键信息。
    关注:产品定位、定价、用户规模、核心功能。
    永远以事实为依据,不做主观推测。""",
    tools=[search, scrape],
    verbose=True
)

swot_analyst = Agent(
    role="战略分析师",
    goal="基于市场数据输出 SWOT 分析",
    backstory="""你毕业于沃顿商学院,专长波特竞争战略。
    擅长从产品功能、定价、用户口碑推导竞争优劣势。
    输出必须包含可执行的战略建议。""",
    verbose=True
)

report_writer = Agent(
    role="报告撰写员",
    goal="把分析结果转化为决策者可读的最终报告",
    backstory="""你为麦肯锡写过 100+ 战略报告。
    风格:结论先行、数据支撑、图表化表达。
    永远把'所以呢(So What)'放在每段结尾。""",
    verbose=True
)

# === Tasks ===
research_task = Task(
    description="""调研以下竞品:{competitors}
    每个竞品收集:
    1. 官方定位和 Slogan
    2. 定价模式(免费/订阅/按量)
    3. 3 个核心功能
    4. 用户规模(如有公开数据)
    5. 主要客户类型""",
    expected_output="""JSON 格式的竞品信息:
    [
      {
        "name": "...",
        "positioning": "...",
        "pricing": "...",
        "core_features": [...],
        "user_scale": "...",
        "customer_type": "..."
      }
    ]""",
    agent=market_researcher,
    output_pydantic=List[CompetitorInfo]  # 强制结构化输出
)

swot_task = Task(
    description="""基于竞品调研结果,做 SWOT 对比分析。
    对每个竞品,输出:
    - Strengths(至少 3 条)
    - Weaknesses(至少 3 条)
    - Opportunities(市场机会)
    - Threats(对我们的威胁)""",
    expected_output="""Markdown 格式的 SWOT 矩阵表格""",
    agent=swot_analyst,
    context=[research_task]
)

report_task = Task(
    description="""把 SWOT 分析整合为最终报告。
    包含:
    1. 执行摘要(200 字内)
    2. 竞品全景图
    3. SWOT 矩阵
    4. 3 条战略建议
    5. 风险提示""",
    expected_output="一份 2000 字内的决策报告",
    agent=report_writer,
    context=[research_task, swot_task],
    output_file="output/competitor_report.md"
)

# === Crew ===
crew = Crew(
    agents=[market_researcher, swot_analyst, report_writer],
    tasks=[research_task, swot_task, report_task],
    process=Process.sequential,
    memory=True,
    verbose=2
)

if __name__ == "__main__":
    competitors = ["Notion AI", "Coda AI", "Microsoft Loop"]
    result = crew.kickoff(inputs={"competitors": competitors})
    print(result.raw)

业务价值:原本 2 天的人工调研 → 2 小时自动化输出,Token 成本约 0.5\~2。


案例二:自动代码评审(层级流程 + 自定义工具)

业务场景:为代码仓库自动运行多 Agent 评审流程,包含代码规范、安全、性能三个维度。

完整代码:

python 复制代码
# examples/03_code_review.py
"""
案例 2: 自动代码评审系统
技术亮点:
- Hierarchical 流程,Manager 自动委派
- 自定义工具(Python 静态分析)
- 多维度评审并行
"""
import subprocess
from crewai import Agent, Task, Crew, Process
from crewai.tools import BaseTool
from pydantic import Field
from typing import Type
from pydantic import BaseModel as PydanticBaseModel

# === 自定义工具:Python 静态分析 ===
class LintToolInput(PydanticBaseModel):
    """lint 工具的输入 schema"""
    file_path: str = Field(..., description="Python 文件路径")

class PythonLintTool(BaseTool):
    name: str = "Python 代码规范检查"
    description: str = "运行 flake8 和 mypy 检查 Python 代码,返回问题列表"

    def _run(self, file_path: str) -> str:
        try:
            # flake8
            flake8_result = subprocess.run(
                ["flake8", file_path, "--max-line-length=100"],
                capture_output=True, text=True, timeout=30
            )
            issues = flake8_result.stdout or "无规范问题"

            return f"代码规范问题:\n{issues}"
        except Exception as e:
            return f"检查失败:{str(e)}"

class SecurityScanTool(BaseTool):
    name: str = "安全漏洞扫描"
    description: str = "用 bandit 扫描 Python 代码中的安全问题"

    def _run(self, file_path: str) -> str:
        try:
            result = subprocess.run(
                ["bandit", "-r", file_path],
                capture_output=True, text=True, timeout=30
            )
            return result.stdout or "无安全问题"
        except FileNotFoundError:
            return "bandit 未安装,跳过安全扫描"
        except Exception as e:
            return f"扫描失败:{str(e)}"

# === Agents ===
code_reviewer = Agent(
    role="代码规范审查员",
    goal="发现违反 PEP8 和类型提示的问题",
    backstory="""你是 Google 高级工程师,5 年代码审查经验。
    关注:命名规范、类型提示、文档字符串、复杂度。""",
    tools=[PythonLintTool()],
    allow_delegation=False
)

security_expert = Agent(
    role="安全审查员",
    goal="识别代码中的安全漏洞",
    backstory="""你是 OWASP 认证专家,专注 Python Web 安全。
    关注:注入、认证、敏感信息泄露、反序列化漏洞。""",
    tools=[SecurityScanTool()],
    allow_delegation=False
)

architect = Agent(
    role="架构审查员",
    goal="评估代码的可维护性和性能",
    backstory="""你是资深架构师,关注 SOLID 原则和性能瓶颈。
    能从代码看出未来的扩展性问题。""",
    allow_delegation=False
)

# === Tasks ===
lint_task = Task(
    description="""审查 {file_path} 的代码规范。
    重点:命名、类型提示、文档、复杂度""",
    expected_output="问题清单(文件:行号 + 问题描述 + 严重程度)",
    agent=code_reviewer
)

security_task = Task(
    description="""扫描 {file_path} 的安全漏洞""",
    expected_output="安全风险清单(漏洞类型 + 位置 + 风险等级 + 修复建议)",
    agent=security_expert
)

arch_task = Task(
    description="""评估 {file_path} 的架构合理性""",
    expected_output="架构评估报告(可维护性、性能、可测试性评分 + 改进建议)",
    agent=architect
)

final_review_task = Task(
    description="""综合三个维度的审查结果,
    输出最终的代码审查报告,包含:
    - 通过/不通过
    - 必须修复的问题(阻塞)
    - 建议优化的问题
    - 整体评分(0-100)""",
    expected_output="Markdown 格式的最终审查报告",
    agent=code_reviewer,  # 让 code_reviewer 汇总
    context=[lint_task, security_task, arch_task]
)

# === Crew(层级流程)===
crew = Crew(
    agents=[code_reviewer, security_expert, architect],
    tasks=[lint_task, security_task, arch_task, final_review_task],
    process=Process.hierarchical,   # Manager 自动委派
    manager_llm="gpt-4o",
    verbose=2
)

if __name__ == "__main__":
    result = crew.kickoff(inputs={"file_path": "src/user_service.py"})
    print(result.raw)

架构亮点:

  • Hierarchical 流程让 Manager 灵活决定评审顺序
  • 自定义工具直接调用本地静态分析工具,零外部依赖
  • 最终任务 context 汇总三个维度结果

案例三:智能客服系统(RAG + 长期记忆)

业务场景:电商客服机器人,能记住用户偏好和历史工单,提供个性化回答。

完整代码:

python 复制代码
# examples/04_customer_service.py
"""
案例 3: 智能客服系统
技术亮点:
- RAG 检索增强(基于知识库)
- 长期记忆(跨会话记住用户)
- 自定义工具查询订单系统
"""
from crewai import Agent, Task, Crew, Process
from crewai.tools import BaseTool, tool
from crewai_tools import PDFSearchTool
from pydantic import Field
import json

# === 模拟订单系统 ===
MOCK_ORDERS = {
    "user_123": [
        {"id": "ORD001", "product": "iPhone 15", "status": "已发货", "date": "2026-09-10"},
        {"id": "ORD002", "product": "AirPods Pro", "status": "已完成", "date": "2026-08-25"},
    ]
}

@tool("查询订单状态")
def query_order(user_id: str) -> str:
    """查询指定用户的所有订单状态。
    参数:
        user_id: 用户 ID
    返回:
        JSON 格式的订单列表
    """
    orders = MOCK_ORDERS.get(user_id, [])
    return json.dumps(orders, ensure_ascii=False, indent=2)

# === RAG 知识库工具 ===
# 假设产品手册已放到 ./knowledge/ 目录
kb_tool = PDFSearchTool(pdf="./knowledge/product_manual.pdf")

# === Agents ===
intent_classifier = Agent(
    role="意图分类器",
    goal="识别用户问题的真实诉求",
    backstory="""你专注于自然语言理解,
    能从用户的多样化表达中识别:
    - 订单查询类
    - 产品咨询类
    - 投诉建议类
    - 其他""",
    verbose=True
)

knowledge_expert = Agent(
    role="产品知识专家",
    goal="基于产品手册回答用户咨询",
    backstory="""你精通公司所有产品的参数、功能、使用方法。
    永远以官方手册为准,不编造信息。
    回答必须有手册引用。""",
    tools=[kb_tool],
    verbose=True
)

order_agent = Agent(
    role="订单专员",
    goal="查询和处理订单相关问题",
    backstory="""你能访问订单系统,回答发货、退换货等问题。
    涉及退款必须明确告知时效(7-15 工作日)。""",
    tools=[query_order],
    verbose=True
)

response_writer = Agent(
    role="客服回复撰写员",
    goal="整合信息,生成友好专业的回复",
    backstory="""你代表公司形象,回复必须:
    - 语气亲切(用'亲'、'您')
    - 结构清晰(先结论后细节)
    - 必要时提供后续步骤
    - 涉及情绪问题先共情再解决""",
    verbose=True
)

# === Tasks ===
classify_task = Task(
    description="""分析用户问题:{user_query}
    输出分类结果(订单/产品/投诉/其他)""",
    expected_output="""JSON: {"category": "...", "urgency": "high/medium/low"}""",
    agent=intent_classifier
)

knowledge_task = Task(
    description="""基于用户问题搜索产品手册,回答用户的咨询。
    问题:{user_query}""",
    expected_output="产品相关的准确回答 + 手册引用",
    agent=knowledge_expert,
    context=[classify_task]
)

order_task = Task(
    description="""查询用户的订单状态。
    user_id:{user_id}""",
    expected_output="订单列表",
    agent=order_agent,
    context=[classify_task]
)

response_task = Task(
    description="""综合所有信息,撰写最终回复给用户。
    user_query:{user_query}""",
    expected_output="一段友好专业的客服回复",
    agent=response_writer,
    context=[classify_task, knowledge_task, order_task]
)

# === Crew ===
crew = Crew(
    agents=[intent_classifier, knowledge_expert, order_agent, response_writer],
    tasks=[classify_task, knowledge_task, order_task, response_task],
    process=Process.sequential,
    memory=True,                # 启用长期记忆
    long_term_memory=None,       # 用默认的 SQLite 存储
    verbose=2
)

# === 使用 ===
if __name__ == "__main__":
    # 第一轮对话
    result1 = crew.kickoff(inputs={
        "user_id": "user_123",
        "user_query": "我上周买的 iPhone 怎么还没收到?"
    })
    print("回复 1:", result1.raw)

    # 第二轮对话(Agent 能记住 user_123 的历史)
    result2 = crew.kickoff(inputs={
        "user_id": "user_123",
        "user_query": "那我可以换个颜色吗?"
    })
    print("回复 2:", result2.raw)

核心价值 :长期记忆让 Agent 知道"那个 iPhone"指的就是 ORD001,用户体验从冰冷的机器人变成了"懂我的客服"。


第六篇 · 源码解析

本节适合想深入理解 CrewAI 内部实现、定制功能或排查问题的同学。

6.1 Crew 类核心调度逻辑

核心文件 :crewai/crew.py

核心方法 kickoff 的执行流程:

python 复制代码
# 简化版源码
def kickoff(self, inputs: Dict[str, Any]) -> CrewOutput:
    # 1. 输入校验 + 初始化
    self._inputs = inputs
    self._setup()

    # 2. 根据 process 类型调度
    if self.process == Process.sequential:
        return self._run_sequential()
    elif self.process == Process.hierarchical:
        return self._run_hierarchical()

def _run_sequential(self) -> CrewOutput:
    task_output = None
    for task in self.tasks:
        # 3. 把上游输出注入下游 prompt
        if task.context:
            task.context = [t.output for t in task.context]
        # 4. 执行任务
        task_output = task.execute_sync(agent=task.agent)
        # 5. 记忆系统记录
        if self.memory:
            self._long_term_memory.save(task_output)
    return CrewOutput(tasks_output=[t.output for t in self.tasks])

关键设计:

  1. Context 注入 :通过修改 task.context 的实际引用实现
  2. 记忆分层:每完成一个 task 就写入长期记忆,便于跨任务检索
  3. 异步支持 :内部用 asyncio 实现并发,但 kickoff 本身是同步包装

6.2 Agent 的 ReAct 循环

核心文件 :crewai/agent.py

Agent 内部用 LangChain 的 AgentExecutor 实现 ReAct(Reasoning + Acting)循环:

python 复制代码
# 简化版
def execute_task(self, task: Task) -> TaskOutput:
    # 1. 构造 prompt
    system_prompt = self._build_system_prompt()
    user_prompt = self._build_user_prompt(task)

    # 2. 调用 LLM
    response = self.llm.invoke([
        SystemMessage(content=system_prompt),
        HumanMessage(content=user_prompt)
    ])

    # 3. 检查是否需要委派
    if self.allow_delegation and "delegate" in response:
        return self._handle_delegation(response, task)

    # 4. 检查是否需要调用工具
    while response.tool_calls:
        tool_results = []
        for tool_call in response.tool_calls:
            result = self._execute_tool(tool_call)
            tool_results.append(result)
        # 5. 把工具结果返回给 LLM 继续推理
        response = self.llm.invoke([
            ...,
            ToolMessage(content=result, tool_call_id=tool_call.id)
        ])

    # 6. 解析最终输出
    return TaskOutput(raw=response.content)

ReAct 循环的关键参数:

  • max_iter:最大循环次数(默认 15)
  • early_stopping_method:何时停止("force" / "generate")
  • 工具调用失败的默认行为:返回错误信息给 LLM,让 LLM 决定下一步

6.3 Hierarchical Manager 委派实现

核心文件 :crewai/crew.py 中的 _run_hierarchical

Manager 本质上也是一个 Agent,只不过它的 tools 是特殊的"委派工具":

python 复制代码
class DelegateWorkTool(BaseTool):
    """Manager 用来委派任务给 Worker 的工具"""
    name = "Delegate work to coworker"
    description = "把任务委派给指定的 coworker"

    def _run(self, task: str, coworker: str, context: str) -> str:
        # 找到对应 worker agent
        worker = self._find_agent(coworker)
        # 委派执行
        worker.execute_task(Task(description=task, context=context))
        return "任务已委派"

class AskQuestionTool(BaseTool):
    """Manager 向 Worker 提问的工具"""
    name = "Ask question to coworker"
    description = "向指定的 coworker 提问"

Manager 的工作流:

复制代码
1. Manager 接收所有任务列表
2. Manager 看到可用工具列表(DelegateWorkTool + AskQuestionTool + Worker 列表)
3. Manager 决定:任务 X 应该分给 Worker Y
4. Manager 调用 DelegateWorkTool
5. Worker 执行后返回结果
6. Manager 检查结果,可能继续委派其他任务或汇总

关键洞察:Manager 没有任何特殊能力,它只是一个"被赋予特殊工具的 Agent"。这意味着 Manager 的质量完全取决于:

  • 它的 system prompt(描述它的管理职责)
  • 它使用的 LLM 能力
  • Worker 列表的清晰度

第七篇 · 生产化

7.1 可观测性

生产环境必须能追踪 Agent 的每一步。

使用 AgentOps
bash 复制代码
pip install agentops
python 复制代码
import agentops
agentops.init(api_key="your_key")  # 初始化

# 之后所有 Crew 执行都会被自动追踪
result = crew.kickoff(inputs={...})

AgentOps 提供:每次 kickoff 的 Token 消耗、每个 Agent 的决策路径、工具调用记录、错误堆栈。

使用 Langfuse(开源替代)
python 复制代码
from langfuse.callback import CallbackHandler

langfuse_handler = CallbackHandler(
    public_key="...",
    secret_key="...",
    host="https://cloud.langfuse.com"
)

# 在 LLM 调用中接入
result = crew.kickoff(
    inputs={...},
    callbacks=[langfuse_handler]
)

7.2 评估体系

为什么 Agent 评估很难
  • 输出是自然语言,无法精确比对
  • Agent 路径不可预测,每次可能走不同的工具调用
  • 质量是连续光谱,不是 0/1
评估方法论

1. 结果评估(最简单)

python 复制代码
def evaluate_crew_output(crew, test_case):
    result = crew.kickoff(inputs=test_case.inputs)

    scores = {
        "完成度": check_required_sections(result.raw),
        "准确性": fact_check(result.raw, ground_truth=test_case.expected_facts),
        "格式合规": check_format(result.raw, expected_format="markdown"),
    }
    return scores

2. 过程评估(更深入)

记录每次执行的"决策日志",评估 Agent 是否走了合理的路径:

python 复制代码
# 启用详细日志
crew = Crew(..., verbose=2, step_callback=log_step)

def log_step(step_output):
    """每个 Agent 步骤的回调"""
    logger.info(f"Step: {step_output}")
    # 存储到数据库用于后续分析
    db.insert("agent_steps", step_output.dict())

3. LLM-as-Judge(用 LLM 评估 LLM)

python 复制代码
from openai import OpenAI

def llm_judge(question, answer, criteria):
    client = OpenAI()
    prompt = f"""
    评估以下回答的质量:
    问题:{question}
    回答:{answer}
    标准:{criteria}

    给出 1-10 分并说明理由。
    """
    return client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}]
    ).choices[0].message.content

7.3 成本与性能优化

成本构成

典型 Crew 执行的 Token 消耗分布:

复制代码
┌──────────────────────────────────────────┐
│  System Prompt  20%   (每个 Agent 重复)│
│  Tool Schemas   15%   (随工具数量增长)  │
│  Conversation   40%   (上下文累积)      │
│  Output         25%   (最终输出)       │
└──────────────────────────────────────────┘
优化策略
策略 节省 实现
模型分级 40-60% 简单任务用 gpt-4o-mini,复杂推理用 gpt-4o
工具缓存 30-50% cache=True 缓存工具结果(相同输入不重复调用)
Prompt 精简 10-20% Backstory 不要超过 200 字
任务拆分 20-30% 大任务拆成小任务,避免超长上下文
异步并发 50%+ 用 async_execution=True 并行独立任务
启用缓存
python 复制代码
crew = Crew(
    agents=[...],
    tasks=[...],
    cache=True,  # 关键!缓存工具结果
)

7.4 错误处理与重试

工具失败重试

CrewAI 默认对工具有限的重试机制,建议自定义更完善的包装:

python 复制代码
from tenacity import retry, stop_after_attempt, wait_exponential

class ResilientWeatherTool(BaseTool):
    name = "天气查询"

    @retry(
        stop=stop_after_attempt(3),
        wait=wait_exponential(multiplier=1, min=2, max=10)
    )
    def _run(self, city: str) -> str:
        return requests.get(...).text
整体兜底
python 复制代码
from crewai.utilities.exceptions import CrewError

try:
    result = crew.kickoff(inputs={...})
except CrewError as e:
    logger.error(f"Crew 执行失败: {e}")
    # 兜底:返回缓存结果 or 人工介入
    result = get_cached_result_or_notify_human()
死循环检测

设置 max_iter 防止 Agent 死循环:

python 复制代码
agent = Agent(
    role="...",
    max_iter=10,  # 超过 10 轮推理强制结束
)

附录

A. 常见问题 FAQ

Q1: Sequential 和 Hierarchical 如何选择?

A: 任务依赖关系明确(如 A→B→C)用 Sequential;任务需要动态决策或并行执行用 Hierarchical。Hierarchical 会多消耗 2~3 倍 Token。

Q2: Agent 能"看到"其他 Agent 的输出吗?

A: 通过 Task 的 context 参数实现。设置 context=[task_a] 后,task_a 的输出会自动注入到当前任务的 prompt 中。

Q3: 如何让 Agent 强制输出 JSON?

A: 用 output_pydantic=YourModel,CrewAI 会自动让 LLM 输出符合 schema 的 JSON,并解析为 Pydantic 对象。

Q4: 记忆系统占用多少空间?

A: 默认 SQLite 存储在 ~/.crewai/memory.db。长期记忆每条约 1KB。生产建议用外部向量库(Qdrant、Pinecone)。

Q5: CrewAI 支持中文吗?

A: 完全支持。LLM 本身就是中文能力强的模型,CrewAI 不限制语言。

Q6: 如何调试 Agent 的行为?

A:

  1. verbose=True 看思考过程
  2. 用 step_callback 记录每步
  3. 用 AgentOps / Langfuse 可视化追踪

Q7: 一个 Agent 能同时属于多个 Crew 吗?

A: 可以。每次 crew.kickoff() 会创建新的 Agent 实例(Factory 模式)。

Q8: 任务执行时间太长怎么办?

A:

  1. 用更快的模型(gpt-4o-mini)
  2. 启用 cache=True
  3. 拆分大任务
  4. 考虑用 LangGraph 重构

B. 推荐学习资源

资源 说明
CrewAI 官方文档 第一手 API 参考
CrewAI GitHub 源码与 examples
CrewAI Discord 社区实时答疑
DeepLearning.AI: Multi-Agent Systems with crewAI Andrew Ng 团队的入门课
《LangGraph vs CrewAI vs AutoGen》--- ByteLedger 2026 横向对比基准测试
AgentOps 文档 生产可观测性方案
Langfuse 文档 开源 LLM 可观测性

写在最后

CrewAI 的精髓是用角色化、流程化的方式把"团队协作"映射到 LLM 调用------Agent 像员工,Task 像工单,Crew 像项目经理。理解了这层隐喻,就理解了它的设计哲学。

学习路径建议:

复制代码
Week 1-2: 跑通官方 Quickstart + 本手册示例 1
Week 3-4: 改造示例 1,加入自定义工具和记忆
Week 5-6: 完成示例 2、3,理解 Hierarchical 和 RAG
Week 7-8: 读源码(crew.py + agent.py),理解调度机制
Week 9+:  生产化(可观测性、评估、成本优化)

下一步 :动手跑通示例 1,然后根据自己的业务场景改造它。实践 > 理论。


本文档基于 CrewAI 1.0+ 版本编写,2026 年 9 月。内容可能随版本迭代变化,请以官方文档为准。

许可:本手册基于知识共享署名 4.0(CC BY 4.0)发布,欢迎自由分享与改编。

相关推荐
菜_小_白32 分钟前
codex
linux·vscode·ai
孙启超1 小时前
【FDE开发指南】第 5 课:中国市场的 FDE
人工智能·ai·职场技能
空心木偶☜2 小时前
Langgraph操作时常见的错误
python·ai·ai编程·langgraph
c萱3 小时前
AI产品经理——03Prompt Engineering提示词工程
ai·prompt·aigc·产品经理·ai编程·ai-native
xuhe23 小时前
Codex解决新模型无法使用/model选择的问题
linux·ai·codex
我才是银古6 小时前
AI 啃 DWG图纸:从二维到三维
ai·cad·dwg
codigger7 小时前
把 AI Agent 养在自己电脑上:从本地部署到远程接管的一份完整思路
ai·编程·#人工智能·#agent
空心木偶☜7 小时前
LangGraph
ai·ai编程·langgraph
空心木偶☜7 小时前
langgraph加上“循环”和“记忆”
ai·ai编程·langgraph
Martina_03217 小时前
AI生成的盔甲换动作后漂移?用6步检查挂点、骨架映射与 Bind Pose
人工智能·游戏·3d·ai·自然语言处理·aigc·游戏策划