CrewAI is a lean, standalone Python framework for orchestrating autonomous, role-playing AI agents. It is built entirely from scratch — independent of LangChain or any other agent framework — and gives you two complementary ways to build multi-agent systems: Crews (teams of agents that collaborate with autonomy) and Flows (event-driven workflows that give you precise, production-grade control). This guide shows you how to install CrewAI, scaffold a project, define agents and tasks, run them, and extend them with tools, memory, and knowledge.
Note
CrewAI is a framework you build with, not an end-user application. Throughout this guide, "you" means a Python developer writing agent systems. If you are looking for architecture internals, the execution engine, the full configuration reference, or deployment, see the companion Admin Guide.
1. Quick Start
The fastest path from zero to a running crew is the CLI scaffolder. It generates a complete project with example agents and tasks wired together.
# 1. Install CrewAI (requires Python >=3.10, <3.14)
pip install crewai
# 2. Scaffold a new crew project
crewai create crew my_project
# 3. Move into it and add your API key
cd my_project
echo "OPENAI_API_KEY=sk-..." >> .env
# 4. Run the crew
crewai run
# Running the crew kicks off the agents defined in config/agents.yaml,
# executes the tasks in config/tasks.yaml sequentially, and writes the
# final result to report.md in the project root.
Tip
CrewAI uses UV for dependency management. If you have UV installed, prefer
uv pip install crewaiandcrewai install— they are faster and produce reproducible lockfiles.
What just happened:
crewai create crewgenerated a project (see §3).- Two agents (
researcher,reporting_analyst) were defined in YAML. - Two tasks were defined in YAML and assigned to those agents.
crewai runexecutedcrew().kickoff(inputs=...), running the tasks in sequence.
2. Installation
2.1 Requirements
| Requirement | Detail |
|---|---|
| Python | >=3.10, <3.14 |
| Package manager | pip works; UV recommended for speed + lockfiles |
| LLM access | An API key for at least one provider (OpenAI by default) |
| OS | macOS, Linux, Windows |
2.2 Install the package
UV (recommended)
uv pip install crewai
pip
pip install crewai
To include the optional tools library (crewai-tools, ~80 prebuilt tools):
uv pip install 'crewai[tools]'
Important
The base
crewaipackage already depends oncrewai-coreandcrewai-cli, so thecrewaicommand is available immediately after install. The[tools]extra only adds the separatecrewai-toolspackage.
2.3 Optional extras
CrewAI ships many optional dependency groups so you only install what you use. Install one or more with bracket syntax:
uv pip install 'crewai[tools,embeddings,qdrant]'
| Extra | Adds |
|---|---|
tools |
The crewai-tools library (web scraping, RAG, file, search, sandbox tools) |
embeddings |
tiktoken for token counting / embeddings |
litellm |
LiteLLM fallback for 100+ LLM providers |
anthropic |
Native Anthropic SDK |
google-genai |
Native Google Gemini SDK |
bedrock / aws |
AWS Bedrock + boto3 |
azure-ai-inference |
Azure AI inference + identity |
watson |
IBM watsonx.ai |
voyageai |
Voyage AI embeddings |
qdrant / qdrant-edge |
Qdrant vector store |
mem0 |
mem0 long-term memory backend |
docling |
Document parsing (docling) for knowledge sources |
pandas / openpyxl |
Tabular data handling |
a2a |
Agent-to-Agent (A2A) protocol: remote agent delegation |
file-processing |
crewai-files for native file inputs |
Note
CrewAI talks to most models through native provider SDKs (OpenAI, Anthropic, Azure, Bedrock, Gemini). For any other provider, install the
litellmextra — see §8.
2.4 Troubleshooting installation
Error: ModuleNotFoundError: No module named 'tiktoken'
Cause: Token-counting/embeddings dependency not installed.
Solution: uv pip install 'crewai[embeddings]' (or 'crewai[tools]').
Error: Failed building wheel for tiktoken
Cause: tiktoken needs a Rust toolchain to build from source.
Solution: Install the Rust compiler, or force a pre-built wheel: uv pip install tiktoken --prefer-binary. On Windows, ensure Visual C++ Build Tools are installed.
Error: Failed to install entrypoints for crewai
Cause: A corrupted or partial environment (reported in community issue #6010).
Solution: Recreate a clean virtual environment (uv venv) and reinstall.
3. Project Structure
crewai create crew <name> generates this layout:
my_project/
├── .gitignore
├── .env # API keys and environment variables
├── pyproject.toml # depends on crewai[tools]; defines run/train/test scripts
├── README.md
├── knowledge/
│ └── user_preference.txt # example knowledge source
├── skills/ # (optional) agent skill directories
└── src/
└── my_project/
├── __init__.py
├── main.py # entry point: run / train / replay / test functions
├── crew.py # @CrewBase class: defines agents, tasks, the crew
├── tools/
│ ├── custom_tool.py
│ └── __init__.py
└── config/
├── agents.yaml # agent role / goal / backstory definitions
└── tasks.yaml # task description / expected_output definitions
You customize a project by editing four things:
| File | What you change |
|---|---|
config/agents.yaml |
Define each agent's role, goal, backstory |
config/tasks.yaml |
Define each task's description, expected_output, assigned agent |
crew.py |
Wire agents, tasks, tools, and the process together |
main.py |
Provide runtime inputs for template interpolation |
Tip
You can also scaffold a Flow project with
crewai create flow <name>. Flows are covered in §9.
4. Core Concepts
CrewAI has a small set of building blocks. Understanding these five concepts is enough to build almost anything.
┌─────────┐ has ┌────────┐ runs ┌────────┐
│ Crew │────────▶│ Agent │─────────▶│ Task │
└─────────┘ agents └────────┘ with └────────┘
│ process │ tools/llm
▼ ▼
sequential / OpenAI / Anthropic /
hierarchical Gemini / Bedrock / ...
| Concept | What it is |
|---|---|
| Agent | An autonomous worker with a role, goal, backstory, an LLM, and optional tools. It reasons, calls tools, and produces output. |
| Task | A unit of work with a description and an expected_output, assigned to an agent. |
| Crew | A team of agents plus an ordered list of tasks and a process that decides how they run. |
| Process | How a crew executes its tasks: sequential (in order) or hierarchical (a manager delegates). |
| Flow | An event-driven workflow that orchestrates Python code and crews with precise, branching control. |
Supporting concepts: Tools (capabilities agents can invoke), LLMs (the models behind agents), Memory (recall across runs), and Knowledge (grounding documents). Each gets its own section below.
5. Building Your First Crew
There are two styles for defining a crew: the YAML + @CrewBase style (recommended, used by the scaffolder) and the pure-Python style (everything inline). Start with YAML.
5.1 Define agents in YAML
config/agents.yaml:
researcher:
role: >
{topic} Senior Data Researcher
goal: >
Uncover cutting-edge developments in {topic}
backstory: >
You're a seasoned researcher with a knack for uncovering the latest
developments in {topic}. Known for your ability to find the most relevant
information and present it clearly and concisely.
reporting_analyst:
role: >
{topic} Reporting Analyst
goal: >
Create detailed reports based on {topic} data analysis and research findings
backstory: >
You're a meticulous analyst with a keen eye for detail, known for turning
complex data into clear and concise reports.
The {topic} placeholders are interpolated at runtime from the inputs dict you pass to kickoff().
5.2 Define tasks in YAML
config/tasks.yaml:
research_task:
description: >
Conduct thorough research about {topic}. Make sure you find any interesting
and relevant information given the current year is {current_year}.
expected_output: >
A list with 10 bullet points of the most relevant information about {topic}
agent: researcher
reporting_task:
description: >
Review the context you got and expand each topic into a full section for a
report. Make sure the report is detailed and contains all relevant information.
expected_output: >
A fully fledged report with the main topics, each with a full section.
Formatted as markdown without '```'
agent: reporting_analyst
Note
The
agent:key in a task references an agent by its YAML name. The order of tasks in a sequential crew is the order they appear in yourtaskslist.
5.3 Wire it together with @CrewBase
crew.py:
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent
@CrewBase
class MyProject():
"""MyProject crew"""
agents: list[BaseAgent]
tasks: list[Task]
@agent
def researcher(self) -> Agent:
return Agent(config=self.agents_config['researcher'], verbose=True)
@agent
def reporting_analyst(self) -> Agent:
return Agent(config=self.agents_config['reporting_analyst'], verbose=True)
@task
def research_task(self) -> Task:
return Task(config=self.tasks_config['research_task'])
@task
def reporting_task(self) -> Task:
return Task(config=self.tasks_config['reporting_task'], output_file='report.md')
@crew
def crew(self) -> Crew:
"""Creates the MyProject crew"""
return Crew(
agents=self.agents, # collected automatically from @agent methods
tasks=self.tasks, # collected automatically from @task methods
process=Process.sequential,
verbose=True,
)
How the decorators work:
| Decorator | Effect |
|---|---|
@CrewBase |
Marks the class as a crew definition; loads config/agents.yaml into self.agents_config and config/tasks.yaml into self.tasks_config |
@agent |
Registers the method's return value into self.agents |
@task |
Registers the method's return value into self.tasks |
@crew |
Marks the method that assembles and returns the Crew |
5.4 Run it
main.py:
#!/usr/bin/env python
import sys
from datetime import datetime
from my_project.crew import MyProject
def run():
inputs = {'topic': 'AI Agents', 'current_year': str(datetime.now().year)}
MyProject().crew().kickoff(inputs=inputs)
Then:
crewai run
The inputs dict fills the {topic} and {current_year} placeholders in your YAML. The final task's output is written to report.md (because reporting_task set output_file='report.md').
5.5 The pure-Python alternative
You can skip YAML entirely and build everything inline — useful for quick scripts and for the README's Flow examples:
from crewai import Agent, Crew, Process, Task
analyst = Agent(
role="Senior Market Analyst",
goal="Conduct deep market analysis with expert insight",
backstory="You're a veteran analyst known for spotting subtle patterns.",
)
analysis_task = Task(
description="Analyze the {sector} sector for the past {timeframe}.",
expected_output="A detailed market analysis with a confidence score.",
agent=analyst,
)
crew = Crew(
agents=[analyst],
tasks=[analysis_task],
process=Process.sequential,
verbose=True,
)
result = crew.kickoff(inputs={"sector": "tech", "timeframe": "1W"})
print(result.raw)
6. Working with Agents
An Agent is the core worker. At minimum it needs a role, goal, and backstory. Everything else is optional and has sensible defaults.
from crewai import Agent
agent = Agent(
role="Senior Python Engineer",
goal="Write clean, well-tested Python",
backstory="You have 10 years of experience shipping production systems.",
llm="gpt-4o", # model string or an LLM instance
tools=[], # list of BaseTool instances
verbose=True, # stream reasoning to the console
allow_delegation=False, # can this agent hand work to others?
max_iter=25, # max reasoning iterations per task
max_rpm=None, # throttle requests per minute
)
6.1 Everyday agent parameters
These are the parameters you will reach for most often. The exhaustive list is in the Admin Guide.
| Parameter | Type | Default | Purpose |
|---|---|---|---|
role |
str |
— (required) | The agent's job title / identity |
goal |
str |
— (required) | What the agent is trying to achieve |
backstory |
str |
— (required) | Context that shapes the agent's behavior |
llm |
str | BaseLLM |
inferred (OpenAI) | Model to run the agent |
tools |
list[BaseTool] |
[] |
Tools the agent can use |
verbose |
bool |
False |
Print the agent's reasoning steps |
allow_delegation |
bool |
False |
Allow delegating to / asking other agents |
max_iter |
int |
25 |
Max iterations to complete a task |
max_rpm |
int | None |
None |
Max LLM requests per minute |
max_execution_time |
int | None |
None |
Hard timeout (seconds) per task |
max_retry_limit |
int |
2 |
Retries when execution errors |
cache |
bool |
True |
Cache tool results |
memory |
bool | Memory |
None |
Enable per-agent memory (falls back to crew memory) |
knowledge_sources |
list |
None |
Documents to ground this agent |
tools |
list |
[] |
Tools available to the agent |
inject_date |
bool |
False |
Append the current date to each task |
multimodal |
bool |
False |
(Deprecated — pass files natively instead) |
Warning
Several agent parameters are deprecated:
function_calling_llm,reasoning/max_reasoning_attempts(useplanning_config/planninginstead),allow_code_execution/code_execution_mode(the built-in code interpreter was removed — use a sandbox tool like E2B or Daytona), andmultimodal(pass files natively). They still work but emitDeprecationWarningand will be removed in a future release.
6.2 Running an agent standalone
You don't always need a crew. An agent can run on its own with kickoff():
from crewai import Agent
agent = Agent(role="Translator", goal="Translate text", backstory="You are fluent in 20 languages.")
result = agent.kickoff("Translate 'good morning' to French.")
print(result.raw) # -> "bonjour"
For structured output, pass a Pydantic model as response_format:
from pydantic import BaseModel
class Translation(BaseModel):
text: str
language: str
result = agent.kickoff("Translate 'good morning' to French.", response_format=Translation)
print(result.pydantic.text) # "bonjour"
Async variants are available: await agent.kickoff_async(...). When you call kickoff() from inside a running event loop (e.g. an async Flow method), CrewAI automatically returns a coroutine to await.
6.3 Planning (reflect-before-acting)
Have an agent build a plan before executing a task:
agent = Agent(role="Engineer", goal="...", backstory="...", planning=True)
For finer control, pass a PlanningConfig (see Admin Guide for fields like reasoning_effort and max_attempts).
7. Working with Tasks
A Task describes a single unit of work. The two required fields are description and expected_output.
from crewai import Task
task = Task(
description="Summarize the attached quarterly report.",
expected_output="A 5-bullet executive summary.",
agent=analyst, # who runs it (optional in hierarchical process)
output_file="summary.md", # write the result to a file
)
7.1 Everyday task parameters
| Parameter | Type | Default | Purpose |
|---|---|---|---|
description |
str |
— (required) | What to do (supports {placeholders}) |
expected_output |
str |
— (required) | What a good result looks like |
agent |
Agent |
None |
The agent responsible (required for sequential) |
context |
list[Task] |
auto | Tasks whose outputs feed this task |
tools |
list[BaseTool] |
inherits agent's | Tools restricted to this task |
output_file |
str |
None |
Save the raw output to a path |
output_pydantic |
BaseModel |
None |
Parse output into a Pydantic model |
output_json |
BaseModel |
None |
Parse output into JSON matching a model |
async_execution |
bool |
False |
Run this task in a background thread |
human_input |
bool |
False |
Pause for human review of the result |
markdown |
bool |
False |
Instruct the agent to return Markdown |
guardrail |
callable | str |
None |
Validate/transform output before continuing |
callback |
callable |
None |
Run after the task completes |
Important
Set only one of
output_pydanticoroutput_jsonper task — setting both raises a validation error. Useoutput_pydanticwhen you want a typed object back,output_jsonwhen you want adict.
7.2 Structured output
from pydantic import BaseModel
class Report(BaseModel):
title: str
bullets: list[str]
task = Task(
description="Research {topic} and produce a structured report.",
expected_output="A title and 10 bullet points.",
agent=researcher,
output_pydantic=Report,
)
output = crew.kickoff(inputs={"topic": "LLMs"})
report = output.pydantic # a Report instance, if the last task produced one
7.3 Task context (chaining outputs)
By default, a task in a sequential crew receives the previous task's output as context. To wire explicit dependencies, set context:
synthesis = Task(
description="Combine the research and the analysis into one brief.",
expected_output="A one-page brief.",
agent=writer,
context=[research_task, analysis_task], # both outputs are injected
)
7.4 Guardrails (validating output)
A guardrail validates a task's output and can trigger a retry with feedback. Provide a function returning (success, result_or_error), or a natural-language string that an LLM evaluates:
def must_be_json(output):
import json
try:
json.loads(output.raw)
return (True, output)
except Exception as e:
return (False, f"Output is not valid JSON: {e}")
task = Task(
description="Return a JSON object of key metrics.",
expected_output="A JSON object.",
agent=analyst,
guardrail=must_be_json,
guardrail_max_retries=3,
)
Tip
A guardrail given as a plain string (e.g.
guardrail="Ensure the answer cites at least two sources") is evaluated by an LLM. This requires the task's agent to have a valid LLM.
7.5 Human-in-the-loop
Set human_input=True on a task to pause execution and let a human review (and optionally correct) the agent's final answer before the crew proceeds.
8. Connecting to LLMs
By default, agents use OpenAI. CrewAI routes to native provider SDKs for the best providers and falls back to LiteLLM for everything else.
8.1 The simplest way: a model string
agent = Agent(role="...", goal="...", backstory="...", llm="gpt-4o")
agent = Agent(role="...", goal="...", backstory="...", llm="claude-sonnet-4-5")
agent = Agent(role="...", goal="...", backstory="...", llm="gemini/gemini-2.0-flash")
CrewAI infers the provider from the model name (or from a provider/model prefix). Set the matching API key as an environment variable:
| Provider | Env var |
|---|---|
| OpenAI | OPENAI_API_KEY |
| Anthropic | ANTHROPIC_API_KEY |
| Google Gemini | GEMINI_API_KEY / GOOGLE_API_KEY |
| Azure OpenAI | AZURE_API_KEY (+ base/version) |
| AWS Bedrock | standard AWS credentials |
8.2 The LLM object for fine control
from crewai import LLM
llm = LLM(
model="gpt-4o",
temperature=0.2,
max_tokens=2000,
top_p=0.9,
seed=42,
timeout=120,
reasoning_effort="medium", # "none" | "low" | "medium" | "high"
)
agent = Agent(role="...", goal="...", backstory="...", llm=llm)
8.3 Native providers vs. LiteLLM fallback
| Routing | Providers |
|---|---|
| Native SDK (no extra install beyond the provider extra) | openai, anthropic, azure, bedrock, gemini, plus openai_compatible and snowflake |
LiteLLM fallback (install crewai[litellm]) |
openrouter, deepseek, ollama, cerebras, hosted_vllm, dashscope, and 100+ others |
# Local model via Ollama (uses the LiteLLM fallback path)
agent = Agent(role="...", goal="...", backstory="...", llm="ollama/llama3")
Caution
If you specify a model that doesn't match any native provider and LiteLLM is not installed, CrewAI raises an
ImportErrortelling you to runuv add 'crewai[litellm]'. Install the fallback if you use non-native providers.
8.4 Setting the LLM at different levels
| Level | Parameter | Effect |
|---|---|---|
| Per agent | Agent(llm=...) |
The model that agent uses |
| Crew manager | Crew(manager_llm=...) |
The model for the auto-manager in hierarchical |
| Planning | Crew(planning_llm=...) |
The model that builds the crew plan when planning=True |
| Chat | Crew(chat_llm=...) |
The model behind crewai chat |
9. Flows (Event-Driven Orchestration)
Crews give agents autonomy. Flows give you precise, deterministic control: you write Python methods and connect them with event decorators. Flows are the recommended architecture for production systems, and they can run crews as steps.
9.1 The Flow decorators
from crewai.flow.flow import Flow, listen, start, router, or_, and_
| Decorator / helper | Meaning |
|---|---|
@start() |
Entry point(s); runs when the flow is kicked off |
@listen(step) |
Runs after step completes, receiving its output |
@router(step) |
Runs after step and returns a label that routes to @listen("label") |
or_(a, b) |
Trigger when any of the listed steps/labels fire |
and_(a, b) |
Trigger when all of the listed steps/labels fire |
9.2 A complete Flow
from crewai.flow.flow import Flow, listen, start, router, or_
from crewai import Crew, Agent, Task, Process
from pydantic import BaseModel
class MarketState(BaseModel):
sentiment: str = "neutral"
confidence: float = 0.0
recommendations: list = []
class AdvancedAnalysisFlow(Flow[MarketState]):
@start()
def fetch_market_data(self):
self.state.sentiment = "analyzing"
return {"sector": "tech", "timeframe": "1W"}
@listen(fetch_market_data)
def analyze_with_crew(self, market_data):
analyst = Agent(role="Senior Market Analyst", goal="Analyze markets",
backstory="A veteran analyst.")
task = Task(description="Analyze {sector} for {timeframe}",
expected_output="Analysis with a confidence score", agent=analyst)
crew = Crew(agents=[analyst], tasks=[task], process=Process.sequential)
return crew.kickoff(inputs=market_data)
@router(analyze_with_crew)
def determine_next_steps(self):
if self.state.confidence > 0.8:
return "high_confidence"
return "low_confidence"
@listen("high_confidence")
def execute_strategy(self):
return "Executing high-confidence strategy"
@listen(or_("low_confidence"))
def request_more_analysis(self):
self.state.recommendations.append("Gather more data")
return "Additional analysis required"
flow = AdvancedAnalysisFlow()
flow.kickoff()
Key ideas:
- A Flow has a typed state object (here
MarketState). Mutateself.stateto carry data between steps; it persists across the run. @startmethods run first.@listenmethods chain off other methods' completion.@routeradds conditional branching.- Crews are just steps inside Flows — call
crew.kickoff()and return the result.
9.3 Running and visualizing Flows
crewai flow kickoff # run the flow defined in the project
crewai flow plot # render an interactive diagram of the flow graph
crewai flow add-crew <name> # scaffold a new crew inside an existing flow
10. Tools
Tools give agents capabilities beyond text generation — searching the web, reading files, querying databases, scraping pages, running code in a sandbox. Install the tools library with crewai[tools].
10.1 Using a prebuilt tool
from crewai import Agent
from crewai_tools import SerperDevTool # Google search via serper.dev
researcher = Agent(
role="Researcher",
goal="Find current information",
backstory="An expert web researcher.",
tools=[SerperDevTool()],
)
Most search/scrape tools read an API key from the environment (e.g. SERPER_API_KEY).
10.2 What's available
crewai-tools ships ~80 tools. Representative categories:
| Category | Example tools |
|---|---|
| Web search | SerperDevTool, BraveSearchTool, TavilySearchTool, ExaSearchTool, SerpApiGoogleSearchTool |
| Web scraping | ScrapeWebsiteTool, FirecrawlScrapeWebsiteTool, SeleniumScrapingTool, SpiderTool, ScrapflyScrapeWebsiteTool |
| Files / documents | FileReadTool, FileWriterTool, DirectoryReadTool, PDFSearchTool, DOCXSearchTool, CSVSearchTool |
| RAG / vector DB | QdrantVectorSearchTool, MongoDBVectorSearchTool, WeaviateVectorSearchTool, RagTool |
| Databases | NL2SQLTool, MySQLSearchTool, SnowflakeSearchTool, DatabricksQueryTool |
| Code sandboxes | E2BPythonTool, DaytonaPythonTool |
| Vision / media | VisionTool, DallETool, OCRTool, YoutubeVideoSearchTool |
| Automation | ComposioTool, ZapierActionTool, MultiOnTool, ApifyActorsTool |
Note
CrewAI also integrates MCP servers and the CrewAI Platform app catalog (Gmail, Slack, GitHub, Jira, Notion, etc.). Pass
mcps=[...]orapps=[...]to anAgentto expose those as tools. See the Admin Guide for details.
10.3 Writing a custom tool
from crewai.tools import BaseTool
from pydantic import BaseModel, Field
class MultiplyInput(BaseModel):
a: int = Field(..., description="First number")
b: int = Field(..., description="Second number")
class MultiplyTool(BaseTool):
name: str = "multiply"
description: str = "Multiply two integers."
args_schema: type[BaseModel] = MultiplyInput
def _run(self, a: int, b: int) -> str:
return str(a * b)
agent = Agent(role="...", goal="...", backstory="...", tools=[MultiplyTool()])
11. Memory and Knowledge
CrewAI separates memory (what the system remembers from its own runs) from knowledge (documents you provide to ground answers).
11.1 Memory
Enable memory at the crew level so agents recall relevant context across tasks and runs:
crew = Crew(
agents=[...],
tasks=[...],
memory=True, # enables unified memory (backed by LanceDB)
)
You can also enable memory per agent (Agent(memory=True)); if an agent has no memory, it falls back to the crew's. Browse stored memories interactively:
crewai memory # open the Memory TUI
crewai reset-memories --memory # clear stored memories
crewai reset-memories --all # clear memory, knowledge, and kickoff outputs
11.2 Knowledge
Knowledge sources are documents (text, PDF, CSV, JSON, Excel, strings) that agents can search to ground their answers.
from crewai import Crew
from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource
facts = StringKnowledgeSource(content="Our SLA is 99.95% uptime. Support hours are 9-5 ET.")
crew = Crew(
agents=[...],
tasks=[...],
knowledge_sources=[facts],
)
Available source types include StringKnowledgeSource, TextFileKnowledgeSource, PDFKnowledgeSource, CSVKnowledgeSource, JSONKnowledgeSource, ExcelKnowledgeSource, and CrewDoclingSource (install crewai[docling]). Reset knowledge with crewai reset-memories --knowledge.
12. Common Workflows
12.1 Sequential vs. hierarchical process
from crewai import Crew, Process
# Sequential: tasks run in order; each task needs an agent.
crew = Crew(agents=[a, b], tasks=[t1, t2], process=Process.sequential)
# Hierarchical: an auto-manager delegates tasks; requires manager_llm or manager_agent.
crew = Crew(
agents=[a, b],
tasks=[t1, t2],
process=Process.hierarchical,
manager_llm="gpt-4o",
)
Important
In
hierarchicalmode you must set eithermanager_llmormanager_agent. The manager coordinates planning, delegation, and validation, so tasks don't each need a pre-assigned agent. Do not include the manager agent in theagentslist.
12.2 Run a crew over many inputs
results = crew.kickoff_for_each(inputs=[
{"topic": "AI"},
{"topic": "Robotics"},
{"topic": "Biotech"},
])
for r in results:
print(r.raw)
Async equivalents exist: await crew.kickoff_async(...) and await crew.kickoff_for_each_async(...).
12.3 Inspect the result
kickoff() returns a CrewOutput:
output = crew.kickoff(inputs={"topic": "AI"})
print(output.raw) # final text output
print(output.pydantic) # typed output, if the last task used output_pydantic
print(output.json_dict) # dict output, if the last task used output_json
print(output.tasks_output) # per-task outputs
print(output.token_usage) # token usage metrics
12.4 Train, test, and replay
crewai train -n 5 -f trained_agents.pkl # iteratively improve with human feedback
crewai test -n 3 -m gpt-4o-mini # score the crew's output quality
crewai replay -t <task_id> # re-run from a specific task
crewai log-tasks-outputs # list the latest kickoff task outputs
Tip
crewai replayresumes from a task you've already run, reusing earlier outputs. Usecrewai log-tasks-outputsto find thetask_idto replay from.
12.5 Stream output
crew = Crew(agents=[...], tasks=[...], stream=True)
for chunk in crew.kickoff(inputs={"topic": "AI"}):
print(chunk, end="", flush=True)
13. The CrewAI CLI
The crewai command is your control surface for projects. Run crewai --help or crewai <command> --help for full details.
13.1 Everyday commands
| Command | Purpose |
|---|---|
crewai create crew <name> |
Scaffold a new crew project |
crewai create flow <name> |
Scaffold a new flow project |
crewai install |
Install project dependencies (via UV) |
crewai run |
Run the crew (crew().kickoff()) |
crewai update |
Migrate a project's pyproject.toml to UV |
crewai version [--tools] |
Print the installed CrewAI (and tools) version |
crewai train -n <N> -f <file> |
Train the crew over N iterations |
crewai test -n <N> -m <model> |
Test/evaluate the crew |
crewai replay -t <task_id> |
Replay from a task |
crewai chat |
Start an interactive chat with the crew |
crewai reset-memories [flags] |
Clear memory / knowledge / outputs |
crewai memory |
Open the Memory browser TUI |
13.2 Flow, tools, and config commands
| Command | Purpose |
|---|---|
crewai flow kickoff / plot / add-crew <name> |
Run, visualize, or extend a flow |
crewai tool create/install/publish <handle> |
Work with the tool repository |
crewai template list/add <name> |
Browse and install project templates |
crewai config list/set/reset |
Manage CLI configuration |
crewai env view |
View tracing-related environment variables |
crewai uv <args> |
Run uv with CrewAI tool credentials injected |
13.3 Cloud (CrewAI AMP) commands
| Command | Purpose |
|---|---|
crewai login / crewai logout [--reset] |
Sign in / out of CrewAI AMP |
crewai deploy create/list/push/status/logs/remove |
Manage cloud deployments |
crewai deploy validate |
Run pre-deploy checks locally |
crewai org list/switch <id>/current |
Manage organizations |
crewai traces enable/disable/status |
Control trace collection |
Note
A few command groups are gated.
crewai experimental skill ...requiresCREWAI_EXPERIMENTAL=1in your environment.crewai checkpoint ...(list/info/resume/diff/prune) manages execution checkpoints when checkpointing is enabled.
14. Troubleshooting
Error: Attribute manager_llm or manager_agent is required when using hierarchical process
Cause: You set process=Process.hierarchical without giving the crew a manager.
Solution: Add manager_llm="gpt-4o" (or a manager_agent=...) to the Crew.
Prevention: Only use hierarchical when you want a coordinating manager; otherwise use sequential.
Error: The task '...' has no agent assigned, therefore it can't be executed directly
Cause: A task in a sequential crew (or run standalone) has no agent.
Solution: Assign agent=... to the task, or run it under a hierarchical process where the manager delegates.
Error: Only one output type can be set, either output_pydantic or output_json
Cause: A task sets both output_pydantic and output_json.
Solution: Keep exactly one.
Error: Unable to initialize LLM with model '...' / Error importing native provider
Cause: The model isn't a native provider and LiteLLM isn't installed, or a provider SDK is missing.
Solution: Install the fallback (uv add 'crewai[litellm]') or the provider extra (e.g. crewai[anthropic]).
Error: Path traversal attempts are not allowed in output_file paths
Cause: An output_file contains .., ~, $, or shell metacharacters.
Solution: Use a plain relative path like report.md or outputs/report.md.
Error: description / expected_output must be provided either directly or through config
Cause: A Task is missing a required field (often a typo in a YAML key referenced via config=).
Solution: Ensure both description and expected_output exist, directly or in the YAML you pass to Task(config=...).
Error: Guardrail function must accept exactly one parameter
Cause: A guardrail callable has the wrong signature.
Solution: It must take exactly one argument (the TaskOutput) and return (bool, result_or_error).
Issue: Agent runs forever / hits the iteration cap
Cause: The task is under-specified or the agent loops on tool calls.
Solution: Tighten expected_output, lower max_iter, or set max_execution_time to cap runtime.
Issue: No output written to output_file on Windows
Cause: Cross-platform file-writing quirks.
Solution: Use FileWriterTool from crewai_tools (pip install 'crewai[tools]'), which CrewAI recommends for portable writes.
15. Frequently Asked Questions
Q: Does CrewAI depend on LangChain? No. CrewAI is built from scratch with no dependency on LangChain or other agent frameworks. This keeps it lean and fast.
Q: What's the difference between Crews and Flows? Crews are teams of agents with autonomy — great when you want flexible, collaborative problem-solving. Flows are event-driven workflows with precise control and branching — great for production pipelines. They compose: run crews as steps inside flows.
Q: Sequential or hierarchical — which process should I use?
Use sequential (the default) when tasks have a clear order. Use hierarchical when you want a manager agent to plan, delegate, and validate dynamically (requires manager_llm or manager_agent).
Q: Can I use local models?
Yes. Install crewai[litellm] and point an agent at, e.g., llm="ollama/llama3". Tools like Ollama and LM Studio work well.
Q: How do I get structured output instead of free text?
Set output_pydantic=YourModel (typed object) or output_json=YourModel (dict) on the final task, then read output.pydantic / output.json_dict from the CrewOutput.
Q: How do I give an agent tools?
Install crewai[tools], import a tool from crewai_tools, and pass it in Agent(tools=[Tool()]). You can also write custom tools by subclassing BaseTool.
Q: How do I pass runtime values into my YAML agents/tasks?
Use {placeholder} in your YAML and pass a matching inputs={"placeholder": value} dict to kickoff().
Q: Does CrewAI collect data?
CrewAI collects anonymous telemetry (versions, OS, counts, process type — never your prompts, data, or secrets). Disable it with OTEL_SDK_DISABLED=true. Opt into richer sharing per-crew with share_crew=True.
Q: Can I pause for human review?
Yes. Set human_input=True on a task to pause for review of the agent's final answer.
Q: How do I run the same crew over many inputs?
Use crew.kickoff_for_each(inputs=[...]) (or the async variant) to run once per input dict and collect all results.
Q: Where do I find more examples? The crewAI-examples repository has trip planners, stock analysis, job postings, and Crew+Flow combinations.
Q: Can I resume a long run?
Yes, when checkpointing is enabled. Use the crewai checkpoint commands (list, resume, diff, prune) or crew.kickoff(from_checkpoint=...).
16. Quick Reference
Minimal crew
from crewai import Agent, Crew, Process, Task
a = Agent(role="Writer", goal="Write", backstory="You write well.")
t = Task(description="Write a haiku about {topic}.", expected_output="A haiku.", agent=a)
crew = Crew(agents=[a], tasks=[t], process=Process.sequential)
print(crew.kickoff(inputs={"topic": "the sea"}).raw)
CLI cheat sheet
| Command | Does |
|---|---|
crewai create crew <name> |
New crew project |
crewai create flow <name> |
New flow project |
crewai install |
Install deps |
crewai run |
Run the crew |
crewai flow kickoff |
Run the flow |
crewai train -n N -f f.pkl |
Train |
crewai test -n N -m model |
Evaluate |
crewai replay -t <id> |
Replay from a task |
crewai reset-memories -a |
Reset all memory |
crewai chat |
Chat with the crew |
Key environment variables
| Variable | Purpose |
|---|---|
OPENAI_API_KEY |
Default LLM provider key |
ANTHROPIC_API_KEY / GEMINI_API_KEY / … |
Other provider keys |
SERPER_API_KEY |
Web search via SerperDevTool |
OTEL_SDK_DISABLED |
Set true to disable telemetry |
CREWAI_TRACING_ENABLED |
Set true to enable trace collection |
CREWAI_EXPERIMENTAL |
Set 1 to unlock experimental CLI commands |