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 处理复杂任务时会遇到三个核心问题:
- 上下文过载:所有工具、规则、历史都塞进同一个 Prompt,超出模型容量
- 角色冲突:要求"既是工程师又是产品经理又是 UX"会让 LLM 推理混乱
- 难以审计:谁做了什么、用了什么工具、为什么这么决策,无法清晰追溯
多 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()
执行流程:
- Manager 接收所有 Task 和 Agent 列表
- Manager 用 LLM 决策"任务 X 应该分给哪个 Worker"
- 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], ...)
工具设计最佳实践
- 原子化:一个工具只做一件事
- 强类型参数:用 Pydantic Field 描述参数约束
- 清晰的 description:Agent 靠 description 决定何时调用,描述要包含"何时用 + 怎么用 + 返回什么"
- 错误处理:工具失败返回明确错误信息,不要抛异常
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])
关键设计:
- Context 注入 :通过修改
task.context的实际引用实现 - 记忆分层:每完成一个 task 就写入长期记忆,便于跨任务检索
- 异步支持 :内部用 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:
verbose=True看思考过程- 用
step_callback记录每步 - 用 AgentOps / Langfuse 可视化追踪
Q7: 一个 Agent 能同时属于多个 Crew 吗?
A: 可以。每次 crew.kickoff() 会创建新的 Agent 实例(Factory 模式)。
Q8: 任务执行时间太长怎么办?
A:
- 用更快的模型(gpt-4o-mini)
- 启用
cache=True - 拆分大任务
- 考虑用 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)发布,欢迎自由分享与改编。