The multi-agent metaphor: roles, tasks, and crews that collaborate.
Agents Module 5 CrewAI Multi-Agent
Agent.run().Structure your agent system like a small team. Each member has a role (e.g., “Senior Researcher”), a goal (e.g., “find authoritative sources”), and a backstory (a paragraph of system-prompt-as-character).
Members work on tasks, organised by a process (sequential, hierarchical). The whole thing is called a crew.
| Concept | Claude SDK | OpenAI SDK (M4) | CrewAI |
|---|---|---|---|
| Primary unit | Tool | Agent + handoff | Agent with role |
| Best at | Tool-heavy single agent | Triage + specialists | Collaborative team |
| Mental model | “One worker, many tools” | “Receptionist routes to specialists” | “Small team works a brief together” |
Agent — a role + goal + backstory + (optional) tools + LLM config.Task — a description, an expected output spec, and the agent assigned to it.Crew — a list of agents + a list of tasks + a process.Process — sequential (tasks run in order, output of N feeds N+1) or hierarchical (a manager agent delegates).Tool — same idea as M2's @tool (CrewAI ships its own decorator); tools are attached to specific agents.researcher = Agent(
role="Senior Researcher",
goal="Find 3 authoritative sources on the given topic",
backstory=(
"You are a meticulous researcher who values primary sources "
"and verifiable citations. You have a healthy skepticism of "
"blog posts and prefer specs, papers, and official docs."
),
llm="anthropic/claude-3-5-sonnet-latest",
verbose=True,
)
Note: backstory is not flavour text — it's prepended to the system prompt for every LLM call this agent makes. It's how you give the agent a persona.
from crewai import Agent, Task, Crew, Process
researcher = Agent(role="Researcher", goal="...", backstory="...", llm="anthropic/claude-3-5-sonnet-latest")
writer = Agent(role="Writer", goal="...", backstory="...", llm="anthropic/claude-3-5-sonnet-latest")
research_task = Task(description="Research the topic: {topic}", expected_output="3 bullet sources", agent=researcher)
write_task = Task(description="Write a 1-paragraph brief based on the research.", expected_output="One paragraph", agent=writer, context=[research_task])
crew = Crew(agents=[researcher, writer], tasks=[research_task, write_task], process=Process.sequential)
result = crew.kickoff(inputs={"topic": "Linux kernel 6.14 networking"})
print(result)
Note the context=[research_task] wiring: the writer sees the researcher's output.
Process.sequentialTasks run in declared order, each can see prior outputs via context=[...]. Simple, deterministic.
This lesson and L10 use sequential.
Process.hierarchicalA separate manager agent gets the goal and decides which agent does what, in what order.
More flexible, more expensive, less predictable. Mentioned, not built.
llm= accepts a LiteLLM model string: "anthropic/claude-3-5-sonnet-latest", "openai/gpt-4o", etc.ANTHROPIC_API_KEY / OPENAI_API_KEY env vars are picked up automatically.| You'd write by hand | CrewAI does for you |
|---|---|
| “Build agent A's prompt with role+goal+context” | The Agent(...) constructor |
| “Feed agent A's output to agent B” | context=[task_a] in Task |
| “Loop sequentially over tasks” | Process.sequential |
| “Render structured outputs across the team” | expected_output= per task |
| “Trace which agent said what” | verbose=True log lines |
You genuinely have 3+ roles that benefit from being distinct agents (planner / worker / reviewer; researcher / writer / editor; etc.). Sweet spot.
You have one role with many tools (Claude SDK, M2), a fixed graph (LangGraph, M3), or a triage-and-handoff shape with no real collaboration (OpenAI SDK, M4).
context=[...].llm="anthropic/..." to Anthropic Claude across this course's framework lessons.