Skip to content

CrewAI — Role-Based Multi-Agent Frameworks

CrewAI is an open-source Python framework for building multi-agent AI systems where specialised agents work together like a team. Each agent has a defined role, goal, and set of tools — and CrewAI handles the orchestration of how they communicate and hand off work.

The mental model: think of building a startup team. You have a researcher, a writer, a reviewer, and a publisher. Each has a specific job. The manager (CrewAI) coordinates them so each person does their part in the right order with the right information.

Terminal window
pip install crewai crewai-tools

An agent is an autonomous AI worker with a specific role:

from crewai import Agent
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")
researcher = Agent(
role="Senior Research Analyst",
goal="Find accurate, up-to-date information on AI topics",
backstory="""You are an expert AI researcher with 10 years of experience.
You excel at finding credible sources and synthesising complex information.""",
llm=llm,
verbose=True
)
writer = Agent(
role="Technical Content Writer",
goal="Write clear, engaging articles for a developer audience",
backstory="""You are a skilled technical writer who can explain complex AI concepts
in plain English without losing accuracy.""",
llm=llm,
verbose=True
)

A task defines what an agent should do:

from crewai import Task
research_task = Task(
description="""Research the topic: {topic}
Find the latest developments, key concepts, and practical applications.
Focus on information from the last 12 months.""",
expected_output="A structured summary with key findings, bullet points, and source references.",
agent=researcher
)
writing_task = Task(
description="""Using the research provided, write a 800-word article about {topic}.
Target audience: senior software developers.
Include: introduction, key concepts, code examples where relevant, conclusion.""",
expected_output="A complete, publication-ready article in markdown format.",
agent=writer,
context=[research_task] # writer receives researcher's output
)

The crew ties everything together:

from crewai import Crew, Process
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential, # or Process.hierarchical
verbose=True
)
result = crew.kickoff(inputs={"topic": "LangGraph multi-agent orchestration"})
print(result.raw)

Tasks run in order. Each task’s output feeds into the next:

Task 1 (Research) → Task 2 (Write) → Task 3 (Review) → Done
crew = Crew(
agents=[researcher, writer, reviewer],
tasks=[research_task, writing_task, review_task],
process=Process.sequential
)

A manager agent coordinates the crew, deciding what to do and when:

manager = Agent(
role="Content Director",
goal="Oversee article production and ensure quality",
backstory="Experienced content director who knows how to coordinate teams.",
llm=llm
)
crew = Crew(
agents=[researcher, writer, reviewer],
tasks=[research_task, writing_task, review_task],
process=Process.hierarchical,
manager_agent=manager
)

The manager decides which agent to call, in what order, and whether the output is good enough to proceed.


Agents become much more powerful with tools:

from crewai_tools import SerperDevTool, WebsiteSearchTool, FileWriterTool
search_tool = SerperDevTool() # Google search
web_tool = WebsiteSearchTool() # Scrape web pages
file_tool = FileWriterTool() # Write output to file
researcher = Agent(
role="Senior Research Analyst",
goal="Find accurate information using web search",
backstory="Expert researcher with access to the web.",
tools=[search_tool, web_tool],
llm=llm
)
writer = Agent(
role="Technical Writer",
goal="Write and save articles",
backstory="Skilled writer who saves work to files.",
tools=[file_tool],
llm=llm
)
from crewai.tools import BaseTool
from pydantic import BaseModel, Field
class JiraSearchInput(BaseModel):
project_key: str = Field(description="The Jira project key")
query: str = Field(description="Search query")
class JiraSearchTool(BaseTool):
name: str = "jira_search"
description: str = "Search Jira tickets in a project"
args_schema: type[BaseModel] = JiraSearchInput
def _run(self, project_key: str, query: str) -> str:
# Call Jira API
return f"Found tickets in {project_key} matching: {query}"
jira_tool = JiraSearchTool()

Practical Example: LinkedIn Article Pipeline

Section titled “Practical Example: LinkedIn Article Pipeline”

A crew that researches, writes, scores, rewrites, and publishes:

from crewai import Agent, Task, Crew, Process
# Agents
news_researcher = Agent(
role="AI News Researcher",
goal="Find the latest AI news, videos, and blog posts on the given topic",
tools=[search_tool, web_tool],
llm=llm
)
brainstormer = Agent(
role="Content Strategist",
goal="Generate compelling angles and outlines for LinkedIn articles",
llm=llm
)
article_writer = Agent(
role="LinkedIn Content Writer",
goal="Write engaging, professional articles optimised for LinkedIn",
llm=llm
)
scorer = Agent(
role="Content Quality Reviewer",
goal="Score articles on clarity, engagement, and professional value (1-10)",
llm=llm
)
# Tasks
research_task = Task(
description="Research '{topic}': find 5 recent news items, 3 blog posts, 2 videos.",
expected_output="Structured research summary with titles, URLs, and key points.",
agent=news_researcher
)
brainstorm_task = Task(
description="Using the research, generate 3 article angle options with outlines.",
expected_output="3 distinct angles with title, hook, and 5-point outline each.",
agent=brainstormer,
context=[research_task]
)
write_task = Task(
description="Write a full LinkedIn article (600-800 words) using the best angle.",
expected_output="Complete article with hook, body, CTA, and relevant hashtags.",
agent=article_writer,
context=[brainstorm_task]
)
score_task = Task(
description="""Score the article on: clarity (1-10), engagement (1-10), value (1-10).
If any score < 7, provide specific rewrite instructions.""",
expected_output="Scores + feedback. If all >= 7: 'APPROVED'. Otherwise: rewrite notes.",
agent=scorer,
context=[write_task]
)
# Run the crew
crew = Crew(
agents=[news_researcher, brainstormer, article_writer, scorer],
tasks=[research_task, brainstorm_task, write_task, score_task],
process=Process.sequential,
verbose=True
)
result = crew.kickoff(inputs={"topic": "Agentic AI in enterprise software development"})

CrewAI supports persistent memory so agents can remember across conversations:

crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
memory=True, # Enable crew-level memory
embedder={
"provider": "openai",
"config": { "model": "text-embedding-3-small" }
}
)

Memory types:

  • Short-term — current crew run context
  • Long-term — persisted to a local vector store, recalled in future runs
  • Entity memory — facts about specific entities the crew has encountered

CrewAILangGraph
Abstraction levelHigh — roles, tasks, crewsLow — nodes, edges, state
Learning curveShallow — intuitive APISteeper — graph thinking required
FlexibilityModerateVery high
Cycles/loopsLimitedFirst-class
Human-in-loopBasicFull interrupt() support
Best forRole-based agent teamsComplex stateful workflows

Use CrewAI when you want to quickly assemble a team of specialised agents for a document workflow (research → write → review).

Use LangGraph when you need fine-grained control over state, loops, branching, and human approval steps.