Single AI agents hit a ceiling fast. They hallucinate, lose context, and struggle with complex workflows that require different types of expertise. Multi-agent systems solve this by letting specialized agents collaborate — each focused on what it does best.

CrewAI

CrewAI is a Python framework that makes building these systems straightforward. Instead of wrestling with low-level orchestration, you define agents with roles, give them tasks, and let the framework handle the coordination.

In this tutorial, you will build a research-and-writing crew: one agent researches a topic, another writes content based on that research. By the end, you will have a working system you can extend for your own use cases.

Prerequisites

Before starting, make sure you have:

  • Python 3.10 or higher installed
  • An OpenAI API key (or any LLM provider supported by CrewAI)
  • Basic familiarity with Python classes and functions

Step 1: Install CrewAI and Set Up Your Project

Create a new project directory and install the framework:

mkdir my-crew && cd my-crew
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install crewai crewai-tools

Set your API key as an environment variable:

export OPENAI_API_KEY="your-key-here"

Alternatively, create a .env file in your project root:

OPENAI_API_KEY=your-key-here

Step 2: Define Your Agents

Agents in CrewAI have three core attributes: a role (what they are), a goal (what they try to achieve), and a backstory (context that shapes their behavior).

Create a file called crew.py:

from crewai import Agent, Task, Crew, Process
 
researcher = Agent(
    role="Senior Research Analyst",
    goal="Find comprehensive, accurate information on the given topic",
    backstory=(
        "You are an experienced research analyst who excels at "
        "finding reliable sources, identifying key facts, and "
        "synthesizing complex information into clear summaries."
    ),
    verbose=True,
    allow_delegation=False,
)
 
writer = Agent(
    role="Content Writer",
    goal="Write engaging, well-structured content based on research findings",
    backstory=(
        "You are a skilled writer who transforms research data "
        "into compelling articles. You focus on clarity, accuracy, "
        "and reader engagement."
    ),
    verbose=True,
    allow_delegation=False,
)

The verbose=True flag lets you see each agent's reasoning process in your terminal — invaluable for debugging.

Step 3: Create Tasks

Tasks define what each agent should accomplish. Each task has a description, an expected output format, and an assigned agent:

research_task = Task(
    description=(
        "Research the topic: {topic}. "
        "Find key facts, recent developments, and expert opinions. "
        "Provide at least 5 distinct points with supporting evidence."
    ),
    expected_output=(
        "A detailed research brief with numbered points, "
        "each containing a fact and its source or context."
    ),
    agent=researcher,
)
 
writing_task = Task(
    description=(
        "Using the research provided, write a 500-word article on {topic}. "
        "Structure it with an introduction, main points, and conclusion. "
        "Make it informative yet accessible to a general audience."
    ),
    expected_output="A polished article of approximately 500 words in markdown format.",
    agent=writer,
)

Notice the {topic} placeholder — you will pass this value when running the crew.

Step 4: Assemble and Run the Crew

Now connect your agents and tasks into a crew:

crew = Crew(
    agents=[researcher, writer],
    tasks=[research_task, writing_task],
    process=Process.sequential,
    verbose=True,
)
 
result = crew.kickoff(inputs={"topic": "the impact of AI agents on software development"})
print(result)

The Process.sequential setting means tasks run one after another — the writer waits for the researcher to finish before starting. CrewAI also supports Process.hierarchical where a manager agent delegates work dynamically.

Step 5: Run Your Crew

Execute the script:

python crew.py

You will see output showing each agent's thought process, the tools they invoke, and their final outputs. The writer's article will incorporate findings from the researcher — that is the multi-agent collaboration in action.

Step 6: Add Tools for Real-World Capabilities

Agents become far more useful with tools. Let us give the researcher the ability to search the web:

from crewai_tools import SerperDevTool
 
search_tool = SerperDevTool()
 
researcher = Agent(
    role="Senior Research Analyst",
    goal="Find comprehensive, accurate information on the given topic",
    backstory=(
        "You are an experienced research analyst who excels at "
        "finding reliable sources and synthesizing complex information."
    ),
    tools=[search_tool],
    verbose=True,
    allow_delegation=False,
)

You will need a Serper API key (SERPER_API_KEY environment variable). Other built-in tools include ScrapeWebsiteTool, FileReadTool, and DirectoryReadTool.

Step 7: Add Memory for Context Retention

Enable memory so agents remember previous interactions within a session:

crew = Crew(
    agents=[researcher, writer],
    tasks=[research_task, writing_task],
    process=Process.sequential,
    memory=True,
    verbose=True,
)

With memory enabled, the writer gets richer context from the researcher's findings, and repeated runs on similar topics improve in quality.

Practical Tips

Start simple, then add complexity. Begin with two agents and sequential processing. Only introduce hierarchical processes or more agents when you genuinely need them.

Write specific backstories. Vague backstories produce generic outputs. The more context you give an agent about its expertise, the better its decisions will be.

Use allow_delegation=False initially. Delegation lets agents pass tasks to each other, which is powerful but harder to debug. Turn it on once your basic flow works.

Monitor token usage. Each agent call consumes LLM tokens. With verbose mode on, watch how many reasoning steps each agent takes. Tighten your task descriptions if agents wander.

Test with cheaper models first. Use gpt-4o-mini during development, then switch to more capable models for production:

researcher = Agent(
    role="Senior Research Analyst",
    goal="Find comprehensive information on the given topic",
    backstory="...",
    llm="gpt-4o-mini",  # Cheaper for testing
)

What to Build Next

Once you have this foundation working, consider these extensions:

  • Add a fact-checker agent that verifies the researcher's claims
  • Create a code generation crew with an architect, developer, and reviewer
  • Build a customer support system with a triage agent routing to specialists
  • Connect to external APIs using custom tools for domain-specific workflows

The key insight with multi-agent systems is that each agent should have a focused, well-defined responsibility. If you find yourself writing a long backstory covering many skills, that is a signal to split into multiple agents.