Sistava

CrewAI Tutorial: How to Build Your First Crew in Python

How-to — — by Mahmoud Zalt

A step by step CrewAI tutorial: install it, define agents and tasks, run your first crew, and read the output. Real, runnable Python.

CrewAI is a Python framework for orchestrating several LLM agents that work on one goal together. You describe each agent as a role with a goal and a backstory, you describe the work as tasks, and the framework builds the prompts, runs the calls, and passes output from one step to the next.

This walkthrough gets you from an empty folder to a crew that produces a real answer. Every command and every parameter below comes from the current documentation, and the sources are listed at the end so you can check anything yourself.

One thing to settle before you start. CrewAI has moved fast, and the shape of a project has changed between versions. Code you find in an old tutorial may import from a path that no longer exists, or scaffold a folder layout the current CLI does not produce. Always check what your installed version does before you debug someone else's snippet.

What do you need before you start?

You need a supported Python, the CrewAI package, and credentials for one model provider. The installation docs state the supported range as Python 3.10 or newer and below 3.14, and they use the uv package manager for both the CLI and project dependencies.

Run that last command and write the number down. Half the confusing errors in this ecosystem come from following a guide written for a different version. The docs also ship a tools extra, installed with pip install 'crewai[tools]', which you will want later but do not need for a first run.

What are agents, tasks and crews?

An Agent is a persona with capabilities, a Task is a unit of work with a description and an expected output, and a Crew is the container that owns both and decides the order. The framework turns the agent fields and the task fields into the prompt it sends to the model.

The field that matters most is expected_output. A vague expected output produces a vague answer, because that string is most of what the model is told about the finish line. Write it the way you would brief a contractor: format, length, and what counts as done.

How do you write your first crew in one file?

Put everything in one file first. The CLI scaffold is useful later, but a single file makes the moving parts visible, and you can delete it without regret. Save the following as first_crew.py.

Two details in there are worth pausing on. The curly braces in the agent goals and the task descriptions are placeholders, filled from the dictionary you pass to kickoff, which is why the same file can research any topic. And context=[research_task] is what makes the writer see the researcher's output rather than starting from nothing.

In a sequential process the docs say each task's output is already available as context for the tasks that follow, so the explicit context list is belt and braces. It becomes essential the moment you reorder tasks or move to a different process type, so it is a good habit from day one.

How do you run it and read the output?

Export a model and a key, then run the file like any Python script. With verbose=True you will watch each agent think and hand off in the terminal, which is the fastest way to understand what the framework is actually sending.

The return value is not a string. It is a CrewOutput object, and the documented attributes tell you far more than a print of the final text.

Get in the habit of printing token_usage on every run while you are learning. A crew is a loop of model calls, and the cost of a design choice is invisible until you look at the counter. A prompt that reads a little better but doubles the iterations is a bad trade you will not notice otherwise.

Once the single file works, the natural next question is where the code should live. Hardcoding prompts inside Python gets awkward as soon as two people edit the same crew, and every prompt tweak becomes a code review. That is the problem the project scaffold exists to solve.

Should you use the CLI scaffold instead?

Use the scaffold once your crew outgrows one file. The CLI generates a project with configuration separated from code, so prompts live in data files rather than Python strings. Note that the default scaffold format changed: the current docs generate JSONC configuration, and the older Python plus YAML layout is now behind a flag.

This is the single biggest reason old tutorials stop matching your terminal. If a guide tells you to open config/agents.yaml and that file is not there, you almost certainly scaffolded with the current default rather than the classic one. Run the command with --classic, or read the JSONC files the docs describe.

From nothing to a working crew

  1. Check Python and install — Confirm your interpreter sits in the supported range, install the CLI or the library, then run crewai version and note it down.
  2. Set a model and a key — Export MODEL as provider/model-id along with the matching provider API key. Pass an explicit LLM object if you want no ambiguity about what is being called.
  3. Write two agents and two tasks — Give each agent a role, goal and backstory. Give each task a description and a precise expected_output. Chain them with context.
  4. Kick off with verbose on — Call crew.kickoff(inputs={...}) and watch the terminal. The verbose trace shows you exactly which agent produced which text.
  5. Read the output object — Print raw, tasks_output and token_usage. Tighten the expected_output strings, then run again and compare both quality and tokens.
  6. Move to the scaffold — When the file gets long or a second person joins, generate a project with crewai create crew and move prompts into configuration.

The step most people skip is the fourth one. Reading the verbose trace for two full runs teaches you more about prompt design than any article can, because you see the exact text the model received and the exact point where it went sideways.

What trips people up on the first run?

The most common first failure is a credentials error that names OpenAI even when you chose a different provider. It is a well-populated topic in the CrewAI community forum, and the cause is usually that some component fell back to a default rather than the model you configured.

It is worth being honest about what you have built at this point. A working crew is genuinely satisfying, and if the thing you are making is a product, this is exactly the right foundation to keep pushing on. The framework rewards people who want that control.

Some readers land here for a different reason. They wanted the outcome, a weekly research briefing or a drafted reply, and building a pipeline was the only route they knew. That is the case we built Sistava for. You hire an AI Employee, tell it in plain English what you want handled, and it arrives with tools connected and asks you when it is unsure. There is no crew to assemble and nothing to maintain when the library changes.

Neither route is the smart one in general. They answer different questions. If your goal is a system you own, shape and ship, a framework is the right tool and you should keep going with it. If your goal is the work getting done, the setup you just did is overhead you can skip.

Whichever way you go, the concepts transfer. Roles, clear expected outputs and explicit handoffs are what make any set of agents produce something useful, whether you wrote the orchestration yourself or not.

Frequently asked questions

FAQ

Do I need an OpenAI key to use CrewAI?

No. The documentation lists native integrations for several providers including Anthropic, Google Gemini, Azure and AWS Bedrock, plus a LiteLLM fallback for others and local models through Ollama. That said, an OpenAI key error is a common report in their community forum even when another provider is configured, because some components can fall back to a default. Passing an explicit LLM object to each agent is the simplest way to avoid the ambiguity.

What Python version does CrewAI need?

The installation documentation states Python 3.10 or newer and below 3.14 at the time of writing. Check python3 --version before installing, and re-check the docs for your version, since supported ranges move as the project releases.

What is the difference between an agent and a task in CrewAI?

An agent is who does the work: a role, a goal and a backstory, plus any tools and model settings. A task is what gets done: a description, an expected output, and optionally which agent owns it. One agent can carry several tasks, and in a sequential crew the tasks run in the order you list them.

How do I pass one task's output into the next one?

Set the context parameter on the later task to a list of earlier Task objects, for example context=[research_task]. The documentation also notes that in a sequential process each task's output is available as context to the tasks that follow, but naming it explicitly makes the dependency obvious and survives reordering.

Should I write my crew in Python, YAML or JSONC?

Start in a single Python file so you can see every moving part. When the crew grows or a second person edits it, generate a project with crewai create crew, which currently produces a JSONC configuration layout. The older Python plus YAML layout is still available behind the --classic flag.

How much does it cost to run a crew?

It depends entirely on your model provider's per-token pricing and how many iterations your agents take, so no fixed figure is meaningful. Print result.token_usage or crew.usage_metrics after each run and multiply by your provider's published rates. Lowering max_iter while you develop keeps a misbehaving prompt from running up a large bill.

If you got a briefing out of that script, you now understand the whole model. Everything else in CrewAI, tools, process types, flows and memory, is a variation on agents, tasks and a crew that runs them. Add one concept at a time and read the verbose trace after each addition.

Sources