# CrewAI User Guide

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.

```bash
# 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
```

```text
# 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](https://docs.astral.sh/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](#3-project-structure)).
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)"

    ```bash
    uv pip install crewai
    ```

=== "pip"

    ```bash
    pip install crewai
    ```

To include the optional tools library (`crewai-tools`, ~80 prebuilt tools):

```bash
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:

```bash
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](#8-connecting-to-llms).

### 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:

```text
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](#9-flows-event-driven-orchestration).

---

## 4. Core Concepts

CrewAI has a small set of building blocks. Understanding these five concepts is enough to build almost anything.

```text
   ┌─────────┐   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`:

```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`:

```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`:

```python
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`:

```python
#!/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:

```bash
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:

```python
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.

```python
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()`:

```python
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`:

```python
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:

```python
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`.

```python
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

```python
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`:

```python
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:

```python
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

```python
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

```python
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 |

```python
# 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

```python
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

```python
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

```bash
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

```python
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

```python
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:

```python
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:

```bash
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.

```python
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

```python
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

```python
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`:

```python
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

```bash
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

```python
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](https://github.com/crewAIInc/crewAI-examples) 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

```python
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 |

---

_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. Unofficial; not affiliated with or reviewed by the project._
