CrewAI Multi-Agents · Lesson 3 of 16
Installation and Your First Crew
Prerequisites
Before installing CrewAI you need:
- Python 3.10 or later (3.11 recommended)
- pip or uv as your package manager
- An API key for at least one LLM provider (OpenAI, Azure, Anthropic, etc.)
Verify your Python version:
python --version
# Python 3.11.9Installation
Using pip
pip install crewai crewai-toolscrewai is the core framework. crewai-tools adds the built-in tool suite (web search, file reading, website scraping, etc.).
Using uv (faster)
uv pip install crewai crewai-toolsUsing the CrewAI CLI (scaffolds a full project)
pip install crewai
crewai create crew my_project
cd my_projectThis creates a project scaffold with pyproject.toml, src/, agent definitions, and task definitions pre-wired. For learning purposes, we will build from scratch.
Verify the installation
import crewai
print(crewai.__version__)
# 0.80.0 (or later)Setting Up API Keys
CrewAI uses LiteLLM under the hood, which means it can connect to any major LLM provider with a simple model string. The API key configuration depends on which provider you use.
OpenAI
export OPENAI_API_KEY="sk-proj-..."Or in a .env file (recommended):
# .env
OPENAI_API_KEY=sk-proj-...Load it in your Python code:
from dotenv import load_dotenv
load_dotenv() # reads .env automaticallyInstall python-dotenv if you do not have it:
pip install python-dotenvAnthropic (Claude)
export ANTHROPIC_API_KEY="sk-ant-..."Then set the model in your agents:
from crewai import Agent, LLM
claude = LLM(model="anthropic/claude-3-5-sonnet-20241022")
agent = Agent(
role="Research Analyst",
goal="Find accurate information",
backstory="You are a meticulous researcher.",
llm=claude,
)Groq (fast, cheap inference)
export GROQ_API_KEY="gsk_..."from crewai import LLM
groq_llm = LLM(model="groq/llama-3.1-70b-versatile")Azure OpenAI Configuration
Azure is common in enterprise and healthcare environments. CrewAI handles Azure via LiteLLM's Azure provider.
Environment Variables
# .env
AZURE_OPENAI_API_KEY=your-azure-key
AZURE_API_BASE=https://your-resource.openai.azure.com/
AZURE_API_VERSION=2024-02-01Using Azure in CrewAI
import os
from dotenv import load_dotenv
from crewai import Agent, Task, Crew, Process, LLM
load_dotenv()
azure_llm = LLM(
model="azure/gpt-4o", # "azure/" prefix tells LiteLLM to use Azure
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
base_url=os.getenv("AZURE_API_BASE"),
api_version=os.getenv("AZURE_API_VERSION"),
)
researcher = Agent(
role="Research Analyst",
goal="Find accurate information on pharmaceutical compounds",
backstory=(
"You are a senior research analyst with expertise in clinical pharmacology. "
"You synthesize complex scientific literature into clear summaries."
),
llm=azure_llm,
verbose=True,
)
writer = Agent(
role="Medical Writer",
goal="Produce clear, compliant medical communications",
backstory=(
"You have written hundreds of medical documents for pharma companies. "
"You are precise, structured, and audience-aware."
),
llm=azure_llm,
verbose=True,
)
research_task = Task(
description="Research the mechanism of action and clinical use of semaglutide.",
expected_output=(
"A structured summary covering: mechanism of action, approved indications, "
"key clinical trial results, and notable adverse effects."
),
agent=researcher,
)
writing_task = Task(
description=(
"Write a 200-word patient-facing summary of semaglutide based on the research."
),
expected_output=(
"A 200-word plain-language summary suitable for patients. "
"Avoid jargon. Use short sentences."
),
agent=writer,
context=[research_task],
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential,
verbose=True,
)
result = crew.kickoff()
print(result.raw)Recommended Project Structure
For anything beyond a quick script, organize your code across multiple files:
my_crew_project/
├── .env # API keys (never commit this)
├── .gitignore # include .env
├── pyproject.toml # or requirements.txt
├── crew.py # entry point — assembles and runs the crew
├── agents.py # Agent definitions
├── tasks.py # Task definitions
├── tools.py # Custom tool definitions
└── models.py # Pydantic output modelsagents.py
# agents.py
from crewai import Agent, LLM
from tools import search_tool, database_tool
def make_researcher(llm: LLM) -> Agent:
return Agent(
role="Research Analyst",
goal="Find accurate, up-to-date information on any topic",
backstory=(
"You are a pharmacologist with 10 years of research experience. "
"You always verify claims with multiple sources."
),
tools=[search_tool],
llm=llm,
verbose=True,
)
def make_writer(llm: LLM) -> Agent:
return Agent(
role="Medical Writer",
goal="Write clear, accurate medical content for professional audiences",
backstory=(
"You are an experienced medical writer who has produced content "
"for clinical journals, pharmaceutical companies, and hospitals."
),
llm=llm,
verbose=True,
)
def make_reviewer(llm: LLM) -> Agent:
return Agent(
role="Compliance Reviewer",
goal="Ensure all content meets regulatory and accuracy standards",
backstory=(
"You are a regulatory affairs specialist. You are conservative, "
"meticulous, and always cite the guideline you are applying."
),
llm=llm,
verbose=True,
)tasks.py
# tasks.py
from crewai import Task
from crewai import Agent
def make_research_task(agent: Agent, topic: str) -> Task:
return Task(
description=f"Research the following topic thoroughly: {topic}",
expected_output=(
"A structured research summary with: key findings (at least 5 bullet points), "
"sources used, and any notable gaps or uncertainties."
),
agent=agent,
)
def make_writing_task(agent: Agent, research_task: Task, audience: str) -> Task:
return Task(
description=(
f"Write a professional article for {audience} based on the research provided."
),
expected_output=(
f"A well-structured article of at least 300 words, appropriate for {audience}. "
"Include a title, introduction, body with subheadings, and conclusion."
),
agent=agent,
context=[research_task],
)
def make_review_task(agent: Agent, writing_task: Task) -> Task:
return Task(
description=(
"Review the article for accuracy, compliance, and clarity. "
"Flag any claims that require stronger evidence."
),
expected_output=(
"A review report with: overall assessment (Approved / Needs Revision), "
"a list of specific issues found (if any), and recommended changes."
),
agent=agent,
context=[writing_task],
)crew.py
# crew.py
import os
from dotenv import load_dotenv
from crewai import Crew, Process, LLM
from agents import make_researcher, make_writer, make_reviewer
from tasks import make_research_task, make_writing_task, make_review_task
load_dotenv()
def build_and_run_crew(topic: str, audience: str) -> str:
llm = LLM(model="gpt-4o")
# Instantiate agents
researcher = make_researcher(llm)
writer = make_writer(llm)
reviewer = make_reviewer(llm)
# Instantiate tasks
research_task = make_research_task(researcher, topic)
writing_task = make_writing_task(writer, research_task, audience)
review_task = make_review_task(reviewer, writing_task)
# Build the crew
crew = Crew(
agents=[researcher, writer, reviewer],
tasks=[research_task, writing_task, review_task],
process=Process.sequential,
verbose=True,
)
result = crew.kickoff()
return result.raw
if __name__ == "__main__":
output = build_and_run_crew(
topic="GLP-1 receptor agonists and their role in type 2 diabetes management",
audience="endocrinologists",
)
print("=== FINAL OUTPUT ===")
print(output)Run with:
python crew.pyUsing Ollama for Local Models (No API Cost)
For development and testing, Ollama lets you run models locally:
# Install Ollama first: https://ollama.ai
ollama pull llama3.1from crewai import Agent, LLM
local_llm = LLM(
model="ollama/llama3.1",
base_url="http://localhost:11434",
)
agent = Agent(
role="Research Analyst",
goal="Find accurate information",
backstory="You are a careful researcher.",
llm=local_llm,
verbose=True,
)Local models are slower and often less capable than GPT-4o for complex reasoning, but they are free and private — useful for sensitive data.
Environment Variables Reference
# .env — complete reference
# OpenAI
OPENAI_API_KEY=sk-proj-...
# Azure OpenAI
AZURE_OPENAI_API_KEY=...
AZURE_API_BASE=https://your-resource.openai.azure.com/
AZURE_API_VERSION=2024-02-01
# Anthropic
ANTHROPIC_API_KEY=sk-ant-...
# Groq
GROQ_API_KEY=gsk_...
# CrewAI tools
SERPER_API_KEY=... # for SerperDevTool (web search)
# Optional: disable telemetry
OTEL_SDK_DISABLED=trueSummary
- Install with
pip install crewai crewai-tools - Use
.env+python-dotenvfor API key management - CrewAI supports any provider via LiteLLM: just change the model string
- Azure OpenAI uses
azure/model-nameas the model string - For real projects, split agents, tasks, tools, and models into separate files
- Local development with Ollama avoids API costs during iteration