Build a Multi-Agent Research Team · 35 min · Python · Anthropic Python SDK · Pydantic
Objective
Structured task assignment, not a free-form plan
from pydantic import BaseModel
from typing import Literal
class TaskAssignment(BaseModel):
specialist: Literal["web_researcher", "technical_analyst", "market_analyst"]
sub_task: str
class TaskList(BaseModel):
research_question: str
tasks: list[TaskAssignment]
If you built Course 06's coding agent, this should feel familiar: a Pydantic schema, populated by prompting the model for JSON matching it, parsed and validated before anything downstream trusts it. The Literal["web_researcher", ...] type does real work here -- it constrains the model to only ever assign a sub-task to one of the 3 specialists that actually exist, rather than inventing a 4th role nothing in the graph knows how to route.
Why the planner gets the stronger model
Not every agent in this system needs the same model
The Planner makes exactly one decision per run (how to decompose this question), but that decision determines the quality ceiling for everything downstream -- a bad decomposition means 3 specialists doing careful work on the wrong sub-tasks. The 3 specialists, by contrast, each do focused, narrower work many times over the course of a run. This course uses a stronger model (Sonnet) for the Planner and Synthesizer -- the two agents whose mistakes are hardest to recover from downstream -- and a faster/cheaper model (Haiku) for the specialists, whose individual outputs get checked against each other in synthesis anyway.
Test the Planner against genuinely different question types before trusting it
"Compare LangGraph and CrewAI" (competitive analysis), "explain how vector databases work" (technology deep dive), and "what's the state of AI agent adoption in enterprise" (trend report) should produce meaningfully DIFFERENT task decompositions -- not the same generic 3-task template with the topic swapped in. If your Planner produces near-identical sub-tasks regardless of question type, the prompt needs more explicit guidance on what makes each of the 3 question types different, not just what the schema should look like.
Your Planner produces a TaskList where two of the three tasks are both assigned to web_researcher, and market_analyst gets nothing. Is this necessarily a bug?
A rigid "every specialist gets exactly one task" rule would be worse than letting the Planner genuinely decide relevance per question -- forcing a market angle onto "explain how vector databases work" would produce a strained, padded section nobody needs. The real thing to verify (in this lesson's lab) is whether the Planner's skew reflects genuine judgment about the question, tested across multiple different questions, not a systematic bias toward one specialist regardless of topic.
What you're building
planner_agent.py: the TaskList/TaskAssignment schema and a plan_research function that prompts Sonnet with the research question and produces a validated task list — tested against 5 genuinely different research questions (spanning technology deep-dives, competitive analysis, and trend reports) and confirming the decompositions are meaningfully different, not templated.
Unlock the full lesson
You've read the first 2 sections. The rest of this lesson covers The Problem, Build, Check Yourself, Key Terms & Next — plus a hands-on lab, quiz, and project artifact.
Create a free account — the opening phases of 29 of 35 courses are free, no credit card.