---
title: Quickstart
description: Build your first CrewAI Flow in minutes — orchestration, state, and an agent crew that produces a real report.
icon: rocket
mode: "wide"
---
### Watch: Building CrewAI Agents & Flows with Coding Agent Skills
Install our coding agent skills (Claude Code, Codex, ...) to quickly get your coding agents up and running with CrewAI.
You can install it with `npx skills add crewaiinc/skills`
In this guide you will **create a Flow** that sets a research topic, runs a **crew with one agent** (a researcher using web search), and ends with a **markdown report** on disk. Flows are the recommended way to structure production apps: they own **state** and **execution order**, while **agents** do the work inside a crew step.
If you have not installed CrewAI yet, follow the [installation guide](/en/installation) first.
## Prerequisites
- Python environment and the CrewAI CLI (see [installation](/en/installation))
- An LLM configured with the right API keys — see [LLMs](/en/concepts/llms#setting-up-your-llm)
- A [Serper.dev](https://serper.dev/) API key (`SERPER_API_KEY`) for web search in this tutorial
## Build your first Flow
From your terminal, scaffold a Flow project (the folder name uses underscores, e.g. `latest_ai_flow`):
```shell Terminal
crewai create flow latest-ai-flow
cd latest_ai_flow
```
This creates a Flow app under `src/latest_ai_flow/`, including a starter crew under `crews/content_crew/` that you will replace with a minimal **single-agent** research crew in the next steps.
Create `src/latest_ai_flow/crews/content_crew/agents/researcher.jsonc` (create the `agents/` directory if needed). Variables like `{topic}` are filled from `crew.kickoff(inputs=...)`.
```jsonc agents/researcher.jsonc
{
"role": "{topic} Senior Data Researcher",
"goal": "Uncover cutting-edge developments in {topic}",
"backstory": "You're a seasoned researcher who finds relevant information and presents it clearly.",
"tools": ["SerperDevTool"],
"settings": {
"verbose": true
}
}
```
Create `src/latest_ai_flow/crews/content_crew/crew.jsonc`:
```jsonc crew.jsonc
{
"name": "Research Crew",
"agents": ["researcher"],
"tasks": [
{
"name": "research_task",
"description": "Conduct thorough research about {topic}. Use web search to find recent, credible information.",
"expected_output": "A markdown report with clear sections: key trends, notable tools or companies, and implications. Aim for 800-1200 words. No fenced code blocks around the whole document.",
"agent": "researcher",
"output_file": "output/report.md",
"markdown": true
}
],
"process": "sequential",
"verbose": true
}
```
Replace the generated `content_crew.py` with a small loader that turns `crew.jsonc` into a `Crew`.
```python content_crew.py
# src/latest_ai_flow/crews/content_crew/content_crew.py
from pathlib import Path
from crewai.project import load_crew
def kickoff_content_crew(inputs: dict):
crew, default_inputs = load_crew(Path(__file__).with_name("crew.jsonc"))
return crew.kickoff(inputs={**default_inputs, **inputs})
```
Connect the crew to a Flow: a `@start()` step sets the topic in **state**, and a `@listen` step runs the crew. The task’s `output_file` still writes `output/report.md`.
```python main.py
# src/latest_ai_flow/main.py
from pydantic import BaseModel
from crewai.flow import Flow, listen, start
from latest_ai_flow.crews.content_crew.content_crew import kickoff_content_crew
class ResearchFlowState(BaseModel):
topic: str = ""
report: str = ""
class LatestAiFlow(Flow[ResearchFlowState]):
@start()
def prepare_topic(self, crewai_trigger_payload: dict | None = None):
if crewai_trigger_payload:
self.state.topic = crewai_trigger_payload.get("topic", "AI Agents")
else:
self.state.topic = "AI Agents"
print(f"Topic: {self.state.topic}")
@listen(prepare_topic)
def run_research(self):
result = kickoff_content_crew(inputs={"topic": self.state.topic})
self.state.report = result.raw
print("Research crew finished.")
@listen(run_research)
def summarize(self):
print("Report path: output/report.md")
def kickoff():
LatestAiFlow().kickoff()
def plot():
LatestAiFlow().plot()
if __name__ == "__main__":
kickoff()
```
If your package name differs from `latest_ai_flow`, change the `kickoff_content_crew` import to match your project’s module path.
In `.env` at the project root, set:
- `SERPER_API_KEY` — from [Serper.dev](https://serper.dev/)
- Your model provider keys as required — see [LLM setup](/en/concepts/llms#setting-up-your-llm)
```shell Terminal
crewai install
crewai run
```
`crewai run` executes the Flow entrypoint defined in your project (same command as for crews; project type is `"flow"` in `pyproject.toml`).
You should see logs from the Flow and the crew. Open **`output/report.md`** for the generated report (excerpt):
```markdown output/report.md
# AI Agents: Recent Landscape and Trends
## Executive summary
…
## Key trends
- **Tool use and orchestration** — …
- **Enterprise adoption** — …
## Implications
…
```
Your actual file will be longer and reflect live search results.
## How this run fits together
1. **Flow** — `LatestAiFlow` runs `prepare_topic` first, then `run_research`, then `summarize`. State (`topic`, `report`) lives on the Flow.
2. **Crew** — `kickoff_content_crew` loads `crew.jsonc` and runs one task with one agent: the researcher uses **Serper** to search the web, then writes the structured report.
3. **Artifact** — The task’s `output_file` writes the report under `output/report.md`.
To go deeper on Flow patterns (routing, persistence, human-in-the-loop), see [Build your first Flow](/en/guides/flows/first-flow) and [Flows](/en/concepts/flows). For crews without a Flow, see [Crews](/en/concepts/crews). For a single `Agent` and `kickoff()` without tasks, see [Agents](/en/concepts/agents#direct-agent-interaction-with-kickoff).
You now have an end-to-end Flow with an agent crew and a saved report — a solid base to add more steps, crews, or tools.
### Naming consistency
The names in `crew.jsonc` must match the files and task references you use:
- `agents: ["researcher"]` loads `agents/researcher.jsonc`
- `tasks[].agent: "researcher"` assigns the task to that agent
## Deploying
Push your Flow to **[CrewAI AMP](https://app.crewai.com)** once it runs locally and your project is in a **GitHub** repository. From the project root:
```bash Authenticate
crewai login
```
```bash Create deployment
crewai deploy create
```
```bash Check status & logs
crewai deploy status
crewai deploy logs
```
```bash Ship updates after you change code
crewai deploy push
```
```bash List or remove deployments
crewai deploy list
crewai deploy remove
```
The first deploy usually takes **around 1 minute**. Full prerequisites and the web UI flow are in [Deploy to AMP](/en/enterprise/guides/deploy-to-amp).
Step-by-step AMP deployment (CLI and dashboard).
Discuss ideas, share projects, and connect with other CrewAI developers.