Module 03
CrewAI Role-Based Crews
On this page
In plain words
Think of a project team where one person researches, one writes and one checks. CrewAI lets you build that with agents. You give each agent a role and a goal, wrap the work into tasks, and pick how the order is decided. For production you wrap the whole thing in a Flow, which is plain code, so every run can be replayed.
How it flows
- 1Define agents
- 2Write tasks
- 3Put in a crew
- 4Pick the process
- 5Kickoff
- 6Read the output
A tiny example
researcher = Agent(role="Researcher", goal="find facts")
writer = Agent(role="Writer", goal="draft a brief")
tasks = [
Task("collect facts", expected_output="5 bullets", agent=researcher),
Task("write brief", expected_output="120 words", agent=writer),
]
crew = Crew(tasks=tasks, process="sequential")
print(crew.kickoff(topic="Infosys"))Notice the agents never call each other: the tasks name the agents, and the process decides the order.
What you will learn
- The four building blocks of CrewAI: Agent, Task, Crew, Process.
- The difference between a Crew (agents decide) and a Flow (your code decides).
- When to use Sequential order and when to pay for a manager agent.
- The three ways role-based teams break in real projects.
The problem, simply
Think about your final-year project team. Priya does the research, Rahul writes the report, Karthik checks it before submission. Nobody wrote a rulebook. Each of you knew your role and passed work along.
That works beautifully in the lab. But suppose the guide asks, "Who changed section 3 on Tuesday night?" Nobody remembers. The work got done, but you cannot replay it.
Software teams hit exactly this wall with AI agents. Three agents with nice roles, a great demo. Then a customer files a bug and you need to know which agent did what, or your manager asks what one run costs. A free-flowing team cannot answer that.
The other extreme is a hardcoded pipeline. That answers everything, but leaves the agent no room to explore. So the skill is knowing which parts of your product need freedom and which parts need a receipt.
The idea
CrewAI is a Python framework for building teams of agents, each with a named role. Its surface is tiny: learn four words and the rest is configuration.
The four building blocks
- Agent — a worker with a
role("Senior Researcher"), agoal("find three solid sources"), a shortbackstorythat shapes its tone and judgment, and a list of tools it may call. - Task — one unit of work: a
description, anexpected_output(the shape the answer must take), the assigned agent, and optionally earlier tasks whose output is passed in as context. - Crew — the container. It holds the agents, the tasks, and the process.
- Process — the execution strategy. How the crew decides who works next.
Here is the part people get wrong. Agents do not talk to each other directly. Tasks point at agents. The Crew holds the tasks. The Process picks the order. That is the whole mental model.
- 1Agent has role
- 2Task assigns agent
- 3Crew holds tasks
- 4Process picks order
- 5Output
Sequential, Hierarchical, and one that does not exist yet
Sequential runs tasks in the order you declared them. Output of task 1 goes into task 2 as context. Cheapest, most predictable. Use it when the order is obvious.
Hierarchical adds a manager agent. Before each round, the manager makes its own model call, looks at the task list and what has been produced so far, and picks who works next. It can even refuse and re-route.
That manager call is not free. A five-task crew now makes six model calls, and the manager's call carries the whole task list plus every prior output. Token cost can easily triple. Pay it only when the order truly depends on what came out earlier — roughly, four or more specialists.
Consensus is a name reserved in the docs for a future voting-based process. It is not implemented. Do not build on it.
WarningWarning: Hierarchical is not "better" than Sequential. It is more expensive and less predictable. Start Sequential and upgrade only when routing actually needs judgment.
Crew versus Flow
This is the real interview question.
A Crew is autonomy-first. The framework decides the shape at runtime. Great for research, brainstorming, first drafts — anywhere the path taken is part of the answer. Cheap to prototype, painful to replay.
A Flow is an event-driven graph you own in plain Python. One function is the start. Others listen for a named event and fire when it is emitted. Every step is ordinary code, so you can test it, log it, and diff a bad run against a good one.
The framework's own advice for production: start with a Flow, then call a Crew inside a Flow step when the exploration is worth it. Audit trail from the Flow, creativity from the Crew.
Remember: Flow for the receipt, Crew for the exploration. Compose them; do not choose one forever.
- 1Flow starts
- 2Step emits event
- 3Crew explores
- 4Flow logs result
- 5Next step
A worked example
Suppose Ananya builds a tool that writes a one-page company brief before a placement interview. Three agents: Researcher, Writer, Editor.
Sequential run: the Researcher collects five facts. That output goes to the Writer as context, who drafts 200 words. The Editor trims it to 120. Three model calls, fixed order, same shape every time.
Now she switches to Hierarchical. A manager runs first and says "Researcher". Then again: "Writer". Then "Editor". Then "done". Four extra calls, and the brief came out the same. For a fixed pipeline, Hierarchical is pure cost.
Tools and typed outputs
You attach a tool either by decorating a plain function — the signature becomes the schema, the docstring becomes the description the model reads — or by writing a small tool class when the tool needs state like a database client. Ready-made tools exist for file reading, web search, and running code.
You can also force a Task to return a typed object instead of free text. Do this whenever a later task reads the result. If task 1 promises "an outline" and produces four sections while task 2 expects three, task 2 will just make something up. A typed contract stops that.
Memory
CrewAI ships four kinds of memory, and a crew can use all four together.
- Short-term — the conversation buffer inside one run. Wiped at the end.
- Long-term — survives across runs, stored in a vector database, fetched by similarity to the current task.
- Entity — facts keyed to a specific thing. "This customer is on the enterprise plan." Survives across runs.
- Contextual — pulled in at the moment the agent needs it, instead of loaded upfront.
TipTip: Do not switch long-term memory on for every task. Every run writes more rows, and retrieval slowly gets noisier. Store only facts that should still be true next month.
Build it
This toy version uses only the standard library. No network, no API key. It mimics the four building blocks so you can see how work threads from one agent to the next.
"""A tiny role-based crew, standard library only."""
from dataclasses import dataclass, field
# --- Fake "model". Real CrewAI would call an LLM here. ---
def fake_model(role, prompt):
if role == "Researcher":
return "facts: campus hiring; three rounds; online test first"
if role == "Writer":
return "draft: " + prompt.split("facts: ")[-1][:40] + " ..."
if role == "Editor":
return "final: " + prompt.split("draft: ")[-1].strip()
return "done"
@dataclass
class Agent:
role: str
goal: str
backstory: str = "" # keep this short, it eats context
@dataclass
class Task:
description: str
expected_output: str
agent: Agent
context: list = field(default_factory=list) # outputs of earlier tasks
@dataclass
class Crew:
tasks: list
memory: dict = field(default_factory=dict) # survives across kickoffs
def kickoff(self, topic):
"""Sequential process: run tasks in declaration order."""
outputs = []
for i, task in enumerate(self.tasks, 1):
prompt = f"{task.description} about {topic}. " + " ".join(task.context)
result = fake_model(task.agent.role, prompt)
print(f" step {i} [{task.agent.role}] -> {result}")
# thread this output forward as context for the next task
if i < len(self.tasks):
self.tasks[i].context.append(result)
outputs.append(result)
self.memory["last_brief"] = outputs[-1]
return outputs[-1]
researcher = Agent("Researcher", "find solid facts")
writer = Agent("Writer", "turn facts into a short draft")
editor = Agent("Editor", "tighten the draft")
crew = Crew([
Task("Collect facts", "5 bullet facts", researcher),
Task("Write a brief", "200 word draft", writer),
Task("Edit the brief", "120 word final", editor),
])
print("CREW (agents flow, order fixed by you):")
final = crew.kickoff("Infosys")
print("result:", final)
print("memory now holds:", list(crew.memory))Look at two things. Each step prints the role that produced it — that is your audit trail, and a real Crew does not hand you that for free. And memory still holds the last brief after the run ends, which is what long-term memory does across kickoffs.
Where you will see this
- Coding assistants like Claude Code and Cursor, where one part plans and another edits files.
- Support bots split into an "understand the complaint" agent and a "check the order status" agent.
- Content pipelines: research, draft, review, publish.
- Swiggy or travel assistants routing your query to a refunds specialist or an order-tracking one.
- Internal report tools where a crew drafts a weekly summary and a human approves it.
Common mistakes
- Giving each agent a 2000-word backstory. With five agents you burn the context budget before the first tool call. Keep backstories under 200 words.
- Using Hierarchical when the order is already obvious. You pay for an extra model call per round and get the same answer. Switch to Sequential.
- Skipping
expected_output. Without a stated contract, the next task reads whatever came out and guesses. The crew still runs, so nobody notices until an audit. - Shipping a bare Crew to production. Output varies run to run, replay is impossible, and on-call cannot compare a bad run to a good one. Wrap it in a Flow.
- Putting side effects in Crew tools. A crew may call a tool more times than you expected. Anything that writes, deletes, or takes a payment belongs in a Flow step, never a Crew tool.
If they ask in an interview
Q: What is the difference between a Crew and a Flow?
A: A Crew is autonomy-first: the model decides the shape at runtime, which suits exploratory work but is hard to replay or test. A Flow is determinism-first, an event-driven graph you own in plain Python, so it is observable and testable. In production, start with a Flow and call a Crew inside a step when exploration is worth the cost.
Q: When would you pick Hierarchical process over Sequential?
A: Only when you have four or more specialists and the choice of who works next depends on what the previous step produced. Hierarchical adds a manager call before every specialist call, so token cost can triple. If the order is fixed, Sequential gives the same output cheaper.
Q: How do you stop one agent's output from breaking the next agent?
A: Make the handoff typed instead of free text. Put a structured output on the upstream task so the next task reads a validated object with known fields, and keep the expected_output string tight. Otherwise the downstream agent quietly improvises when the shape does not match.
Try these
- Add a fourth agent, a Fact Checker, between the Writer and the Editor. Notice how little changes — that is the point of the Task list.
- Rewrite the crew as a Flow: each step emits an event name and the next step listens for it. Count where variability dropped, and where readability got worse.
- Add a manager function that picks the next role each round and returns "done" at the end. Print how many extra manager calls three specialists cost you.
- Give one agent a 300-word backstory and print the total prompt length before and after.
Words, simply
| Word | Meaning in simple words |
|---|---|
| Agent | A worker with a role, a goal, a short backstory, and some tools |
| Task | One unit of work, assigned to one agent, with a stated output shape |
| Crew | The box that holds the agents, the tasks, and the process |
| Process | The rule that decides who works next: fixed order or a manager |
| Flow | A workflow you write in plain code, driven by named events |
| Backstory | The short paragraph that shapes an agent's tone and judgment |
| Manager LLM | The extra model call in Hierarchical that picks the next task |
| Entity memory | Facts stored against a specific customer or account, kept across runs |
Quick recap
- Four words run the whole framework: Agent, Task, Crew, Process. Agents never talk directly; tasks and the process do the wiring.
- Crew gives exploration but no receipt; Flow gives the receipt. Start with a Flow and call a Crew inside it.
- Most pain comes from three things: bloated backstories, a manager you did not need, and untyped handoffs.