Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

CrewAI User Guide

Generated June 2026 from crewAIInc/crewAI at aed6923

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

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 crewai and crewai install — they are faster and produce reproducible lockfiles.

What just happened:

  1. crewai create crew generated a project (see §3).
  2. Two agents (researcher, reporting_analyst) were defined in YAML.
  3. Two tasks were defined in YAML and assigned to those agents.
  4. crewai run executed crew().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 crewai package already depends on crewai-core and crewai-cli, so the crewai command is available immediately after install. The [tools] extra only adds the separate crewai-tools package.

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 litellm extra — 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 your tasks list.

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 (use planning_config / planning instead), allow_code_execution / code_execution_mode (the built-in code interpreter was removed — use a sandbox tool like E2B or Daytona), and multimodal (pass files natively). They still work but emit DeprecationWarning and 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_pydantic or output_json per task — setting both raises a validation error. Use output_pydantic when you want a typed object back, output_json when you want a dict.

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 ImportError telling you to run uv 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). Mutate self.state to carry data between steps; it persists across the run.
  • @start methods run first. @listen methods chain off other methods' completion. @router adds 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=[...] or apps=[...] to an Agent to 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 hierarchical mode you must set either manager_llm or manager_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 the agents list.

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 replay resumes from a task you've already run, reusing earlier outputs. Use crewai log-tasks-outputs to find the task_id to 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 ... requires CREWAI_EXPERIMENTAL=1 in 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