🔥 CrewAI 实战:构建多 Agent 协作团队

🔥 CrewAI 实战:构建多 Agent 协作团队


🔍 引言

在 AI 时代,单一 Agent 已经难以应对复杂的多步骤任务。多 Agent 协作系统通过角色分工、任务编排,让多个 AI 智能体像团队一样协同工作。本文将带你从零开始构建一个基于 CrewAI 的多 Agent 协作系统,实现研究员、分析师、报告撰写员的分工协作。

🎯 项目亮点

特性 实现方式 技术亮点
🤖 多角色分工 CrewAI Agent 专业化角色定义
🔄 任务编排 CrewAI Task 顺序执行与上下文传递
🛠️ 工具集成 BaseTool 统一工具调用
📊 数据处理 SQLite + Pandas 结构化数据查询
📧 报告输出 文件写入 自动化报告生成
🤖 LLM 集成 DeepSeek API 高效推理能力

🏗️ 整体架构

flowchart TB subgraph CrewAI["CrewAI Multi-Agent 系统"] subgraph Agents["Agent 角色层"] R[Researcher
研究员] A[Analyst
分析师] W[Writer
撰写员] end subgraph Tasks["Task 任务层"] RT[Research Task
研究任务] AT[Analysis Task
分析任务] WT[Write Task
撰写任务] end subgraph Tools["Tool 工具层"] TS[TavilySearch
网络搜索] WE[Weather
天气查询] DQ[DatabaseQuery
数据库查询] CA[Calculator
计算器] FW[FileWriter
文件写入] end subgraph LLM_Lary["LLM 层"] LLM[DeepSeek V4
推理引擎] end end RT --> TS RT --> WE RT --> DQ AT --> CA WT --> FW R --> RT A --> AT W --> WT Agents --> LLM_Lary RT --> |context| AT AT --> |context| WT classDef task fill:#e1f5fe,stroke:#01579b,stroke-width:1px; classDef crewAI fill:#fff9c4,stroke:#fbc02d,stroke-width:1px; classDef agents fill:#e8f5e9,stroke:#2e7d32,stroke-width:1px; class Tasks task; class CrewAI crewAI; class Agents agents;

🚀 核心功能实现

1. 工具定义

在 CrewAI 中,工具通过继承 BaseTool 类实现,每个工具需要定义 namedescription_run 方法:

python 复制代码
from crewai.tools import BaseTool
import math
import requests
import sqlite3
import pandas as pd

class Calculator(BaseTool):
    name: str = "Calculator"
    description: str = "执行数学计算,输入纯数学表达式,如 '2+3*4'。"

    def _run(self, expression: str) -> str:
        """执行数学计算,输入纯数学表达式,如 '2+3*4'。"""
        allowed = set("0123456789.+-*/() ")
        if not all(c in allowed for c in expression):
            return "Error: 表达式包含非法字符"
        try:
            return str(eval(expression, {"__builtins__": {}}, math.__dict__))
        except Exception as e:
            return f"Error: {str(e)}"


class Weather(BaseTool):
    name: str = "Weather"
    description: str = "查询指定城市的实时天气,输入城市中文名,如 '北京'。"

    def _run(self, city: str) -> str:
        """查询指定城市的实时天气,输入城市中文名,如 '北京'。"""
        geo_url = f"https://geocoding-api.open-meteo.com/v1/search?name={city}&count=1"
        geo_data = requests.get(geo_url).json()
        if not geo_data.get("results"):
            return f"未找到城市 {city}"
        lat = geo_data["results"][0]["latitude"]
        lon = geo_data["results"][0]["longitude"]
        weather_url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&current_weather=true"
        w_data = requests.get(weather_url).json()
        cur = w_data["current_weather"]
        return f"{city}当前温度 {cur['temperature']}°C,风速 {cur['windspeed']} km/h"


class DatabaseQuery(BaseTool):
    name: str = "DatabaseQuery"
    description: str = "执行SQL查询,可查询 sales 表(含 product, amount, date 字段)。"

    def _run(self, query: str) -> str:
        """执行SQL查询,可查询 sales 表(含 product, amount, date 字段)。"""
        init_db()
        try:
            conn = sqlite3.connect("sales.db")
            df = pd.read_sql_query(query, conn)
            conn.close()
            if df.empty:
                return "查询结果为空"
            return df.to_string(index=False)
        except Exception as e:
            return f"查询出错: {e}"


class FileWriter(BaseTool):
    name: str = "FileWriter"
    description: str = "将内容写入文件,例如 'report.md'。"

    def _run(self, filename: str, content: str) -> str:
        """将内容写入文件,例如 'report.md'。"""
        try:
            with open(filename, "w", encoding="utf-8") as f:
                f.write(content)
            return f"成功写入文件: {filename}"
        except Exception as e:
            return f"写入失败: {e}"

2. Agent 角色定义

2.1 LLM 配置
python 复制代码
from crewai import LLM

llm = LLM(
    model="deepseek/deepseek-v4-pro",  # 模型名称
    base_url="https://api.deepseek.com",  # API 基础地址
    temperature=0,  # 温度参数(0-1,越低越确定性)
    reasoning_effort="high",  # 推理深度
)
2.2 Agent 参数详解
python 复制代码
from crewai import Agent

researcher = Agent(
    role="资深研究员",  # 角色名称
    goal="利用网络搜索、数据库、天气等工具收集和分析信息,输出关键发现。",  # 目标
    backstory="你是一个全栈研究员,能使用各种工具获取实时数据、查询内部系统。",  # 背景故事
    tools=[tavily_search, Weather(), DatabaseQuery(), Calculator()],  # 分配的工具
    verbose=True,  # 是否输出详细日志
    allow_delegation=False,  # 是否允许委派任务
    llm=llm  # 指定的 LLM
)

analyst = Agent(
    role="高级数据分析师",
    goal="处理研究员获得的原始数据,进行计算、对比,提炼出有价值的洞察。",
    backstory="你是数据专家,擅长从表格和数字中看出趋势。",
    tools=[Calculator()],
    verbose=True,
    allow_delegation=False,
    llm=llm
)

writer = Agent(
    role="报告撰写员",
    goal="根据分析师的洞察,撰写结构清晰、语言流畅的Markdown报告,并保存文件。",
    backstory="你是一名技术文档工程师,追求简洁与严谨。",
    tools=[FileWriter()],
    verbose=True,
    allow_delegation=False,
    llm=llm
)

Agent 完整参数表:

参数 类型 必需 说明
role str Agent 的角色名称,定义其在团队中的职能
goal str Agent 的目标,驱动其行为决策
backstory str Agent 的背景故事,增强角色一致性
tools list[BaseTool] 分配给 Agent 的工具列表
llm LLM 指定使用的语言模型
verbose bool 启用详细日志输出,默认 False
allow_delegation bool 允许 Agent 委派任务给其他 Agent
max_iter int 最大迭代次数,默认 20
max_rpm int 每分钟最大请求数
memory bool 启用记忆功能,默认 True
cache bool 启用工具结果缓存,默认 True
respect_context_window bool 尊重上下文窗口限制,默认 True

3. 任务编排

python 复制代码
from crewai import Task

research_task = Task(
    description="""
    1. 使用 search 工具搜索"2026年5月全国天气趋势"。
    2. 使用 weather 工具查询"北京"和"深圳"的当前天气。
    3. 使用 database_query 查询所有销售记录。
    请将以上三项结果整理为一份要点列表。
    """,
    expected_output="一份包含天气趋势、两个城市实时天气、销售记录表的要点列表。",
    agent=researcher
)

analysis_task = Task(
    description="""
    根据研究员提供的数据:
    - 计算总销售额(用计算器)。
    - 简单评论天气是否可能影响销售(例如高温或暴雨与销售额的关系)。
    """,
    expected_output="包含总销售额和一个简短天气影响评述的文本。",
    agent=analyst,
    context=[research_task]  # 依赖研究员的任务输出
)

write_task = Task(
    description="""
    基于分析师的结论,撰写一份名为 weather_sales_report.md 的Markdown报告。
    标题:《天气与销售关联分析报告》
    内容需包含:数据概览、天气情况、销售总额、影响简评。
    """,
    expected_output="完整的Markdown报告。",
    agent=writer,
    output_file="weather_sales_report.md",
    context=[analysis_task]
)

Task 完整参数表:

参数 类型 必需 说明
description str 任务的详细描述
expected_output str 期望的输出格式/内容
agent Agent 执行此任务的 Agent
context list[Task] 前置任务列表,用于上下文传递
output_file str 输出文件路径
tools list[BaseTool] 任务专用工具(覆盖 Agent 工具)
async_execution bool 是否异步执行,默认 False
config dict 任务特定配置
callback function 任务完成回调函数

4. Crew 组装与执行

python 复制代码
from crewai import Crew, Process

crew = Crew(
    agents=[researcher, analyst, writer],  # Agent 列表
    tasks=[research_task, analysis_task, write_task],  # Task 列表
    process=Process.sequential,  # 执行流程
    verbose=True,  # 日志级别
    memory=True,  # 启用记忆
    embedder={  # 嵌入配置
        "provider": "openai",
        "model": "text-embedding-3-small"
    },
    share_crew=True  # 共享 Crew 实例
)

result = crew.kickoff()
print("最终输出:\n", result)

Crew 完整参数表:

参数 类型 必需 说明
agents list[Agent] Agent 列表
tasks list[Task] Task 列表
process Process 执行流程:sequential/hierarchical/parallel
verbose int 启用详细日志输出,默认 False
memory bool 启用 Crew 级别记忆,默认 False
embedder dict 嵌入模型配置
planning bool 启用任务规划,默认 False
planning_llm LLM 规划使用的 LLM
max_rpm int 全局每分钟请求数限制
language str 输出语言,默认 "zh"
step_callback function 每步执行后的回调
share_crew bool 共享 Crew 实例

Process 执行模式:

模式 说明 适用场景
Process.sequential 顺序执行 任务有明确先后依赖
Process.hierarchical 层级管理 需要 Manager Agent 协调
Process.parallel 并行执行 任务相互独立可同时执行

📦 依赖与环境配置

安装依赖

bash 复制代码
pip install crewai crewai-tools langchain-core python-dotenv requests pandas

环境变量配置(.env)

tex 复制代码
TAVILY_API_KEY=your_tavily_api_key
DEEPSEEK_API_KEY=your_deepseek_api_key

💡 使用示例

运行命令

bash 复制代码
python main.py

执行流程

sequenceDiagram participant User as 用户 participant Researcher as 研究员 participant Analyst as 分析师 participant Writer as 撰写员 User->>Researcher: 启动任务 Researcher->>Researcher: 搜索天气趋势 Researcher->>Researcher: 查询北京天气 Researcher->>Researcher: 查询深圳天气 Researcher->>Researcher: 查询销售数据 Researcher-->>Analyst: 返回综合要点列表 Analyst->>Analyst: 计算总销售额 Analyst->>Analyst: 分析天气影响 Analyst-->>Writer: 返回分析结论 Writer->>Writer: 撰写 Markdown 报告 Writer->>Writer: 保存 weather_sales_report.md Writer-->>User: 返回完整报告

输出示例


🔧 核心技术解析

1. Agent 角色设计原则

原则 说明
专业化 每个 Agent 只负责一个领域
职责清晰 通过 role 和 goal 明确定位
工具匹配 根据职责分配必要的工具
可追溯 通过 verbose 模式追踪执行过程
LLM 独立 每个 Agent 可使用独立的 LLM

2. 任务上下文传递

CrewAI 通过 context 参数实现任务间数据传递:

python 复制代码
analysis_task = Task(
    ...,
    context=[research_task]  # 研究员的输出作为分析师的输入
)
flowchart LR R[Researcher
研究输出] -->|context| A[Analyst
分析输入] A[Analyst
分析输出] -->|context| W[Writer
撰写输入]

3. 工具权限控制

每个 Agent 只分配必要的工具:

Agent 工具权限 理由
研究员 搜索、天气、数据库、计算器 需要收集各种数据源
分析师 仅计算器 专注于数据分析
撰写员 仅文件写入 专注于输出生成

4. LLM 集成策略

flowchart TB subgraph LLM配置["LLM 配置选项"] A[全局 LLM
Crew 级别] B[独立 LLM
Agent 级别] C[规划 LLM
Planning 级别] end A --> |所有 Agent 默认使用| Crew B --> |特定任务优化| Agents C --> |任务规划| Planning

🚀 技术洞察

1. 角色分工的重要性

多 Agent 的核心价值在于分工协作:

  • 研究员:负责信息收集(外部搜索、数据库查询)
  • 分析师:负责数据处理和洞察提炼
  • 撰写员:负责结构化输出

2. BaseTool vs @tool 装饰器

CrewAI 推荐使用 BaseTool 类而非 LangChain 的 @tool 装饰器:

特性 BaseTool @tool 装饰器
集成度 CrewAI 原生 需适配
类型提示 完整支持 部分支持
缓存机制 内置 需额外配置
异步支持 支持 需适配

📊 性能优化建议

优化方向 具体措施
任务并行化 将可并行的任务设置为并行执行
结果缓存 启用 cache=True 缓存重复查询结果
工具选择优化 根据 Agent 角色精简工具列表
日志级别控制 生产环境降低 verbose 级别
异步执行 使用 async_execution=True 支持异步工具调用
上下文窗口 启用 respect_context_window=True 避免溢出
记忆管理 合理使用 memory=True 平衡性能和资源

🎯 总结与展望

本文要点

  1. ✅ 使用 CrewAI 构建多 Agent 协作系统
  2. ✅ 定义专业化的 Agent 角色(研究员、分析师、撰写员)
  3. ✅ 实现任务编排与上下文传递
  4. ✅ 集成多种工具(搜索、天气、数据库、计算器)
  5. ✅ 自动生成结构化报告
  6. ✅ 配置 DeepSeek LLM 实现高效推理

未来方向

  • 🔄 动态角色分配:根据任务自动选择合适的 Agent
  • 🧠 角色沟通:Agent 之间可以直接沟通
  • 📊 性能监控:追踪每个 Agent 的执行效率
  • 🔒 权限管理:细粒度的工具访问控制
  • 📱 UI 界面:可视化展示多 Agent 协作过程

📮 互动交流

如果你有任何问题或想法,欢迎在评论区留言!如果觉得本文对你有帮助,请点赞、收藏、关注三连支持一下~

相关推荐
GarrettGao1 小时前
MCP 实践-用 AI 对话触发 Jenkins 打包App
ai编程·mcp
郭煌1 小时前
# 什么该交给 AI,什么自己来:一个工程师的 4 象限决策法
ai编程
ZengLiangYi1 小时前
AI Coding JSONL 里的系统标签噪音如何过滤
ai编程
HLAIA光子1 小时前
Claude Code、Codex 为什么都选了 Grep 而不是 RAG
ai编程·claude
沫离痕2 小时前
Claude Code 配置目录说明
ai编程
人月神话Lee2 小时前
【图像处理】二值化与阈值——从灰度到黑白的决策
ios·ai编程·图像识别
guslegend3 小时前
第9节:前端工程与一键启动
前端·大模型·状态模式·ai编程
Dvesiz4 小时前
【ClaudeCode平替(免费)】OpenCode 完整安装与 VSCode 使用指南
ide·vscode·编辑器·github·ai编程·claude·visual studio code
xiaoxue..4 小时前
Harness Engineering 讲解
架构·ai编程·harness