CrewAI — role-based crews

Roles, tasks, and processes in CrewAI, and when a role-based crew beats a hand-built LangGraph.

🕸️ Module 4 6 min read Not started

Why this matters

CrewAI is the most beginner-friendly multi-agent framework — you describe agents as roles with goals and backstories, give them tasks, and CrewAI handles delegation. It is hugely popular in 2026 for cross-functional agent teams (research + analysis + writing + QA). It pairs especially well with stakeholders who can read and edit the role definitions.

Learning objectives

  1. Define agents, tasks, and crews.
  2. Pick between sequential and hierarchical processes.
  3. Use built-in tools (web search, file I/O) and custom tools.
  4. Wire CrewAI memory and human input.
  5. Know when to switch to LangGraph.

1. The CrewAI mental model

  • Agent — a role/goal/backstory plus tools and an LLM.
  • Task — a description, expected output, and (optionally) the agent who must do it.
  • Crew — agents + tasks + a Process (sequential or hierarchical).

Install:

powershell
uv add crewai crewai-tools

2. Sequential crew (the easiest)

python
import os
from crewai import Agent, Task, Crew, Process, LLM
from crewai_tools import SerperDevTool, FileWriterTool

llm = LLM(model="openai/gpt-4.1-mini")  # CrewAI uses litellm under the hood

researcher = Agent(
    role="Senior Research Analyst",
    goal="Find facts and citations on the topic",
    backstory="A diligent analyst with a love for primary sources.",
    tools=[SerperDevTool()],         # web search
    llm=llm,
    verbose=True,
)

writer = Agent(
    role="Tech Writer",
    goal="Turn research into a 400-word post",
    backstory="A clear, concise tech writer.",
    tools=[FileWriterTool()],
    llm=llm,
    verbose=True,
)

t1 = Task(
    description="Research the topic '{topic}'. Return 6 bullet points with citations.",
    expected_output="A bulleted list of 6 facts with sources.",
    agent=researcher,
)

t2 = Task(
    description="Write a 400-word, engaging post for a developer audience using the research.",
    expected_output="A markdown file `post.md`.",
    agent=writer,
    output_file="post.md",
    context=[t1],          # explicit dependency
)

crew = Crew(
    agents=[researcher, writer],
    tasks=[t1, t2],
    process=Process.sequential,
    verbose=True,
)

result = crew.kickoff(inputs={"topic": "Agentic AI in 2026"})
print(result.raw)

Key points:

  • inputs={"topic": ...} substitutes {topic} placeholders.
  • context=[t1] makes t2 aware of t1's output.
  • output_file= writes to disk automatically.

3. Hierarchical crew (with a manager)

In hierarchical mode, you do not assign agents to tasks. The manager decides at runtime.

python
crew = Crew(
    agents=[researcher, writer],          # workers only — do NOT include the manager here
    tasks=[t1, t2],                        # tasks may omit `agent=`
    process=Process.hierarchical,
    manager_llm="openai/gpt-4.1-mini",     # OR pass manager_agent=...
    planning=True,                          # crew plans before execution
    verbose=True,
)

# OR with a custom manager agent:
manager = Agent(
    role="Project Manager",
    goal="Deliver the report on time at high quality",
    backstory="An experienced PM who delegates effectively.",
    allow_delegation=True,
    llm=llm,
)
crew = Crew(
    agents=[researcher, writer],
    tasks=[t1, t2],
    process=Process.hierarchical,
    manager_agent=manager,                  # ← do NOT also put `manager` in `agents=...`
    planning=True,
)

Hard rules to remember:

  • The manager agent must not be in agents=... and must not have its own tools — CrewAI gives it DelegateWorkTool and AskQuestionTool automatically.
  • allow_delegation=True belongs on the manager only.
  • Workers are usually allow_delegation=False.

4. Custom tools (with Pydantic schemas)

python
from crewai.tools import BaseTool
from pydantic import BaseModel, Field

class FetchArgs(BaseModel):
    url: str = Field(..., description="URL to fetch")

class FetchTool(BaseTool):
    name: str = "fetch_page"
    description: str = "Download a webpage and return text."
    args_schema: type[BaseModel] = FetchArgs

    def _run(self, url: str) -> str:
        import httpx
        return httpx.get(url, timeout=10).text[:5000]

Drop FetchTool() into any agent's tools=[...].


5. Memory and human input

python
crew = Crew(
    agents=[...], tasks=[...],
    process=Process.sequential,
    memory=True,            # short-term + long-term memory enabled
    embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}},
)

For human input on a specific task:

python
t_review = Task(
    description="Review the draft. Point out 3 issues.",
    expected_output="3 bulleted issues",
    agent=writer,
    human_input=True,        # CLI prompts the user before this task completes
)

For a UI-driven workflow you usually wrap CrewAI in a FastAPI/Streamlit and capture human input through your own forms instead.


6. Async, batching, training

  • crew.kickoff_async(inputs=...) for async runs.
  • crew.kickoff_for_each(inputs_list=...) for batches (parallelism per worker count).
  • crew.train(n_iterations=5, inputs=...) to gather feedback and refine prompts (CrewAI's lightweight optimisation).

7. When to choose CrewAI vs LangGraph

NeedPick
Linear or hierarchical pipelines, business-readable codeCrewAI
Custom routing, cycles, HIL, sub-graphs, evalsLangGraph
Production observability with checkpointers and time-travelLangGraph
Quick PoC for stakeholdersCrewAI

It is fine — and common — to combine. Use LangGraph as the production backbone and embed a CrewAI crew as one node when a sub-task is naturally a "crew."


8. CrewAI Flows (the LangGraph competitor)

In late 2024 CrewAI added Flows — a state machine layer (similar to LangGraph) that you can use with or without a Crew. Decorators: @start, @listen, @router. If you really like CrewAI's syntax and want graph control, look at Flows. For deeply complex agent topologies, LangGraph still pulls ahead in 2026.


Hands-on lab (5 hours)

Build a product-launch crew:

  • market_research (web search).
  • competitor_analysis (search + structured comparison).
  • messaging_writer (drafts taglines and copy).
  • qa_reviewer (proofreads).

Requirements:

  • Use hierarchical process with a custom Project Manager agent.
  • Add a custom FetchTool for pulling competitor websites.
  • Memory on; export final files to out/.
  • Wrap in a FastAPI endpoint POST /launch that takes {topic, competitors: [..]}.
  • Document one experiment where you swap the manager LLM (gpt-4.1-mini ↔ claude-opus-4-7) and report the cost/quality difference.

Common pitfalls

  1. Putting the manager into agents=... — the runtime misroutes tasks.
  2. Tools on the manager — never. The manager only delegates.
  3. No expected_output — tasks complete unpredictably.
  4. Forgetting context=[t1] — later tasks miss earlier output.
  5. Using Process.hierarchical without manager_llm or manager_agent — runtime error.

Self-check

  1. What does Process.hierarchical actually change at runtime?
  2. Why must the manager not have tools?
  3. How do context=[...] task dependencies differ from a graph edge?
  4. When do you reach for CrewAI Flows over a plain Crew?
  5. How does CrewAI handle memory under the hood?

References

Sign in to save your progress and earn badges.