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