n4nAI

CrewAI agent roles tutorial: manager and worker patterns

Build a working CrewAI hierarchical crew with manager and worker agents. Step-by-step code, prerequisites, and expected output for the manager worker pattern.

n4n Team2 min read532 words

Audio narration

Coming soon — every post will get a voice note here.

The crewai manager worker agent role pattern splits responsibility between a supervising agent and specialized workers, letting you scale multi-step LLM workflows without hand-wiring every call. This tutorial builds a runnable hierarchical crew from scratch, showing how to define roles, delegate tasks, and read the manager’s plan. You’ll need Python 3.10+, a working OpenAI-compatible endpoint, and the crewai package.

Prerequisites

  • Python 3.10 or newer
  • crewai (install with pip install crewai)
  • An OpenAI-compatible LLM endpoint and API key

Set the environment before importing CrewAI:

export OPENAI_API_KEY="sk-your-key"
export OPENAI_API_BASE="https://api.openai.com/v1"

If you want one endpoint that addresses 240+ models with automatic fallback and per-token metering, point OPENAI_API_BASE at n4n.ai’s OpenAI-compatible URL instead. The rest of the code stays identical.

What the pattern actually does

In a hierarchical crew, the manager LLM receives the full goal and a list of worker descriptions. It produces a plan, assigns each task to a worker, and aggregates results. Workers do not talk to each other directly; all coordination flows through the manager. This is the core of the crewai manager worker agent role pattern.

Step 1: Define worker agents

Create three workers: a researcher, a writer, and a fact-checker. Set allow_delegation=False so they execute rather than re-delegate.

from crewai import Agent

researcher = Agent(
    role="Senior Research Analyst",
    goal="Find concise, authoritative facts on a given topic",
    backstory="You have 10 years of experience distilling complex topics into bullet points.",
    allow_delegation=False,
    verbose=True,
)

writer = Agent(
    role="Technical Writer",
    goal="Turn research into a clear, skimmable markdown summary",
    backstory="You write documentation for engineers and hate fluff.",
    allow_delegation=False,
    verbose=True,
)

fact_checker = Agent(
    role="Fact Checker",
    goal="Verify claims against provided sources and flag errors",
    backstory="You are pedantic and cite evidence for every correction.",
    allow_delegation=False,
    verbose=True,
)

Step 2: Define tasks with context

Tasks reference the agent that should execute them. In hierarchical mode the manager decides order, but you can hint dependencies with context.

from crewai import Task

research_task = Task(
    description="Research the current state of server-side WebAssembly runtimes.",
    expected_output="3-5 bullet points with named projects and one sentence each.",
    agent=researcher,
)

write_task = Task(
    description="Write a markdown section summarizing the research.",
    expected_output="Markdown with a heading and the bullet points as a list.",
    agent=writer,
    context=[research_task],
)

check_task = Task(
    description="Verify the writer's markdown against the research bullets.",
    expected_output="Corrected markdown or 'OK' if accurate.",
    agent=fact_checker,
    context=[research_task, write_task],
)

Step 3: Build the hierarchical crew

Pass process=Process.hierarchical and a manager_llm. The manager is created internally.

from crewai import Crew, Process

crew = Crew(
    agents=[researcher, writer, fact_checker],
    tasks=[research_task, write_task, check_task],
    process=Process.hierarchical,
    manager_llm="gpt-4o-mini",
    verbose=True,
)

result = crew.kickoff()
print("FINAL:", result)

Checkpoint output

You should see logs similar to:

[Manager] Plan: 1) Research... 2) Write... 3) Check...
[Researcher] Bullet points: Wasmtime, Wasmer, WasmEdge
[Writer] ## Server-side WASM Runtimes ...
[Fact Checker] OK
FINAL: ## Server-side WASM Runtimes
- Wasmtime...

If you see the manager assigning tasks by name, the crewai manager worker agent role pattern is working.

Step 4: Inspect manager delegation

The manager’s thoughts are stored in crew.chat_history. Filter for the manager role to debug planning.

for msg in crew.chat_history:
    if getattr(msg, "role", None) == "manager":
        print("MANAGER:", msg.content[:300])

This reveals how the manager interpreted worker skills—useful when a worker gets the wrong task.

Step 5: Use a custom manager agent

For stricter control, define a manager agent and pass manager_agent. The manager must allow delegation.

manager = Agent(
    role="Engineering Lead",
    goal="Coordinate research, writing, and checking into a final brief",
    backstory="You delegate efficiently and never produce content yourself.",
    allow_delegation=True,
    verbose=True,
)

crew = Crew(
    agents=[researcher, writer, fact_checker, manager],
    tasks=[research_task, write_task, check_task],
    process=Process.hierarchical,
    manager_agent=manager,
    verbose=True,
)

Run crew.kickoff(). The logs now show your named manager instead of an anonymous one.

Step 6: Route workers to specific models

You can pin a worker to a model using the model argument. An OpenAI-compatible gateway like n4n.ai honors client routing directives and forwards provider cache-control hints, so a string like "anthropic/claude-3-haiku" reaches the right backend.

researcher = Agent(
    role="Senior Research Analyst",
    goal="Find concise, authoritative facts",
    backstory="Experienced analyst.",
    allow_delegation=False,
    model="anthropic/claude-3-haiku",
)

This keeps costly models on the manager while cheap models handle bulk extraction.

Step 7: Handle failures and retries

Hierarchical crews survive transient provider errors because the manager can re-assign. Bound retries with max_iter:

researcher = Agent(
    role="Senior Research Analyst",
    goal="...",
    backstory="...",
    allow_delegation=False,
    max_iter=3,
)

If a worker exhausts iterations, the manager receives an error and can try another agent or report failure.

Full runnable script

import os
from crewai import Agent, Task, Crew, Process

researcher = Agent(
    role="Senior Research Analyst",
    goal="Find concise facts on server-side WASM runtimes",
    backstory="10 years distilling complex topics.",
    allow_delegation=False,
    verbose=True,
)
writer = Agent(
    role="Technical Writer",
    goal="Summarize research in markdown",
    backstory="Engineer-focused documentation writer.",
    allow_delegation=False,
    verbose=True,
)
fact_checker = Agent(
    role="Fact Checker",
    goal="Verify markdown against research",
    backstory="Pedantic evidence citer.",
    allow_delegation=False,
    verbose=True,
)

t1 = Task(description="Research server-side WASM runtimes.",
          expected_output="3-5 bullets.", agent=researcher)
t2 = Task(description="Write markdown summary.",
          expected_output="Markdown section.", agent=writer, context=[t1])
t3 = Task(description="Verify markdown.",
          expected_output="Corrected or OK.", agent=fact_checker, context=[t1, t2])

crew = Crew(
    agents=[researcher, writer, fact_checker],
    tasks=[t1, t2, t3],
    process=Process.hierarchical,
    manager_llm="gpt-4o-mini",
    verbose=True,
)
print(crew.kickoff())

When not to use this pattern

If your tasks are strictly linear and single-skilled, Process.sequential avoids the extra manager calls and latency. The crewai manager worker agent role pattern pays a tax in tokens and round-trips for flexibility. Use it when worker specialization clearly improves output quality.

Tuning tips

  • Set verbose=2 on the crew to see full manager prompts.
  • Use manager_llm with a stronger model than workers for better planning.
  • Monitor per-agent token usage if your endpoint meters individually; hierarchical crews can silently double spend.
  • Keep worker goal strings tight; the manager matches tasks to goals verbatim.

That’s the complete pattern, runnable as written.

Tagscrewaiagent-rolestask-designpatterns

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All crewai agent roles & task design posts →