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)发布,欢迎自由分享与改编。

相关推荐
李博士每天要洗澡1 小时前
AI Agent 怎样参与视频剪辑?从任务描述、MCP 到可编辑时间线
大数据·人工智能·ai·django·pygame
FIT2CLOUD飞致云2 小时前
GPU监控支持华为昇腾设备,防火墙管理焕新,虚拟机管理下放至专业版,1Panel v2.3.0版本发布
运维·ai·开源·1panel·运维面板
修电脑的猫11 小时前
在中国使用 Claude Code 解决 403 错误(VS CODE)
ai·sap
蚕豆糯米饭13 小时前
Github Copilot 研发效能提升实战指南
ai·github·copilot·ai编程
Token掘金室14 小时前
Aider配置自定义API教程
ai
Young丶16 小时前
讲透 Claude Code 系列 (四):Claude Skills 完全指南:可复用的“专业能力包”从入门到精通
人工智能·ai·ai编程·ai coding
小七-七牛开发者16 小时前
谷歌利用果蝇实现“AI 突围”?Cognition 再融 20 亿美元;AI 三巨头集体呼吁放慢脚步
ai·agent·token·skill·周一上线
子非鱼eva17 小时前
Ascend950PR版本速配表
人工智能·ai