news 2026/9/3 3:09:59

CrewAI实战指南:从零搭建多智能体协作工作流

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CrewAI实战指南:从零搭建多智能体协作工作流

如果你最近在关注 AI Agent 方向,大概率会注意到一个现象:ChatGPT 这类单一大模型已经不能满足复杂任务的落地需求了。真正要做一份行业研究报告、一套竞品分析、一个自动化运营 SOP,如果只靠一次 Prompt,模型很快就会出现上下文丢失、步骤遗漏、结果深度不够的问题。于是,“多智能体系统”这个概念被推到了台前。

但说实话,多智能体这个概念在业界的讨论热度,远远超过了实际落地进度。原因很简单:大模型本身只是“大脑”,而多智能体系统要解决的是“多个大脑如何分工、如何协作、如何把任务跑完”的系统工程问题。很多人看完概念觉得懂了,一写代码就发现:智能体怎么定义、任务怎么拆分、角色之间怎么交接、失败怎么重试,全是难题。

这篇文章要写的 CrewAI,就是目前开源社区里把“多智能体协作”这个概念落地得比较完整的一套 Python 框架。它不要求你从零实现 Agent 调度逻辑,而是用类声明式的方式,把智能体、任务、流程、协作工具组装成一个可运行的 Crew(团队)。

文章的定位很明确:不堆概念,直接给你一条能跑通的主线——从 CrewAI 的核心设计讲起,到环境搭建、代码示例、运行验证、常见问题,最后给出工程落地建议。读完你应该能做到:自己定义一个多角色智能体团队,编排任务流程,跑出一个真实可用的自动化工作流。

1. 这篇文章真正要解决的问题

先花一点时间搞清楚:为什么在多智能体这个方向上,我们特别需要 CrewAI 这种框架?

如果你自己尝试过用 LangChain 或者直接调用 OpenAI SDK 写 Agent,你会发现真正的痛点不是让模型“变聪明”,而是把复杂任务结构化。比如要做一个企业舆情分析报告,任务天然包含以下环节:

  • 采集信息源;
  • 筛选高价值信息;
  • 判断情绪和风险等级;
  • 撰写分析正文;
  • 整理成固定格式的报告。

如果只让一个 Agent 完成全部工作,它既要会搜索、又要会写作、还要会判断,不仅系统 Prompt 会写得非常长,而且任何一个环节失败都会导致整条链路不可用。更麻烦的是,这种单体 Agent 出现错误时,你很难定位是采集的问题,还是判断逻辑的问题,还是生成格式的问题。

多智能体系统的核心价值,就是把这种“大而全”的任务,拆成多个“小而专”的角色任务。每个智能体只把自己负责的环节做到位,再通过流程机制实现任务上下文传递和结果汇总。

CrewAI 解决的问题,概括起来就是三件事:

  • 智能体定义:如何用清晰的角色(Role)、目标(Goal)和背景故事(Backstory)定义一个专职智能体。
  • 任务编排:如何把多个任务按顺序、按层级或者按事件驱动的方式串起来,形成完整工作流。
  • 可运行的自动化流程:如何让这套多智能体系统不仅存在于文档里,还能真正跑出结果,并接入大模型 API、外部工具和企业数据。

所以,这篇文章适合的读者有三类。第一类是刚开始了解 Agent 开发、想找一套能快速跑通的脚手架的人;第二类是已经用 LangChain 写过 Agent,但觉得直接编排多角色太痛苦的人;第三类是团队里要评估多智能体框架选型,需要看 CrewAI 到底能做什么、不能做什么的技术负责人。

一句话总结我的判断:CrewAI 不是让 AI 从“单打独斗”变成“一堆 Agent 聊天”,而是把多智能体协作变成了可配置、可复用、可维护的工程代码。这种变化才是它真正值得关注的原因。

2. CrewAI 核心概念与设计思想

CrewAI 之所以上手门槛比从零写调度器低,是因为它把多智能体系统中的几个高频抽象概念,直接做成了框架的基础组件。理解这几个概念,胜过背诵十篇 API 文档。

2.1 Crew、Agent、Task 是三大基础组件

CrewAI 的顶层抽象是 Crew(团队/剧组),它定义了一个多智能体组织,负责管理这个系统里有哪些智能体、要执行哪些任务、任务之间以什么方式流转。

Agent(智能体)是 Crew 里的执行单元。每个 Agent 是一个“带角色设定的大模型实例”,它拥有独立的角色、目标和背景信息。CrewAI 里的 Agent 还有一个重要特性:它可以配置工具(Tools),比如搜索、网页访问、自定义 Python 函数,这样它在执行任务时就有能力调用外部资源。

Task(任务)是分配给 Agent 的、明确要输出结果的工作单元。Task 包含任务描述、期望输出格式、负责任务的 Agent 等信息。多个 Task 之间允许有依赖关系,后置任务可以把前置任务的输出作为输入上下文。

下面用一个表格把这几个概念对照一下:

概念通俗理解解决的核心问题CrewAI 中的关键配置
Agent团队里的一个“员工”每个角色只做专业的事role、goal、backstory、llm、tools
Task安排给员工的一条工作指令工作边界和输出标准description、expected_output、agent
Crew一条完整的业务流水线把角色和任务组装成可运行流程agents、tasks、process
Process流水线的执行方式决定任务串行还是分级管理sequential、hierarchical
Flow基于事件驱动的工作流控制器更灵活的编排与状态管理@start、@listen、状态对象

只看表格可能还不够“切肤”。要理解这些概念,最好的方式是把 CrewAI 比作一个剧组:

  • 导演(Flow 或 Hierarchical Process 中的 Manager)不亲自演戏,但决定哪个演员在什么节点上场。
  • 编剧和摄影师(Agent)是不同的执行单元,编剧写脚本,摄影师拍画面。
  • 每个拍摄任务(Task)都有明确交付物。
  • 整部电影(Crew)是以上所有元素的集合。

当然,这个类比只是为了帮新手建立心智模型。真正写代码时,Agent 不会像人一样“商量”着干活,它靠的是结构化 Prompt、工具调用和任务上下文传递。

2.2 Process 决定协作是顺序还是分级

多智能体系统里最容易让人困惑的一点是:多个智能体到底怎么协作?是我命令你、你命令他,还是大家各干各的,最后拼在一起?

CrewAI 提供两种内置 Process:

Sequential Process(顺序流程)。所有任务按声明顺序依次执行,Agent 像流水线工人一样逐个处理自己负责的环节。优点是好理解、好排错、成本和延迟可控。适合上下文强依赖、不适合并行的任务链。比如“先生成大纲,再根据大纲写正文,再基于正文配摘要”。

Hierarchical Process(层级流程)。Crew 里会安排一个 Manager Agent 或指定 manager_llm,由它负责任务规划、分配、审查和交接,普通 Task 不预先绑定 Agent,而是由 Manager 动态决定。优点是有全局统筹,适合任务拆解不固定、依赖关系相对动态的场景。缺点是多一次管理调度,会引入额外的大模型调用开销和不确定性。

社区里经常讨论“多智能体的四种交互模式”,典型分类包括顺序链、并行分组、主从委派、事件驱动协作等。对应到 CrewAI 里,顺序模式对应 Sequential Process,主从委派对应 Hierarchical Process,事件驱动模式对应基于 Flow 的编排方式,并行分组可以通过多个异步 Task 来组合实现。换句话说,你不需要把这些模式当作孤立术语,它们的本质是任务关系图的结构差异

2.3 Flow:比 Process 更灵活的工作流层

Process 解决了一个 Crew 内部任务的线性和层级调度问题,但真实业务往往没有这么规整。你会发现很多自动化流程是循环的、条件是跳转的、不同 Crew 之间需要嵌套调用。

CrewAI 的 Flow 组件就是为这种场景设计的。Flow 允许你定义一个带状态的数据类,通过@start()装饰器标注流程的起点,通过@listen()装饰器监听某个方法完成后触发下一个动作。这种事件驱动机制可以处理:

  • 条件分流:根据某个步骤输出,决定走 A 分支还是 B 分支;
  • 流程合并:几个独立结果汇聚到一个最终总结步骤;
  • 父子流程:一个 Flow 内部调用另一个已经定义好的 Crew。

如果你之前用过自动化测试框架或者数据管道调度框架,Flow 的概念不会陌生。它本质上就是用装饰器和状态对象来描述有向无环图(DAG)

2.4 一个容易被忽略的设计:Agent 的 Post-Tools

很多新手用 CrewAI 时会有一个误区:Agent 收到任务后,会自动“思考”然后调用工具。实际上,Agent 是否调用工具、调用什么工具,取决于你在创建 Agent 时传给它的tools参数,以及任务的描述是否明确提示它需要使用工具。

CrewAI 官方还有一个Agentpost_tools参数策略,就是让 Agent 在正式回答前先调用一组工具来增强信息,避免“不知道答案也硬编”。这里不展开细节,但你要记住一个原则:在这类多智能体系统里,工具的挂载位置会直接影响任务质量——工具挂得太少,Agent 只能靠模型幻觉补充信息;工具挂得太多,Agent 容易在无关工具上浪费 Token 和时间。

3. 适用场景与框架选型:CrewAI 到底适合什么

多智能体框架目前不是一个赢者通吃的赛道。选型错误,往往不是框架的问题,而是需求和框架的匹配出了问题。因此在写代码之前,值得先把选型问题理清楚。

先看 LangChain。LangChain 是 Agent 开发的“瑞士军刀”,它提供了组件化的工具链和大量第三方集成,但它本身不定义任务协作模型。如果你想基于 LangChain 写多智能体协作,自己需要设计 Agent 之间的通信协议、记忆共享、任务分配机制,实际上是从零搭一套框架。

再看 AutoGen 或 Semantic Kernel。这类框架擅长对话驱动的多智能体交互,多个 Agent 通过消息传递完成合作。这在研究、对话式推理场景里很有优势,但业务落地上,Agent 之间自由对话往往意味着不确定性高、调试困难,输出格式也较难约束。

CrewAI 的定位恰好介于两者之间。它更接近“结构化团队协作”:用 Crew、Task、Process 这种有边界的模型,把任务编排固化成代码。你定义角色,定义任务,框架帮你执行;任务结果结构化,可控性强,容易复用。

对比维度LangChain AgentAutoGenCrewAI
核心抽象Chain + Agent + ToolConversable Agent + 对话流Crew + Agent + Task + Process
多智能体协作方式需要自行设计对话驱动声明 + 流程驱动
任务结果可控性中等偏低较高
上手难度中等偏高较低
适合业务场景工具链复杂、组件化集成研究探索、开放对话企业流程自动化、内容生产流水线

那 CrewAI 最适合哪些场景?根据实际项目经验,我可以给出几个比较明确的场景清单。

第一个是内容与研究报告生产流水线。比如收集资料、整理观点、撰写初稿、校对优化,如果把这几个环节拆成专职 Agent,配合固定的任务输出格式,产出质量会明显高于单 Agent 长文本生成。

第二个是企业业务运营自动化。例如客服工单分类、竞品监控日报、销售线索初筛。这类任务有清晰输入输出,有固定流程,非常适合用 Crew 封装成可重复调用的服务。

第三个是多工具编排场景。CrewAI Agent 支持挂载工具,你能把搜索工具、数据库查询工具、内部 API 工具挂到不同 Agent 上,让它们各司其职。

不太适合 CrewAI 的场景也有一个典型:高实时性、强交互的对话助手。CrewAI 本身不是对话状态管理框架,它有 Memory 和短期上下文设计,但面向用户的多轮对话系统还是应该用专门对话 Agent 框架来做,把 CrewAI 作为服务端内部任务编排组件。换言之,不要让用户直接和 CrewAI 的 Agent 自由对话,而是通过 API 去触发一个明确的 Crew 工作流。

4. 环境准备与工程目录设计

在动手写代码之前,先把运行环境说清楚。

CrewAI 是一个基于 Python 的框架,底层封装了 LangChain 的若干能力,同时支持 OpenAI、Anthropic、Gemini、Ollama 等不同模型来源。我建议你在一个干净的环境中安装,避免跟已有 LangChain 项目里的依赖发生版本冲突。

建议环境如下:

  • Python 3.10 或更高版本(推荐 3.10 到 3.12,具体以官方当前支持版本为准);
  • pip 包管理器;
  • 一个可选用的虚拟环境工具,比如 venv 或 conda;
  • 准备一个大模型 API Key。如果你用 OpenAI 兼容接口,可以配置OPENAI_API_KEY环境变量。

安装 CrewAI 的命令很简单:

pip install crewai

如果计划让 Agent 使用浏览器搜索、网页内容读取等常用工具,可以一起安装工具包:

pip install 'crewai[tools]'

CrewAI 生态迭代速度较快,重要版本的 API 可能有调整,因此creai的具体版本号建议以官方 PyPI 页面为准。本文的代码示例以当前主流的类声明式用法为主。安装完成后,可以先做一个最小验证:

python -c "import crewai; print(crewai.__version__)"

如果这条命令能正常输出版本号,说明框架安装没问题。

工程目录方面,如果你只是学习跑通,建议先建一个单文件脚本;如果是正式业务项目,我更推荐这样的目录结构:

project/ ├── agents/ │ └── researcher_agent.py # 智能体定义 ├── tasks/ │ └── research_task.py # 任务定义 ├── crews/ │ ├── research_crew.py # 组装 Crew │ └── flow.py # 基于 Flow 的工作流 ├── tools/ │ ├── search_tool.py │ └── custom_tool.py ├── config/ │ └── llm_config.py # 模型统一配置 ├── output/ │ └── reports/ ├── main.py # 入口 └── requirements.txt

这种拆分方式的好处是:智能体、任务、流程互相解耦。一个 Agent 可以参与不同 Task;一个 Task 也可以在不同 Crew 里复用;将来接入 Web 服务时,只需要在 API 层调用Crew.kickoff(),整个业务能力就被封装成函数了。

实际项目里,我更建议把智能体定义和任务描述放到配置文件里管理,代码里只负责注册和组装。CrewAI 也支持 YAML 配置方式,对团队协作和后续维护更友好。不过本文为了减少认知负担,直接用 Python 代码描述。

5. CrewAI 完整示例:从最小 Crew 到事件驱动 Flow

下面开始进入实操环节。我们从最简单的一 Crew 一 Agent 开始,逐步增加角色和任务,最后用一个 Flow 示例演示事件驱动工作流。

5.1 最小示例:研究助手 Crew

先跑通最小环境。创建一个first_crew.py文件,代码如下:

# 文件路径:first_crew.py from crewai import Agent, Task, Crew, Process # 1. 定义智能体 researcher = Agent( role="高级技术研究员", goal="围绕用户给定主题,调研技术原理并形成结构化摘要", backstory=( "你是一位经验丰富的技术研究员," "擅长快速从资料中提炼关键事实," "不喜欢无依据的推测。" ), verbose=True ) # 2. 定义任务 research_task = Task( description="调研 CrewAI 的核心概念,输出一份面向开发者的摘要。", expected_output=( "一份包含核心概念、主要用途、适用场景的 Markdown 列表," "每项不超过 50 字。" ), agent=researcher, ) # 3. 组装 Crew crew = Crew( agents=[researcher], tasks=[research_task], process=Process.sequential, verbose=True, ) if __name__ == "__main__": result = crew.kickoff() print("=== 最终输出 ===") print(result)

这里需要解释几个关键参数。

Agent里的role设置了智能体的角色身份,goal设定了总体目标,backstory是给大模型的背景补全信息,这三者拼在一起,实际构成了 Agent 系统提示词的核心。verbose=True表示在命令行输出任务执行的中间过程,排错时非常有用。

Task里的description是任务内容,expected_output是期望的输出结构和风格。多智能体系统里,任务描述写得好不好,决定了大模型和下游协作者能不能理解结果。这块不要偷懒。

Crew接收agents列表和tasks列表,process=Process.sequential表示顺序执行。kickoff()是 Crew 的入口函数,调用后框架会自动拉起整个流程。

运行方式:

python first_crew.py

如果配置好了大模型 API,你会看到控制台依次输出 Agent 的思考步骤、工具调用和最终结果。kickoff()返回的对象是 CrewOutput,直接print(result)可以看见任务输出正文。

5.2 顺序编排:内容生产流水线

下面把场景升级:用三个 Agent 组成一条内容生产流水线,分工做“选题策划 → 初稿撰写 → 校对润色”。

# 文件路径:content_crew.py from crewai import Agent, Task, Crew, Process planner = Agent( role="内容策划编辑", goal="根据主题规划文章大纲和核心观点", backstory="你是一位资深内容策划,善于把复杂技术问题拆解成清晰的文章结构。", ) writer = Agent( role="技术文章作者", goal="根据大纲撰写技术教程正文", backstory="你是一位有一线开发经验的技术作者,擅长用示例和步骤讲清楚概念。", ) reviewer = Agent( role="质量审核编辑", goal="从准确性、结构完整性和表达清晰度方面审核文章,输出修改建议", backstory="你是一位严格的编辑,重点检查文章是否存在术语误用、逻辑断裂和缺少示例。", ) plan_task = Task( description=( "主题:如何使用 Python 实现定时任务。" "请输出文章大纲,包括引言、环境准备、核心示例、常见问题四部分。" ), expected_output="结构化的 Markdown 大纲,每个章节下写清楚要点。", agent=planner, ) write_task = Task( description=( "基于以下大纲撰写技术教程正文:\n" "{plan_output}\n" "要求每段给出可运行的代码示例,语言风格平实、专业。" ), expected_output="完整的 Markdown 技术文章正文,包含代码块。", agent=writer, context=[plan_task] ) review_task = Task( description=( "审核以下技术文章,检查内容准确性和结构:\n" "{write_output}\n" "输出具体修改建议,不要直接重写全文。" ), expected_output="按严重程度排序的修改建议列表。", agent=reviewer, context=[write_task] ) content_crew = Crew( agents=[planner, writer, reviewer], tasks=[plan_task, write_task, review_task], process=Process.sequential, verbose=True, ) if __name__ == "__main__": result = content_crew.kickoff() print("=== 审核建议 ===") print(result)

这个示例里有几个关键点值得展开。

第一个是context参数。write_task声明了context=[plan_task],意思是它执行时会把plan_task的输出作为上下文传入。review_task同理依赖write_task的输出。相比直接使用{plan_output}这种变量占位,context更明确地建立了任务级依赖关系。实际上,CrewAI 在 Task 执行时会把 context 中任务的输出拼到当前任务描述后面,因此你可以在任务描述里用大括号引用。如果任务之间没有显式依赖,就不要乱加context,减少不必要的 Token 消耗。

第二个是任务描述里的占位符写法。{plan_output}是引用前序任务输出的快捷方式。用不熟悉的开发者很容易忽略这一点,导致下游任务拿不到上游结果。

第三点是Process.sequential只负责按列表顺序执行任务,它不代表“每个 Agent 都只执行一次任务”。框架内部会协调上下文,你只需要定义清楚哪些角色、哪些任务、哪些依赖。

运行内容生产 Crew 后,你会看到作者 Agent 产出初稿,审核 Agent 对初稿给出意见。如果你希望把审核意见直接应用到文章里,只需要再增加一个编辑 Agent 和对应 Task,承接修改任务即可。这就是流水线编排的威力:每增加一个环节,只是新增一个角色和一条任务

5.3 层级流程:Manager 统筹模式

业务场景里还有一种更常见的情况:任务不是一开始就能写死成固定步骤的,需要根据实际内容动态拆解。比如“调研某技术方向的趋势并输出报告”,具体要访问哪些网站、要看哪些材料,不应该是我们预先硬编码的,而应该由一个统管 Agent 来判断。

这种场景适合用 Hierarchical Process。

# 文件路径:hierarchical_crew.py from crewai import Agent, Task, Crew, Process researcher = Agent( role="前沿技术观察员", goal="搜集指定技术方向的最新动态与发展趋势", backstory="你长期跟踪 AI 工程化领域动态,善于发现关键信号。", ) analyst = Agent( role="商业技术分析师", goal="对收集到的信息进行结构化分析并形成判断", backstory="你擅长从分散信息中归纳趋势,给技术决策者提供可执行的结论。", ) report_task = Task( description="调研多智能体编排框架的行业采用趋势,并输出一份分析简报。", expected_output="包含关键趋势、代表项目、落地建议的 Markdown 简报。", ) hierarchical_crew = Crew( agents=[researcher, analyst], tasks=[report_task], process=Process.hierarchical, manager_llm=None, # 不显式指定时,会复用默认 LLM manager_agent=None, # 也可以指定一个 Agent 作为 Manager verbose=True, ) if __name__ == "__main__": result = hierarchical_crew.kickoff() print("=== 层级流程输出 ===") print(result)

注意,在层级流程的写法里,report_task没有绑定agent参数。这是因为在 Hierarchical Process 中,负责任务分配的 Manager 会动态决定把 Task 交给哪个 Agent 执行,不需要预先绑定。你需要提供的是 Agent 池,Manager 从池中选择合适的执行者。

如果你希望 Manager 既当裁判又当运动员,可以显式传入一个manager_agent;如果只告诉 Crew 用哪个模型做管理,就传manager_llm。二者选择其一即可。实际生产环境中,为避免 Manager 模型和执行 Agent 模型混用导致成本难以核算,更推荐用manager_llm指定一个更高配置的模型,执行 Agent 使用相对轻量的模型。

用层级流程时要注意 Token 消耗。Manager 的每一步规划、审查、总结都会调用大模型。任务一多,成本会显著上升。如果业务步骤固定、拆解明确,优先使用顺序流程,层级流程作为兜底和补充。

5.4 自定义工具:让 Agent 不再只靠记忆

多智能体 Agent 真正落地,一般离不开工具调用能力。一个只靠模型内部知识回答问题的 Agent,本质上还是一个高级聊天机器人;只有让它可以查询数据库、调内部接口、搜索网页,它才算进入工作流。

CrewAI 的 Agent 通过tools参数挂载工具,工具可以是内置的serper_dev_toolscrape_website_tool,也可以是自己写的一个普通 Python 函数,再包装成tool装饰器。

演示一个自定义工具。假设我们需要让 Agent 查询本地配置好的知识库 API:

# 文件路径:knowledge_tool.py from crewai_tools import tool @tool("知识库搜索") def search_knowledge_base(query: str) -> str: """ 在内部知识库中搜索与 query 相关的知识内容。 如果未找到,返回 'NO_RESULT'。 """ # 实际项目中,这里会调用内部知识库 API 或向量数据库 # 这里只做演示,使用一个简单映射表 knowledge = { "部署": "生产环境部署前必须备份数据库,并执行回归测试。", "回滚": "回滚操作优先使用上一稳定版本镜像,并观察监控指标。", } for key, value in knowledge.items(): if key in query: return value return "NO_RESULT"

然后挂载到 Agent 上:

# 文件路径:tool_crew.py from crewai import Agent, Task, Crew, Process from knowledge_tool import search_knowledge_base ops_agent = Agent( role="运维知识顾问", goal="回答基于内部知识库的运维问题", backstory="你只能依据内部知识库回答,不要凭空补充没有来源的操作步骤。", tools=[search_knowledge_base], ) answer_task = Task( description="请回答:生产环境部署时的注意事项有哪些?", expected_output="一段不超过 100 字的安全操作建议。", agent=ops_agent, ) tool_crew = Crew( agents=[ops_agent], tasks=[answer_task], verbose=True, ) if __name__ == "__main__": result = tool_crew.kickoff() print(result)

这里一个关键细节是tool装饰器里的函数文档字符串。大模型并不是靠你的“函数名”理解工具的,它靠的是函数签名、参数说明、文档字符串综合判断何时调用该工具。因此,工具描述要写清楚“什么场景用、输入什么、返回什么、找不到时返回什么”。一个含糊的工具描述很可能让 Agent 在无关请求上频繁调用工具,消耗大量 Token。

这里也回应一个网络热词:很多人问“如何把小龙虾或者爱马仕集成到多智能体系统中”,其实,当一个 Agent 能通过 MCP(Model Context Protocol)等协议挂载外部工具时,重点不是对象本身叫什么名字,而是它暴露了什么工具接口、返回什么格式的数据。真正值得研究的是 MCP 服务器如何把业务数据抽象成 Agent 可调用的工具。

5.5 事件驱动工作流:基于 Flow 实现动态编排

前几个示例里的 Process 都是把一个 Crew 内部的任务按固定方式跑完。如果业务包含多个 Crew、条件分支或循环处理,就要用 Flow。

下面这段代码演示一个“热点内容自动加工”流程:收到主题后,先生成研究摘要;如果摘要长度不够,走增强补充路径;最后汇总输出。

# 文件路径:research_flow.py from typing import Any from pydantic import BaseModel from crewai.flow import Flow, listen, start from crewai import Agent, Task, Crew, Process class ResearchState(BaseModel): topic: str = "人工智能编排框架" raw_summary: str = "" final_summary: str = "" need_expand: bool = False class ResearchFlow(Flow[ResearchState]): @start() def initiate_research(self): # 首轮 Agent 执行:快速生成摘要 agent = Agent( role="行业研究员", goal="快速生成指定主题的研究摘要", backstory="你擅长快速判断主题的核心脉络。", ) task = Task( description=f"围绕主题《{self.state.topic}》生成 150 字以内摘要。", expected_output="一段简洁摘要。", agent=agent, ) crew = Crew(agents=[agent], tasks=[task], process=Process.sequential) self.state.raw_summary = crew.kickoff().raw # 判断是否需要扩展:比如摘要是否过短 self.state.need_expand = len(self.state.raw_summary) < 50 @listen(initiate_research) def expand_if_needed(self): if not self.state.need_expand: return # 第二轮覆盖:针对缺失细节做补充 agent = Agent( role="细节补充编辑", goal="对短摘要进行事实扩充", backstory="你是严谨的编辑,补充内容必须与摘要主题一致。", ) task = Task( description=f"基于摘要《{self.state.raw_summary}》扩展成 300 字左右的完整段落。", expected_output="一段内容完整、信息密度高的文字。", agent=agent, ) crew = Crew(agents=[agent], tasks=[task], process=Process.sequential) self.state.final_summary = crew.kickoff().raw @listen(expand_if_needed) def finalize(self, output: Any): # 如果没有经过扩展,final_summary 为空,这里兜底赋值 if not self.state.final_summary: self.state.final_summary = self.state.raw_summary print("=== 最终研究结果 ===") print(self.state.final_summary) if __name__ == "__main__": flow = ResearchFlow() flow.kickoff()

这段代码里,Flow 的用法主要通过装饰器和状态对象完成:

  • 继承Flow[ResearchState]ResearchState继承了pydantic.BaseModel,用来定义整个 Flow 运行期间的状态字段。
  • @start()标记的initiate_research是入口方法,任何流程只能有一个或多个入口,它们是 Flow 的开始。
  • @listen(initiate_research)表示监听某个方法执行完后的结果。只有前一个方法执行成功,被监听的方法才会执行。
  • 状态对象self.state负责在多个方法之间传递数据。这样一来,MCP 调用、Crew 执行、分支判断等都变成了方法之间的数据流动,整体更接近传统后端工程师熟悉的 Service 代码。

Flow 是 CrewAI 新版本里力推的编排层,但不是说每个项目都必须用它。如果是固定顺序的 3 到 5 个步骤,直接用Crew.kickoff()就够了;如果流程里有分支、循环、嵌套多个 Crew,建议升级到 Flow。

6. 运行验证与判断标准

跑通代码只是第一步。真正需要注意的是,你怎么判断多智能体系统的运行结果是“成功”的。

6.1 命令行运行观察什么

verbose=True时,CrewAI 会在控制台打印每个 Agent 的执行过程。不同 Agent 完成任务后,你会看到类似这样的输出结构:

  • 任务开始提示:Agent 正在处理的任务描述;
  • 思考过程:Agent 如何理解任务;
  • 工具调用与观察结果:如果调用了工具,会显示工具输入和返回值;
  • 任务最终输出:Agent 的最终回答。

如果某个环节的输出明显不符合任务描述中的要求,比如“本应输出 Markdown 列表,实际输出了纯文本”,这就说明任务描述不够严格。所有任务描述都必须显式声明 expected_output,否则大模型不知道交付标准,结果会非常不稳定。

6.2 结果判断的三种方式

第一种是人工阅读。适合调研报告、内容生产,判断标准是信息准确、逻辑清晰、没有幻觉。

第二种是结构化字段校验。适合数据抽取、分类、工单处理。可以把Task配置output_pydanticoutput_json,让 Agent 输出 JSON 格式,然后在Crew.kickoff()返回结果中用 Pydantic 模型校验字段完整性和类型。

第三种是外部断言。适合自动化任务,比如 Agent 判断“某事件风险等级为高危”,下游系统再拿着这个结论触发不同告警,通过业务规则确保输出被正确消费。

6.3 第一优先级看的失败点

如果运行失败,不要急着改 Prompt。先按以下顺序排查:

  • 看 API Key 是否配置、是否欠费或限流。这是大多数第一次运行失败的根因。
  • 看依赖版本。CrewAI 与 LangChain 生态版本耦合较紧,升级某个包可能导致内部接口不兼容。
  • 看任务之间的上下文变量名是否正确。占位符写错不会直接报错,但会输出原始字符串到下游。
  • verbose日志里 Agent 最后执行到哪个节点。如果某个 Agent 从头到尾没有输出,大概率是它的任务描述没有进到 Agent 的执行上下文。

7. CrewAI 常见问题与排查思路

我整理了多智能体开发过程中出现频率最高的几个问题。这张表可以直接作为你排错时的检查单。

问题现象可能原因排查方式解决方案
第一次运行报错 401/429API Key 错误、额度不足或触发限流单独调用模型 SDK 验证 Key;检查账号余额更新 Key;提高限流阈值或切换模型供应商
Agent 没有调用工具工具描述不清晰或任务描述未提示工具查看 verbose 日志中 Agent 是否“考虑”过工具调用的可能性优化工具描述;在任务描述里明确“允许使用知识库搜索”
流程中途报错“Could not parse LLM output”大模型返回内容不满足 JSON、代码块等结构化要求查看报错前后 LLM 原文;确认是否超过上下文长度缩小任务粒度;配置output_jsonoutput_pydantic;更换更强模型
下游任务引用了空上下文context 任务未执行,或任务描述中变量名写错先独立运行上游任务,确认输出非空;检查引用变量名检查 Task 列表顺序和 context 关系
任务结果很好,但耗时太长/费用过高任务链过长、层级 Manager 反复调度、Agent 反复重试在 verbose 日志中统计每个环节步数;查看 API 用量面板减少 Agent 数量;用顺序流程替代层级流程;降低重试次数
不同 Agent 之间格式不统一每个 Task 都未规定 expected_output查看多个 Task 的返回结果在 expected_output 中规定 Markdown/JSON/列表等格式
Flow 中@listen方法不执行监听的方法名写错,或监听方法抛异常被吞掉检查装饰器中的函数引用是否与实际情况一致;添加 try/except 打印异常修正监听参数;对异常做显式捕获
生产环境频繁变更导致流程不可用模型版本、提示词、Agent 配置没有版本管理检查是否有配置文件和流程代码的版本标签将 Agent/Task 配置纳入 Git;对 Prompt 变更做回归测试

这里单独强调两个新手最容易出的问题。

第一个是任务越写越大。很多人觉得一个 Agent 一次做多个步骤能省钱,实际结果往往相反——大模型在长任务里的注意力和指令遵循能力会下降,一步错步步错。更合理的拆法是一个 Agent 只完成“一个思维动作”:检索就检索,分析就分析,写就写,审就审。

第二个是没有给 Agent 定义清晰的“不做什么”。一个 Agent 的 backstory 里只写了“你擅长写文章”,它就可能在需要调用工具时选择自己“编内容”。所以在 backstory 中要明确加一句边界,比如“你只能依据资料输出,不臆造事实”“如果缺少必要信息,明确说明缺少哪些信息”。

8. 多智能体系统开发最佳实践与工程建议

从“代码能跑”到“系统能上线”,中间还差着一整套工程化约束。下面是我认为在多智能体系统开发中比较重要的几条建议。

8.1 为任务设计明确的外部上下文边界

多智能体系统稳定性的最大隐患是上下文污染。当 Agent 数量变多、任务链变长,如果一个早期任务的输出含错误信息,后续 Agent 可能会在错误前提上继续生成,而且错误会被逐步放大。

因此,不要把所有历史结果都传给下游。每个 Task 的 description 只保留完成任务所需的关键上下文即可。必要时,可以在任务间加入“信息抽取”环节,让一个专门 Agent 从上游长文本中抽取出精炼的结构化信息,再传给下游。这会让 Token 成本更可控,也会显著提高结果稳定性。

8.2 用最小授权和沙箱隔离工具权限

如果你给 Agent 挂载了能执行代码、访问数据库或调用内部 API 的工具,必须遵循最小权限原则。一个做内容分类的 Agent 不需要删除数据库的权限;一个做数据查询的 Agent 不应获得生产环境的写权限,默认只读。

工具调用应该有三层护栏:第一层是在代码层做好参数校验和权限校验;第二层是在工具描述中明确边界;第三层是核心操作前加入人工审批或条件约束。

8.3 日志、追踪和评估是生产上线的前提

传统的单元测试很难覆盖自然语言输出的不确定性。多智能体项目上线前,需要至少做到:

  • 每个任务的输入、输出、Token 用量、延迟都记录到日志里;
  • 对结果做结构化评估,例如 JSON 字段校验、关键词规则、核心指标是否出现;
  • 准备一组典型用例作为回归集,修改 Prompt 或任务步骤后,用同一组用例重新跑一遍;
  • 数据敏感时做脱敏后再记录日志。

8.4 Prompt 和配置要纳入版本管理

多智能体系统的核心其实是提示词工程和任务编排。Agent 的 role、goal、backstory、Task 的 description,本质上都是代码的一部分,需要走 Git 管理。实际操作中,可以把 Agent 和 Task 配置抽成 YAML 文件,再通过 CrewAI 的配置加载机制读取,避免把大量自然语言配置散落在 Python 类的文件里。

8.5 固定模型版本和 Provider 配置

同一个 Prompt 在不同模型上的表现差异很大。团队在开发阶段如果用高配模型验证效果,但生产环境为了省钱换了小模型,很可能出现规则不稳定的现象。更稳妥的做法是:在配置中心统一管理模型选择,评估阶段固定一组模型,输出结果全部保留对比记录,生产切换模型时必须做回归。

8.6 控制并行度和异步任务粒度

CrewAI 支持任务异步执行。当多个相互独立的任务存在时,可以用async_execution=True让它们在同一个 Crew 内并行执行,减少总耗时。但并行并不是越多越好:并行度太高,短时间内的 Token 消耗会猛增;同一个模型供应商的限流也会导致大面积失败。

建议从 2 到 3 个并行任务开始,观察 API 每分钟请求数和 Token 消耗,再逐步调高。

9. 总结与后续学习方向

回到这篇文章开头提出的判断:CrewAI 的真正价值,是把多智能体系统从“研究玩具”推进到“工程化任务编排工具”的位置。它用 Crew、Agent、Task、Process、Flow 这几个清晰的概念,让开发者能用声明式代码搭建一条可运行的自动化工作流。从实际项目经验来看,这不只是省掉了一部分调度代码,更是改变了多智能体系统的维护方式——你不再需要读完几千行调度逻辑才能理解系统在干什么,看配置就能知道哪些角色、按什么顺序、完成哪些任务。

如果你是第一次接触 CrewAI,下一步可以按这个路径实践:

-先复现第 5.1 节的最小示例,跑通环境;

  • 把第 5.2 节的内容生产流水线改成你自己的业务场景;
  • 找一个小型工具,按第 5.4 节的方式把它封装成 Agent 工具;
  • 如果流程进入分支和循环,再开始用 Flow。

值得继续深入研究的方向有三个:一是 CrewAI 与 MCP 协议的集成方式,这决定 Agent 能否接入企业内外部丰富的工具生态;二是多智能体系统的评测体系,因为它直接影响你能不能把系统从开发环境稳定迁移到生产环境;三是记忆机制的设计,什么时候需要短期记忆、什么时候用长期记忆、什么时候干脆不要记忆,需要基于业务做取舍。

建议你把这篇文章收藏下来,作为一个从零搭建多智能体系统的索引。遇到具体问题,比如模型调用失败、任务上下文丢失、Agent 输出格式不对,优先查第 7 节的排查表,再回来看对应章节的示例代码。多智能体开发是一条需要反复调试的路,但只要你把基本概念和最小示例跑通了,往后加角色、加任务、加工具,都只是在这个框架里做增量扩展而已。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 3:07:56

Agent记忆系统设计:从上下文到长线协作的工程实践

如果你的 Agent 连续聊了十几轮还能记住用户一开始给的偏好&#xff0c;你可能会觉得它“挺聪明”。但如果第二天再打开同一个 Agent&#xff0c;它把昨天的项目背景、约定好的命名规则、已经排查过的坑全部忘光&#xff0c;你会立刻意识到&#xff1a;这根本不是聪明与否的问题…

作者头像 李华
网站建设 2026/9/3 3:06:49

Codex 编程智能体实战指南:从安装部署到 API 接入与报错排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/3 3:03:28

2026 Linux高并发全链路优化:从C10K到C10M单机千万并发落地方案

Linux单机高并发瓶颈从未是硬件资源&#xff0c;而是IO模型、系统调度、内核参数、协议栈架构四层软件约束。从C10K&#xff08;万级并发&#xff09;、C1000K&#xff08;百万级并发&#xff09;到C10M&#xff08;千万级并发&#xff09;的技术迭代&#xff0c;本质是逐步破除…

作者头像 李华
网站建设 2026/9/3 3:00:49

基于Spring Boot的地磅全自动控制系统设计与实现

简介&#xff1a;面向Java全栈或工业自动化系统学习者的炼糖厂地磅全自动控制系统完整项目&#xff0c;采用SpringBootMyBatisVueRedis技术栈&#xff0c;涵盖厂房设备、员工、公告、设备维护、薪酬、值班及设备控制等核心业务模块。资源共385个文件&#xff0c;打包13.37MB&am…

作者头像 李华
网站建设 2026/9/3 3:00:07

CM0304神阵解密:BT442与NB433的底层逻辑与实战设置

简介&#xff1a;面向《足球经理2003/2004》&#xff08;CM0304&#xff09;玩家的战术阵型资源包&#xff0c;围绕BT442与NB433两套经典阵型展开&#xff0c;适合需要快速调整打法、研究攻防平衡的球迷玩家。BT442以中场厚度和双翼卫驱动进攻为核心&#xff0c;适合强调控制与…

作者头像 李华
网站建设 2026/9/3 2:58:42

STM32F407移植FreeRTOS与Modbus RTU从站:RS485通信稳定实战

简介&#xff1a;面向STM32开发者的Modbus从机通信与FreeRTOS集成工程资源。该工程基于STM32F407的HAL库&#xff0c;整合FreeModbus协议栈、RS485物理层通信与FreeRTOS实时系统&#xff0c;可应用于工业设备联网、数据采集与多任务控制等场景。压缩包整体约17.19MB&#xff0c…

作者头像 李华