CrewAI in Practice
CrewAI replaces graphs and state machines with a hiring model: define what each agent is, what task it is assigned, and how the crew is organized. This lesson builds the benchmark agent in CrewAI and shows where the role abstraction helps - and where it hides complexity.
CrewAI’s Mental Model
Where LangGraph asks you to think in graphs, CrewAI asks you to think in job descriptions. You define agents (each with a role, goal, and backstory), assign them tasks (each with a description, expected output, and available tools), and assemble them into a crew with a process type (sequential or parallel). The framework handles the execution loop, inter-agent communication, and result collection.
This model is intuitive for anyone who has ever written a team brief. A “senior researcher” with a “find credible information” goal is easier to communicate than a state machine with conditional edges - especially in teams where not everyone reads Python. The trade-off: you have less explicit control over the execution flow, and debugging unexpected agent behavior requires understanding what CrewAI is doing on your behalf.
The Core Components
- Agent - a role-defined LLM instance with a goal, backstory, tool access, and delegation settings. Think of it as a job description that becomes an instruction set.
- Task - a unit of work with a description, expected output format, and assigned agent. Tasks can have context dependencies on other tasks.
- Crew - the container that organizes agents and tasks, sets the process type, and executes the whole operation.
- Tool - any callable wrapped in CrewAI’s tool decorator, making it available to agents.
Defining the Tools
from crewai.tools import tool
@tool("web_search")
def web_search(query: str) -> str:
"""Search the web for information on a query.
Returns a list of results with title, url, and snippet.
Use this to find relevant sources for a research question."""
result = _web_search_impl(query) # underlying implementation from Lesson 3
# CrewAI tools must return a string - serialize the result
import json
return json.dumps(result, indent=2)
@tool("fetch_document")
def fetch_document(url: str) -> str:
"""Retrieve the full text content of a document by URL.
Use this after web_search to read a specific page in detail."""
result = _fetch_document_impl(url) # underlying implementation from Lesson 3
return json.dumps(result, indent=2)
None instead of the result.Defining the Agents
For the research task, we use two specialized agents. This demonstrates CrewAI’s strength: role specialization with natural language descriptions.
from crewai import Agent
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-opus-4-8", temperature=0)
researcher = Agent(
role="Senior Research Specialist",
goal=(
"Find accurate, well-sourced information on the research question "
"using web search and document retrieval. Gather at least three "
"credible sources with specific, quotable claims."
),
backstory=(
"You are an experienced researcher with a systematic approach: "
"search broadly first, then read the most relevant sources deeply. "
"You always note when information is incomplete or contradictory."
),
tools=[web_search, fetch_document],
llm=llm,
verbose=True, # logs agent reasoning steps
max_iter=10, # circuit breaker: max reasoning iterations
)
report_writer = Agent(
role="Research Report Writer",
goal=(
"Synthesize research findings into a structured, readable report "
"that directly answers the question with sourced claims and "
"explicitly flags any information gaps."
),
backstory=(
"You write clear, precise research reports for technical audiences. "
"Every claim in your reports traces to a specific source. "
"You are honest about what the research did and did not find."
),
llm=llm,
verbose=True,
)
Defining the Tasks
from crewai import Task
def create_research_task(question: str) -> Task:
return Task(
description=f"""Research the following question thoroughly:
{question}
Use web_search to find relevant sources, then fetch_document to read
the most relevant pages in full. Collect at least three specific,
quotable claims with their source URLs.""",
expected_output=(
"A structured list of findings: each finding is a claim, "
"its source URL, and a brief note on reliability. "
"Flag any areas where sources conflict or information is missing."
),
agent=researcher,
)
def create_report_task(question: str, research_task: Task) -> Task:
return Task(
description=f"""Write a research report that answers:
{question}
Use the research findings from the previous task. Structure the report with:
1. Direct answer to the question
2. Supporting evidence (at least 3 sourced claims with URLs)
3. Information gaps or caveats""",
expected_output=(
"A structured research report in markdown format with: "
"an executive summary, sourced claims section, and gaps section."
),
agent=report_writer,
context=[research_task], # report task has access to research task output
)
Assembling and Running the Crew
from crewai import Crew, Process
def run_research_crew(question: str) -> str:
research_task = create_research_task(question)
report_task = create_report_task(question, research_task)
crew = Crew(
agents=[researcher, report_writer],
tasks=[research_task, report_task],
process=Process.sequential, # tasks run in order, second sees first's output
verbose=True,
# memory=True, # enable for cross-run memory (requires embedding model)
)
result = crew.kickoff(inputs={"question": question})
return result.raw # the final task's output as a string
# Run it
report = run_research_crew(
"What are the main approaches to AI agent memory?"
)
print(report)
The Parallel Process Option
When tasks are independent (no context dependencies), CrewAI’s Process.hierarchical mode delegates tasks to agents in parallel, with a manager agent coordinating. This is CrewAI’s strongest differentiator for tasks that naturally decompose into parallel workstreams:
from crewai import Crew, Process, Agent
manager = Agent(
role="Research Manager",
goal="Coordinate the research team and synthesize their findings",
backstory="An experienced manager who delegates effectively and synthesizes diverse inputs",
llm=llm,
allow_delegation=True, # can assign tasks to other agents
)
parallel_crew = Crew(
agents=[researcher, report_writer],
tasks=[research_task, report_task],
process=Process.hierarchical,
manager_agent=manager,
verbose=True,
)
Accessing Task Outputs
result = crew.kickoff(inputs={"question": question})
# Per-task outputs
for task_output in result.tasks_output:
print(f"Task: {task_output.description[:60]}...")
print(f"Output: {task_output.raw[:200]}...")
print()
# Token usage summary
print(f"Total tokens used: {result.token_usage}")
CrewAI: What It’s Good At
- Natural role decomposition - if your problem maps naturally to “person A does X, person B does Y,” CrewAI’s model is intuitive and fast to prototype.
- YAML-first configuration - for teams that want to configure agents without modifying Python, CrewAI’s YAML config files keep business logic separate from orchestration code.
- Parallel workstreams - independent tasks running in parallel are a first-class feature. LangGraph can do this too, but requires explicit parallel branching in the graph.
CrewAI: What It Costs
- Less explicit control - CrewAI decides how agents interact within a process. When an agent behaves unexpectedly, tracing why requires reading CrewAI’s execution logs rather than your own state graph.
- String-only tool returns - the requirement to return strings from tools is a leaky abstraction. Structured data must be serialized, and tool errors must be expressed as error strings rather than exceptions.
- Iteration control -
max_iteris a blunt circuit breaker. LangGraph’s conditional edges provide finer-grained loop control for agents with complex stopping conditions.
Ready to Go Deeper?
Live instructor-led courses from our partners. Affiliate disclosure.
AI & ML Courses - 30% Off
Live instructor-led AI, machine learning, data science, and cloud courses for working professionals. Use code Limited30 at checkout.
EdurekaDataCamp - AI & Data Science
Hands-on Python, machine learning, and AI courses with interactive exercises and real projects.
DataCampedX - Top AI Courses
University-level AI courses from MIT, Harvard, Stanford. Earn certificates that employers recognize.
edX