当单个大模型需要同时完成资料检索、内容生成和事实核验时,往往会出现角色混淆:生成时频繁打断、检索时过早下结论、核验时又缺少统一标准。CrewAI的核心思路不是让一个模型硬扛所有环节,而是把任务拆解给多个具有独立身份、目标和背景的智能体,让它们像真实团队一样协作。下面从核心概念和可运行代码开始,演示如何用CrewAI定义角色与任务。

一、CrewAI 的三个核心对象:Agent、Task 与 Crew
在 CrewAI 中,一个智能体由 Agent 类表示。它最关键的三个参数是 role、goal 和 backstory。role 决定智能体的职业身份,例如研究员、撰稿人、审校员;goal 是它要达成的具体目标;backstory 则补充背景信息,让模型在生成回复时拥有更稳定的语气和专业视角。三者写清楚之后,智能体不会轻易跳出自己的职责边界。
任务由 Task 类表示,需要绑定一个执行智能体,并通过 description 描述工作内容,通过 expected_output 明确产出格式。CrewAI 会根据这两项信息判断任务是否完成,并把结果传递给下一个任务。Crew 是团队的容器,负责接收智能体和任务列表,并按照 process 指定的流程执行。
下面先创建两个基础智能体:一个负责收集信息,另一个负责总结输出。这样能直观看出角色定义对模型行为的影响。
from crewai import Agent, Task, Crew, Process
researcher = Agent(
role="信息研究员",
goal="围绕给定主题收集准确、全面的事实信息",
backstory="你擅长从多个角度检索资料,并整理出结构化要点。",
verbose=True
)
writer = Agent(
role="技术撰稿人",
goal="将研究材料改写成逻辑清晰、易于理解的技术文章",
backstory="你擅长把复杂信息转化为自然流畅的中文技术内容。",
verbose=True
)
research_task = Task(
description="收集CrewAI多智能体框架的核心概念、适用场景和典型工作流。",
expected_output="包含核心概念、适用场景和工作流三部分的要点列表。",
agent=researcher
)
writing_task = Task(
description="根据研究要点撰写一篇面向初学者的CrewAI入门说明。",
expected_output="一篇结构完整的中文技术说明,字数不少于500字。",
agent=writer
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential,
verbose=True
)
result = crew.kickoff()
print(result)
这段代码展示了最小可运行结构。虽然示例中只有两个智能体,但已经能看出角色定义和任务拆分的基本方式。实际项目里,任务之间通常还存在依赖关系,需要把前一个任务的输出作为后一个任务的输入。
二、从角色到任务:搭建一个内容生产团队
一个更贴近真实场景的团队至少包含三个角色:研究员、撰稿人和审校员。研究员负责查找资料并输出带有事实依据的要点,撰稿人把要点组织成文章,审校员检查术语准确性、逻辑连贯性和表达问题。这样拆分的目的是让每个智能体只专注于一个阶段,避免单个模型在长链路任务中丢失目标。
在定义角色时,backstory 不只是装饰。它会被写入提示词中,影响模型的语言风格和专业判断。例如,审校员的目标如果写成“检查文章”,模型可能只给出笼统评价;如果写成“逐段核对术语是否准确、句子是否通顺,并返回修改建议列表”,输出质量会明显提升。因此,描述越具体,智能体越容易执行。
任务之间的数据传递可以通过 context 参数显式声明。例如,撰稿任务可以设置 context=[research_task],这样撰稿智能体在生成内容前会拿到研究任务的结果。CrewAI 会把上游任务的输出注入到下游任务的提示词中,减少重复调用和上下文断裂。
from crewai import Agent, Task, Crew, Process
researcher = Agent(
role="资料研究员",
goal="找到支撑主题的关键事实和案例,并注明来源",
backstory="你拥有信息检索背景,能快速识别可信资料,排除营销噪音。",
verbose=True
)
writer = Agent(
role="技术撰稿人",
goal="根据研究材料撰写一篇有逻辑、可操作的技术文章",
backstory="你擅长把零散信息组织成有层次的教程,语言平实准确。",
verbose=True
)
reviewer = Agent(
role="技术审校员",
goal="逐段检查文章的事实准确性、术语一致性和语句通顺度",
backstory="你是一位严格的技术编辑,只关注错误和可改进之处,不重写全文。",
verbose=True
)
task_research = Task(
description="调研CrewAI的角色定义、任务编排、流程控制以及与LangGraph的差异。",
expected_output="至少5条研究要点,每条包含事实描述和适用场景。",
agent=researcher
)
task_write = Task(
description="基于研究结果,撰写一篇CrewAI多智能体协作实战教程。",
expected_output="一篇不少于800字的技术教程,包含概念解释和代码示例。",
agent=writer,
context=[task_research]
)
task_review = Task(
description="审校教程内容,重点检查术语是否准确、逻辑是否连贯、代码示例是否有误。",
expected_output="修改建议列表,每条建议标明原文位置和修改理由。",
agent=reviewer,
context=[task_write]
)
crew = Crew(
agents=[researcher, writer, reviewer],
tasks=[task_research, task_write, task_review],
process=Process.sequential,
verbose=True
)
result = crew.kickoff()
print(result)
这里使用了 Process.sequential,即顺序流程。任务会按照列表顺序执行,后一个任务可以读取前一个任务的输出。如果后续任务没有通过 context 关联上游任务,CrewAI 默认不会自动传递所有历史信息,显式声明依赖能提高稳定性。
三、流程控制、上下文与工具集成
CrewAI 提供顺序流程和层级流程两种执行方式。顺序流程适合步骤明确的流水线,例如先检索、再撰写、最后审校。层级流程则适合需要统一调度或任务关系复杂的场景,它会把管理角色引入团队,由管理者智能体分配任务。对于大多数入门项目,顺序流程足够用,因为它的行为更容易预测和调试。
上下文传递是保证协作质量的关键。除了 context 参数,还可以使用 output_json 或 output_pydantic 约束任务输出为结构化数据。这样下游任务可以读取明确字段,而不是依赖自由文本。举例来说,研究任务可以输出 JSON 对象,包含 facts、examples 和 risks 三个字段,撰稿任务再根据这些字段组织内容。
工具集成让智能体不再只依赖模型内部知识。CrewAI 支持为 Agent 设置 tools 参数,传入搜索工具、文件读取工具或自定义 Python 函数。工具通常用 LangChain 的 tool 装饰器实现,这样在任务执行过程中,模型可以决定是否调用工具获取实时数据。下面是一个自定义工具示例,展示如何将网页搜索封装成可调用函数。
from crewai import Agent, Task, Crew, Process
from langchain.tools import tool
@tool("search_web")
def search_web(query: str) -> str:
"""根据关键词搜索并返回摘要信息。"""
# 这里接入真实搜索API,例如Serper或Bing API
return f"关于 {query} 的搜索结果摘要:CrewAI支持角色定义、任务编排和工具调用。"
researcher = Agent(
role="搜索研究员",
goal="使用工具获取主题相关信息,并整理成要点",
backstory="你优先使用外部工具获取最新资料,不依赖过时记忆。",
tools=[search_web],
verbose=True
)
task = Task(
description="搜索CrewAI框架的最新能力,并给出三点总结。",
expected_output="三点总结,每条不超过50字。",
agent=researcher
)
crew = Crew(
agents=[researcher],
tasks=[task],
process=Process.sequential,
verbose=True
)
result = crew.kickoff()
print(result)
需要特别留意的是,函数文档字符串必须写清楚工具用途,因为 CrewAI 会把它作为工具说明交给模型判断何时调用。同时,verbose 参数可以打开详细日志,帮助观察每个智能体接收到的提示词、思考过程和最终输出。在开发阶段建议开启,生产环境可以关闭以减少噪音。memory 参数用于开启跨任务记忆,cache 参数控制是否缓存相同任务结果,自动缓存能降低重复调用成本,但调试时最好关闭。
四、常见误区与进阶建议
初学时最容易出现的问题是角色定义过宽。比如把研究员的目标写成“帮我完成任务”,把撰稿人的目标写成“写点东西”,模型会失去明确方向。角色应当像招聘岗位一样具体:说明职责范围、产出标准、语言风格。另一个常见问题是任务描述与预期输出不一致,例如描述要求“写一篇分析文章”,但预期输出只写“一段话”,此时模型可能提前结束。两者需要匹配。
上下文传递不完整也会造成下游任务质量下降。如果撰稿任务没有通过 context 拿到研究结果,智能体可能凭空生成内容,尤其当它没有外部工具时。因此,只要任务之间有数据依赖,就应当显式声明。对于复杂结构,优先使用 JSON 输出,再让下游任务按字段读取,这比拼接长文本更可靠。
从架构角度看,CrewAI 更适合角色边界清晰、步骤可枚举的团队协作场景。如果任务需要高度动态的图结构、条件分支或人在回路审批,可以结合 LangGraph 的状态图能力;如果只是让多个智能体自由对话,AutoGen 的对话模式可能更直接。CrewAI 的优势在于把角色、任务和团队抽象得非常直观,能让初学者在十几分钟内搭起可运行原型。
最后,调试多智能体应用时不要只看最终输出。建议打开 verbose 观察每个智能体的输入和输出,确认提示词中没有角色串扰、任务遗漏或工具误调用。可以先从一个智能体和一个任务开始,跑通后再逐步增加角色和依赖,这样定位问题会容易得多。多智能体协作并不等于智能体越多越好,清晰的分工和明确的数据流才是团队稳定产出的关键。