Course Content
CrewAI Multi-Agents
9 sections · 53 lessons
What is a Crew in CrewAI, and how does it manage execution?
What you need to know
What happens inside kickoff
- Before kickoff — optional hooks (
@before_kickoffin a@CrewBaseclass) can clean or add inputs. - Interpolate —
{placeholders}in agent and task text are filled frominputs. - Run tasks — in list order; each task goes to its agent (sequential) or to the manager (hierarchical).
- Pass context — each task receives earlier outputs, all of them by default or those named in
context. - Check —
output_pydanticconversion and guardrails; failed checks retry the task. - Return — a
CrewOutput;@after_kickoffhooks can post-process it.
Reading the result
1result = crew.kickoff(inputs={"city": "Indore", "category": "cloud kitchens"})23result.raw # last task's text4result.pydantic # last task's model, if it set output_pydantic5result.tasks_output # list of TaskOutput, one per task, in order6result.token_usage # prompt, completion and total tokenstasks_output and token_usage are the cheapest debugging and cost data you get: which task produced what, and what it cost.
Running many times
| Method | Behaviour |
|---|---|
kickoff(inputs) | one run, blocking |
kickoff_for_each(inputs=[...]) | one run per input, one after another |
akickoff(inputs) | one run with native async, for use inside async code |
akickoff_for_each(inputs=[...]) | one run per input, concurrently |
replay(task_id=...) | re-run from a task, reusing saved outputs of earlier tasks |
From the command line, crewai run runs the project, crewai log-tasks-outputs lists the saved task IDs from the last run, and crewai replay -t <task_id> replays from one.
Crew-wide settings worth knowing
memory=True— shared memory across tasks and runs.cache=True— reuse identical tool results (off by default since CrewAI 1.15.3).max_rpm— a request-rate limit for the whole crew.step_callback,task_callback— your functions called after each agent step and each task.planning=True— a planner writes a plan for every task before the run.
A real-life example
A market-research team at a cloud-kitchen chain needs the same competitor scan for 12 cities every Monday. The crew has a researcher, a pricing analyst and a writer.
They first called kickoff_for_each with 12 inputs and wondered why it took 18 minutes: it runs the cities one after another, about 90 seconds each. Switching to await crew.akickoff_for_each(inputs=cities) ran them concurrently, and with max_rpm=60 to respect the provider's limit the whole batch took about 4 minutes.
One Monday the writer task failed for Pune because the model timed out. Instead of re-running research (the expensive part), they used crewai log-tasks-outputs to find the writer task's ID and crewai replay -t <id>, which reused the saved research and analysis. token_usage from each result went into a cost dashboard: about Rs 14 per city.
Follow-up questions to expect
- "Where do I put setup logic, like loading a customer record?" — In a
@before_kickoffmethod in the@CrewBaseclass, or in the Flow step that calls the crew. - "Is a Crew object reusable?" — Yes for repeated kickoffs, but
kickoff_for_eachcopies it per input so runs do not share task outputs. Create fresh crews per request in a web server to avoid shared state. - "How do I stream output to a UI?" — Set
stream=Trueon the crew and iterate the streaming output, or listen to CrewAI events.