CrewAI is the fastest path to a working multi-agent system in Python — and the clearest example of what role-based agent collaboration looks like when the workflow resembles an org chart rather than a flowchart.

The LangGraph vs CrewAI post in this series established when to choose each framework: CrewAI wins when your workflow has clear roles, sequential handoffs, and you need a working prototype this week. LangGraph wins when you need durable state, conditional branching, or human-in-the-loop approval gates. This CrewAI tutorial is the implementation companion to that decision: if you chose CrewAI, here’s every line of code you need to go from installation to a production-ready multi-agent research and writing system.
Setup: Install CrewAI in 3 Minutes
CrewAI requires Python 3.10 or higher (3.12 recommended). It enforces strict Python version bounds and depends on compiled C extensions — check your version first.
# Check your Python version (must be 3.10–3.13)
python --version
# Install CrewAI with the tools package
pip install "crewai[tools]" python-dotenv
# .env — CrewAI uses LiteLLM internally, which wraps any provider
ANTHROPIC_API_KEY=sk-ant-your-key-here
# CrewAI defaults to OpenAI if no model is specified.
# We're using Claude — set this to override the default:
MODEL=claude/claude-sonnet-5
CrewAI uses LiteLLM internally, which means any provider supported by LiteLLM works — Claude, GPT-5.6, Gemini, or local Ollama models. The MODEL=claude/claude-sonnet-5 environment variable sets Claude as the default for all agents in the crew.
Part 1: Your First Crew — Research and Write in 50 Lines
The minimal working CrewAI system: two agents (Researcher and Writer), two tasks (research and write), one crew that runs them sequentially. The Researcher gathers information; the Writer uses that output to produce a polished article.
import os
from dotenv import load_dotenv
from crewai import Agent, Task, Crew, Process
load_dotenv()
# ─── Define Your Agents ─────────────────────────────────────────
# Each agent has: role, goal, and backstory.
# The backstory is surprisingly important — it shapes how Claude
# approaches its role. Write it like a job description.
researcher = Agent(
role="Senior Research Analyst",
goal="Find accurate, current information on {topic} "
"and produce a comprehensive research brief",
backstory="""You are an expert researcher with a talent for
finding relevant information quickly and synthesizing it into
clear, well-organized briefs. You prioritize accuracy over
comprehensiveness — if you're unsure, you say so.""",
verbose=True,
llm="claude/claude-sonnet-5", # researcher uses Sonnet 5
allow_delegation=False # prevents delegation loops
)
writer = Agent(
role="Technical Content Writer",
goal="Transform the research brief into a clear, "
"engaging article for a technical audience",
backstory="""You are a technical writer who excels at making
complex topics accessible without sacrificing accuracy. You
write in an active voice, avoid jargon unless necessary, and
always lead with the most important point.""",
verbose=True,
llm="claude/claude-sonnet-5",
allow_delegation=False
)
# ─── Define Your Tasks ──────────────────────────────────────────
# Tasks specify: what to do, who does it, and what the output looks like.
# {topic} is a placeholder filled at crew.kickoff() time.
research_task = Task(
description="""Research the following topic thoroughly: {topic}
Your research brief must include:
1. A concise definition (2-3 sentences)
2. Why it matters in 2026 (3-4 key points)
3. The top 3 real-world use cases with specific examples
4. Common misconceptions or pitfalls to avoid
5. Recommended resources for deeper learning
Cite sources where possible. If information is uncertain, flag it.""",
expected_output="""A structured research brief with all five
sections above, formatted with headers. Total length: 400-600 words.""",
agent=researcher
)
write_task = Task(
description="""Using the research brief provided, write a complete
article on: {topic}
Requirements:
- Lead with the most compelling point (inverted pyramid structure)
- Technical audience: assume programming knowledge, not AI expertise
- Include 1-2 concrete code examples or real-world scenarios
- End with a clear "what to do next" recommendation
- Target length: 600-800 words""",
expected_output="A complete, publication-ready article in markdown format.",
agent=writer,
context=[research_task] # Writer receives researcher's output as context
)
# ─── Assemble and Run the Crew ──────────────────────────────────
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task],
process=Process.sequential, # tasks run in order
verbose=True
)
# kickoff() runs the crew. The inputs dict fills {topic} placeholders.
result = crew.kickoff(inputs={"topic": "RAG (Retrieval-Augmented Generation)"})
print("\n" + "="*60)
print("FINAL ARTICLE")
print("="*60)
print(result.raw)
Run this and you’ll see both agents working in the terminal — the researcher gathering information, then the writer using that output to produce a polished article. The verbose=True setting shows each agent’s reasoning steps, which is invaluable for debugging unexpected outputs.
Part 2: Adding Tools — Give Agents Real Capabilities
The crew above uses only the agents’ training knowledge. Add tools and agents can search the web, read files, scrape URLs, and call APIs. CrewAI’s tools package includes ready-built tools for the most common use cases.
from crewai_tools import SerperDevTool, ScrapeWebsiteTool, FileReadTool
from crewai.tools import tool
# ─── Built-in tools from crewai-tools ───────────────────────────
# SerperDevTool: Google search via Serper API (free tier: 100 searches/month)
# Requires: SERPER_API_KEY in .env
search_tool = SerperDevTool()
# ScrapeWebsiteTool: Reads and returns a webpage's text content
scraper_tool = ScrapeWebsiteTool()
# ─── Custom tool with the @tool decorator ───────────────────────
# Use this for any function you want to expose to agents
@tool("Save to File")
def save_to_file(filename: str, content: str) -> str:
"""
Save content to a file on disk.
Use when the user wants to save the final output.
Args:
filename: The name of the file to create (e.g., 'report.md')
content: The text content to write
"""
with open(filename, "w") as f:
f.write(content)
return f"Successfully saved to {filename}"
# ─── Assign tools to specific agents ────────────────────────────
# Only the researcher needs search and scraping.
# The writer only needs to save the final article.
researcher_with_tools = Agent(
role="Senior Research Analyst",
goal="Find current, accurate information on {topic} using web search",
backstory="""Expert researcher who knows how to find reliable sources
quickly. You always verify information from at least two sources before
including it in the brief.""",
tools=[search_tool, scraper_tool], # give tools here
verbose=True,
llm="claude/claude-sonnet-5",
allow_delegation=False
)
writer_with_tools = Agent(
role="Technical Content Writer",
goal="Write and save a polished article on {topic}",
backstory="Expert technical writer who produces clear, accurate content.",
tools=[save_to_file], # only the writer saves the output
verbose=True,
llm="claude/claude-sonnet-5",
allow_delegation=False
)
# Tasks and crew assembly remain the same — just swap in the new agents
Part 3: Cost Optimization — Reduce Costs by 60–70%
A two-agent research crew using Claude Sonnet 5 for all agents costs approximately $0.10 to $0.30 per run. For high-volume use cases — running the crew 100 times per day — this compounds quickly. The CrewAI cost optimization pattern: use the most capable model only where it produces meaningfully better output.
# Cost-optimized crew: Haiku does the heavy lifting,
# Sonnet handles the final polished output.
# Reduces cost by 60-70% for research-heavy workflows.
import os
from crewai import Agent, Task, Crew, Process
from dotenv import load_dotenv
load_dotenv()
# Haiku for data gathering and initial analysis (cheap, fast)
RESEARCH_MODEL = "claude/claude-haiku-4-5-20251001" # $0.80/$4.00 per MTok
# Sonnet for final synthesis and polished output (quality matters here)
WRITING_MODEL = "claude/claude-sonnet-5" # $2.00/$10.00 per MTok
data_collector = Agent(
role="Data Collection Specialist",
goal="Quickly gather raw information on {topic} from multiple sources",
backstory="Fast, efficient data gatherer. Quality over completeness.",
llm=RESEARCH_MODEL, # Haiku: cheap and fast for structured gathering
verbose=False, # Turn off verbose for cheaper agents
allow_delegation=False
)
analyst = Agent(
role="Research Analyst",
goal="Synthesize the collected data into a clear research brief",
backstory="Expert at turning raw data into structured insights.",
llm=RESEARCH_MODEL, # Haiku handles structured synthesis too
verbose=False,
allow_delegation=False
)
writer = Agent(
role="Senior Technical Writer",
goal="Write a polished, publication-ready article from the research brief",
backstory="Expert writer who elevates good content into great content.",
llm=WRITING_MODEL, # Sonnet only for the final quality output
verbose=True,
allow_delegation=False
)
# Cost estimate per run:
# Data collection (Haiku): ~$0.002
# Analysis (Haiku): ~$0.003
# Writing (Sonnet): ~$0.05
# Total: ~$0.055 vs ~$0.20 with all-Sonnet crew
# Savings: ~72% reduction
Production Checklist: 5 Common CrewAI Problems and Their Fixes
- Delegation loops (agents keep passing tasks to each other): Set
allow_delegation=Falseon all non-manager agents. Delegation loops happen when multiple agents have overlapping roles. Only the manager agent in a hierarchical crew should have delegation enabled. - Agents going off-script: Be more specific in the task description’s
expected_outputfield. Vague expected outputs produce creative interpretations. “A 400-600 word research brief with exactly five sections” beats “a research brief.” - High costs on repeated runs: Enable agent caching to avoid paying for repeated tool call summaries:
cache=Trueon the agent. This caches tool results so the same web search doesn’t get billed twice across runs. - Installation failures (
ModuleNotFoundError): CrewAI requires Python 3.10 to 3.13. Python 3.9 and below are not supported. If you have multiple Python installations, usepython3.12 -m pip install "crewai[tools]"explicitly. - Context window exceeded on long tasks: Break the task description into smaller, more specific tasks. A single task that asks an agent to “research everything about X” can generate context windows that overflow. Three focused tasks with specific deliverables stay within limits reliably.
For the complete CrewAI documentation including Flows for pipeline orchestration, see CrewAI’s official documentation.
The Builder’s Takeaway
CrewAI is the most intuitive multi-agent framework available in 2026 for workflows that map cleanly to team roles. Define the agents, describe their jobs, specify what each task should produce, and CrewAI handles the coordination. The role-backstory-goal structure takes five minutes to learn and produces working multi-agent systems in under 50 lines. The cost optimization pattern — Haiku for research, Sonnet for output — cuts per-run costs by 60 to 70 percent without meaningful quality loss on the final deliverable. The five production problems above cover 90 percent of the issues builders hit in the first week. Build the two-agent crew from Part 1 today, add tools from Part 2 this week, and apply the cost optimization before you run it at scale. The LangGraph vs CrewAI decision framework tells you when to reach for each — this tutorial gives you the CrewAI implementation once you’ve made that call.
Continue in This Series
- LangGraph vs CrewAI — the framework decision: when to use CrewAI vs LangGraph with working code for both
- LangChain Tutorial 2026 — the higher-level chain and agent framework that CrewAI sits alongside
- How to Build an AI Agent With Python — the raw SDK agent loop that all frameworks build on
- RAG Tutorial Python 2026 — add a knowledge retrieval layer to your CrewAI researcher agent
- AI Agent Unit Economics — the T/R ratio that determines whether the Haiku/Sonnet cost split makes sense for your specific use case
This post is part of The Agentic Protocol’s Work series — the connective infrastructure layer beneath every autonomous pipeline. See also: LangGraph vs CrewAI.