Have you ever asked ChatGPT to research something, analyze the findings, and then write a polished report, all in one prompt? You probably got something back, but it wasn’t great. That’s because you’re asking a single model to wear way too many hats at once. CrewAI is a Python framework that solves this by letting you build a crew of specialized AI agents, each focusing on one part of the job.
For example, instead of cramming research, validation, and writing into a single prompt, you create a team. One agent researches, another validates, and a third writes. Each focuses on what it does best, working together to complete the task.
By the end of this tutorial, you’ll understand that:
- CrewAI coordinates teams where each agent has a specific role, goal, and backstory that influence its behavior.
- Sequential workflows automatically pass outputs from one agent to the next, making coordinated pipelines straightforward.
- The
contextparameter gives you fine-grained control over which task outputs feed into other tasks. - You can equip agents with tools like web scraping to expand what they can do beyond text generation.
- API costs multiply quickly since each agent makes separate LLM calls, and verbose logging helps you debug agent behavior.
Before you invest time learning CrewAI, you should understand when it’s the right tool for your project. This comparison highlights the key trade-offs:
| Use Case | Pick CrewAI | Pick LangGraph | Pick AG2 / AutoGen |
|---|---|---|---|
| You need structured, role-based workflows | ✅ | - | - |
| You want minimal boilerplate to go from prototype to production | ✅ | - | - |
| You need complex state machines with conditional branching | - | ✅ | - |
| Your agents need conversational, chat-driven coordination | - | - | ✅ |
CrewAI’s sweet spot is workflows where agents have clear responsibilities and work in a predictable sequence. If you need fine-grained state management with branching logic, LangGraph gives you more control. If your agents need conversational back-and-forth, AG2—the community fork of AutoGen—supports chat-driven coordination patterns and may be a better fit.
Microsoft AutoGen is now in maintenance mode, so new projects typically choose AG2 or Microsoft Agent Framework.
Get Your Code: Click here to download the free sample code you’ll use to build and coordinate teams of AI agents with CrewAI in Python.
Take the Quiz: Test your knowledge with our interactive “CrewAI in Python: Coordinating Teams of AI Agents” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
CrewAI in Python: Coordinating Teams of AI AgentsCheck your understanding of CrewAI in Python. Review how to define agent roles, assign tasks, add tools, and coordinate multi-agent workflows.
Get Started With CrewAI in Python
Before you dive into building multi-agent systems with CrewAI, you’ll need to install it and set up an API key for your chosen language model provider. This tutorial uses Google’s Gemini model, which you can access for free through Google AI Studio.
Note: CrewAI is model-agnostic, so you’re not locked into Gemini. It also works with OpenAI, Anthropic’s Claude, Mistral, Groq, and Ollama for local models, among others. Check the CrewAI documentation for the full list of supported providers.
You can install CrewAI from PyPI using pip. Before running the command below, you should create and activate a virtual environment. CrewAI requires Python 3.10 to 3.13, so run python --version first—installing on Python 3.14 or later will silently resolve to a much older CrewAI release and then fail to build:
$ python-mpipinstall'crewai[tools,google-genai]'
This installs CrewAI’s core framework, the native Google Gemini provider, and prebuilt tools like web scraping that agents can use during their work.
You’ll need a Gemini API key to run the examples in this tutorial. If you don’t have one yet, then head over to Google AI Studio to sign in with your Google account and generate an API key for free.
Once you have your API key, set it as an environment variable:
With your environment variable set, CrewAI is ready to connect to Gemini in your projects.
To get started with CrewAI, you can create a single agent that acts as a travel advisor:
single_agent.py
fromcrewaiimport LLM, Agent, Crew, Task
llm = LLM(model="gemini/gemini-2.5-flash")
travel_agent = Agent(
role="Travel Advisor",
goal="Provide helpful travel recommendations",
backstory=(
"You're an experienced travel advisor who has visited"
" over fifty countries and specializes in budget-friendly"
" adventure travel."
),
llm=llm,
verbose=True,
)
task = Task(
description="Suggest three budget-friendly destinations in Southeast Asia",
expected_output="A short list of three destinations with brief descriptions",
agent=travel_agent,
)
crew = Crew(agents=[travel_agent], tasks=[task])
result = crew.kickoff()
print(result.raw)
In this example, you import the Agent, Task, Crew, and LLM classes from crewai. Agents are the primary building blocks for multi-agent systems in CrewAI. You create an LLM instance pointing to Google’s Gemini model, then create an agent by passing three required arguments plus the llm parameter.
The role tells the agent what it is. The goal guides what it tries to accomplish. The backstory provides context that shapes how it responds. These three parameters work together to give your agent a personality and expertise area.
Note: The verbose=True parameter prints detailed logs of the agent’s reasoning process to your terminal. This is helpful when you’re debugging, but you’ll want to turn it off in production since it creates a lot of noise.
Note: On first run, CrewAI may display a “Would you like to view your execution traces?” prompt that auto-dismisses after twenty seconds. This is normal behavior and won’t affect your results.
Build Your First Multi-Agent Team
A single agent is useful for understanding the basics, but CrewAI really shines when you combine multiple agents into a coordinated team. You’ll see how specialized agents working together outperform a single agent trying to do everything. In this section, you’ll build a two-agent crew—a researcher and a writer—that work in sequence on a renewable-energy article.
Define Specialized Agents
You’ll create two agents with distinct responsibilities. One agent researches information, and another transforms it into polished content:
research_and_writer_crew.py
fromcrewaiimport LLM, Agent, Crew, Process, Task
llm = LLM(model="gemini/gemini-2.5-flash")
researcher = Agent(
role="Senior Research Analyst",
goal="Find comprehensive information about a given topic",
backstory=(
"You're a seasoned research analyst with a knack for"
" uncovering the most relevant and accurate information."
" You're known for your thorough and well-organized research."
),
llm=llm,
)
writer = Agent(
role="Content Writer",
goal="Write clear, engaging content based on research findings",
backstory=(
"You're an experienced writer who excels at transforming"
" complex research into accessible, well-structured articles"
" that readers enjoy."
),
llm=llm,
)
Notice how each agent has a distinct identity. The researcher focuses on finding information, while the writer focuses on presenting it. This separation of concerns is fundamental to how CrewAI works. You wouldn’t ask your best researcher to also be your best copywriter in real life, and the same principle applies here.
Create Tasks and Coordinate Your Team
Now you’ll give each agent a specific job and combine them into a crew, which is a group of agents that work together toward a shared goal. Add the following to the same script, below the agent definitions:
research_and_writer_crew.py
# ...
research_task = Task(
description="Research the latest trends in renewable energy technology",
expected_output=(
"A detailed list of the top five renewable energy trends"
" with explanations"
),
agent=researcher,
)
writing_task = Task(
description="Write a short article based on the research findings",
expected_output=(
"A well-structured article of about three hundred words"
" on renewable energy trends"
),
agent=writer,
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential,
verbose=True,
)
result = crew.kickoff()
print(result.raw)
When you call crew.kickoff(), CrewAI executes each task in order. The researcher completes its task first, and its output automatically flows into the writer’s task as context. This automatic data flow is one of CrewAI’s key features.
Setting process=Process.sequential makes this explicit, though sequential execution is the default behavior. Your final output comes from the last task in the sequence, which in this case is the writer’s article.
This pattern lets you build complex workflows by chaining together specialized agents. Research flows into writing. Writing flows into editing. Editing flows into final review. Each agent does one thing well, and the team produces better results than any single agent could.
Control Task Dependencies Explicitly
The automatic data flow you saw in the previous section works great for simple two-task sequences. But what happens when you have three or more tasks, and not every task depends on the one immediately before it? You’ll need explicit control over which outputs feed into which tasks.
The context parameter gives you fine-grained control over task dependencies.
Continuing with the researcher and writer agents from the previous section, update your existing script—optionally saving it under a new filename to keep things tidy:
explicit_context.py
# ...
research_task = Task(
description=(
"Research the current state of electric vehicle adoption"
" worldwide"
),
expected_output=(
"A bullet-point list of key statistics and trends"
" in EV adoption"
),
agent=researcher,
)
writing_task = Task(
description=(
"Using the provided research, write a concise summary article"
" about electric vehicle adoption"
),
expected_output="A two-hundred-word article summarizing EV adoption trends",
agent=writer,
context=[research_task],
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
verbose=True,
)
result = crew.kickoff()
print(result.raw)
The key line here is context=[research_task]. This explicitly tells CrewAI that writing_task depends on research_task and should receive its output as context. While this happens automatically in a two-task crew, the context parameter becomes essential when you have more complex workflows.
For example, imagine you have two research tasks running in parallel with async_execution=True. You could have a writing task that depends on both via context=[task_a, task_b]. The writing task won’t start until both research tasks complete. This gives you precise control over how your agents coordinate.
The interactive timeline below makes this concrete: three research tasks run concurrently, and you choose which of their outputs feed the writer’s context. Because the writer waits for all of its context tasks, it starts only once its slowest selected input finishes—so dropping that input lets the whole crew finish sooner:
Expand Agent Capabilities With Tools
Right now, your agents can only generate text based on their training data. But what if an agent needs current information or needs to interact with external systems? That’s where tools come in. Tools are functions that agents can call to expand their capabilities beyond text generation.
You’ll use the ScrapeWebsiteTool to give your researcher the ability to scrape live data from a website. This is particularly useful for facts tied to a specific page, such as the current Python version listed on python.org:
agent_with_tools.py
fromcrewaiimport LLM, Agent, Crew, Task
fromcrewai_toolsimport ScrapeWebsiteTool
llm = LLM(model="gemini/gemini-2.5-pro")
scrape_tool = ScrapeWebsiteTool()
researcher = Agent(
role="Python Release Analyst",
goal="Find the latest Python release information",
backstory=(
"You're a developer advocate who tracks Python releases"
" and summarizes what's new for the community."
),
tools=[scrape_tool],
llm=llm,
)
writer = Agent(
role="Tech Blogger",
goal="Write concise release summaries for a developer audience",
backstory=(
"You write clear, engaging blog posts that help developers"
" stay up to date with the Python ecosystem."
),
llm=llm,
)
research_task = Task(
description=(
"Scrape https://www.python.org/downloads/ and report"
" the latest stable Python version number and its release date"
),
expected_output="The latest Python version number and release date",
agent=researcher,
)
writing_task = Task(
description=(
"Write a one-paragraph announcement based on the Python"
" release information provided by the research task"
),
expected_output=(
"A concise one-hundred-word announcement covering the"
" latest Python version number and release date"
),
agent=writer,
context=[research_task],
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
verbose=True,
)
result = crew.kickoff()
print(result.raw)
Notice that only the researcher has scrape_tool in its tools list. The writer doesn’t need web access because it works with the research output it receives through the context parameter.
This pattern of giving different agents different tools mirrors how real teams work. Your researcher has access to databases and search engines. Your writer has access to style guides and templates. Each specialist has the tools they need, and no more.
You can also override an agent’s tools at the task level by passing tools=[...] to a specific Task. This lets the same agent use different tools for different assignments, which can be useful for complex workflows.
Beware of Limitations and Gotchas
CrewAI makes multi-agent coordination feel clean and intuitive. However, there are some important constraints you should understand before building production systems. Being aware of these trade-offs early will help you make better architectural decisions, avoid surprising failure modes in production, and save significant debugging time later.
Multi-Agent Crews Are Expensive to Run
Each agent makes its own LLM API calls, which means costs multiply quickly. A crew with three agents running sequential tasks makes at least three separate API calls. If agents iterate or use tools, then you’ll make even more calls.
You can monitor costs by checking crew.usage_metrics after calling kickoff(). This shows you token counts and helps you understand where your money is going. In production, these costs can spiral if you’re not careful.
API Keys Are Required for Everything
CrewAI doesn’t provide models itself. You need a Gemini API key, an OpenAI API key, or an API key for another LLM provider like Anthropic. If you use tools that rely on external APIs, you’ll need additional keys for those services. The Gemini free tier is generous for experimentation, but plan your budget accordingly if you scale up.
If you enable memory=True or certain tools, CrewAI may look for OPENAI_API_KEY. Setting it to any non-empty string suppresses the error.
Communication Is Task-Based, Not Conversational
AG2, the actively maintained community fork of Microsoft’s AutoGen, is built for conversational patterns where agents engage in back-and-forth discussion. CrewAI works differently: its agents primarily pass structured outputs from one task to the next, with no built-in mechanism for agent negotiation or debate. If your use case requires agents that discuss and revise their thinking, consider AG2 or Microsoft Agent Framework instead.
Sequential Execution Is the Default and Safest Pattern
This tutorial covered sequential coordination because it’s the most straightforward and stable approach. Hierarchical processes require a manager_llm or manager_agent parameter, and parallel execution uses async_execution=True on individual tasks. Both add complexity and potential failure modes, so master sequential workflows first.
Verbose Logging Is Essential During Development
Agent behavior can be unpredictable. The model might misinterpret instructions, use the wrong tool, or produce unexpected output. Always use verbose=True during development so you can see exactly what each agent is thinking and where things go wrong. You’ll want this turned off once your crew is running for real, but while you’re building, it’s your primary debugging tool.
Conclusion
You’ve set up CrewAI and built your first multi-agent team, chaining specialized agents into a sequential workflow. You also weighed the practical trade-offs of running agent crews in production.
CrewAI excels at structured, role-based workflows where each agent has clear responsibilities. It saves you from complex orchestration code by handling task coordination and data flow automatically.
In this tutorial, you’ve learned how to:
- Install and configure CrewAI with an LLM provider and API key
- Create specialized agents with roles, goals, and backstories
- Build coordinated teams that pass outputs between tasks automatically
- Control task dependencies explicitly using the
contextparameter - Equip agents with tools to expand their capabilities beyond text generation
- Weigh the trade-offs in API costs, execution patterns, and communication styles
With these skills, you can start building AI agent teams that coordinate complex workflows, each agent focusing on what it does best.
Next Steps
Now that you understand the core features of CrewAI, you can explore more advanced topics:
- Experiment with hierarchical coordination: Try
Process.hierarchicalwith amanager_llmto see how a manager agent delegates work to team members dynamically. - Create custom tools: Use the
@tooldecorator fromcrewai.toolsto build your own tools that agents can invoke. - Explore advanced features: Check out the CrewAI documentation for Memory, Knowledge, and Flows.
- Compare with other frameworks: If you’re choosing between frameworks, explore LangGraph for state machine control or AG2 for conversational patterns.
You can also start building practical projects like content generation pipelines, research automation systems, or customer service agents. CrewAI’s role-based architecture helps you ship reliable multi-agent applications with minimal boilerplate.
For a guided path through these topics, Real Python’s LLM Application Development With Python learning path organizes tutorials and video courses on working with language models, so you can deepen your skills with a structured curriculum.
Get Your Code: Click here to download the free sample code you’ll use to build and coordinate teams of AI agents with CrewAI in Python.
Frequently Asked Questions
Now that you have some experience with CrewAI in Python, you can use the questions and answers below to check your understanding and recap what you’ve learned.
Yes, including OpenAI, Anthropic’s Claude, Mistral, Groq, AWS Bedrock, and Ollama for local models. Set the llm parameter on any agent. For example, use llm=LLM(model="gpt-4.1-mini") for OpenAI or llm=LLM(model="ollama/llama3.1") for a local Ollama model. You’ll need the appropriate API key set as an environment variable for cloud providers.
Cost depends on the number of agents, tasks, and which LLM you use. Each agent makes separate API calls, so a three-agent crew costs roughly three times what a single-agent call would cost. The Gemini free tier provides generous limits for experimentation.
After running crew.kickoff(), check crew.usage_metrics to see exact token counts. You can reduce costs by using a cheaper model for tool-calling operations via the function_calling_llm agent parameter.
CrewAI is a standalone multi-agent orchestration framework built entirely from scratch, independent of LangChain. LangChain is a general-purpose framework for building LLM applications with chains, retrieval, memory, and more. If you need to use existing LangChain tools with CrewAI, you can wrap them manually using BaseTool from crewai.tools. Many developers use both frameworks for different purposes in the same project.
CrewAI doesn’t have a Process.parallel option, but you can achieve parallel execution by setting async_execution=True on individual tasks. Tasks marked for async execution run concurrently, and downstream tasks that list them in their context parameter will wait for all of them to complete before starting.
Use Process.hierarchical when you want a manager agent to dynamically delegate tasks to the most appropriate team member rather than following a fixed order. This is useful for complex workflows where task assignment depends on intermediate results. You’ll need to provide either a manager_llm or a custom manager_agent when using this mode.
Agents communicate through task outputs rather than direct conversation. In a sequential process, the output of each task automatically flows as context to the next task. You can also explicitly define dependencies using the context parameter on a Task. This task-based approach provides predictable data flow but doesn’t support the back-and-forth exchanges you’d find in AG2 or similar conversational frameworks.
Take the Quiz: Test your knowledge with our interactive “CrewAI in Python: Coordinating Teams of AI Agents” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
CrewAI in Python: Coordinating Teams of AI AgentsCheck your understanding of CrewAI in Python. Review how to define agent roles, assign tasks, add tools, and coordinate multi-agent workflows.