Build a working multi-agent CrewAI crew by defining role-based agents, assigning tasks, and wiring them into a sequential or hierarchical workflow that…
Construct a CrewAI Agent by setting its role, goal, backstory, model, and tools — then trace how those fields become the system prompt that drives behavior. You'll build the researcher and writer agents for a 'crewai tutorial' SEO page.
How to define a CrewAI Agent by setting its role, goal, backstory, model, and tools — and how those fields become the system prompt that drives behavior.
Why this matters: Getting agent definitions right is the foundation of every CrewAI workflow — vague fields produce vague outputs, and the wrong tool assignment silently breaks the division of labor.
Decision this forces: How many agents does this workflow need, and what distinct role does each one own?
Your agent just returned a wall of raw HTML instead of a clean summary — because nothing told it to behave like a researcher. How do you make a CrewAI act like a specialist instead of a generic chatbot?
A CrewAI is a language model wired to a , a goal, a , a model name, and a list of . CrewAI stitches those five fields into the system prompt that opens every LLM call for that agent.
Each field does a distinct job: names the persona ("Senior SEO Researcher"), goal narrows the objective ("find high-intent keywords"), and adds context that shapes tone and judgment ("You have 5 years of technical SEO experience").
Tools are the only field that changes what the agent can do — not just how it sounds. An agent without tools can only reason over text it already has; add a search tool and it can fetch live data.
from crewai import Agent researcher = Agent( role="Researcher", goal="Research stuff", backstory="", llm="gpt-4o-mini" ) print(researcher.role)
This agent runs without error — which is the trap. Vague fields produce vague behavior, not a crash.
CrewAI inserts the role, goal, and backstory verbatim into the system prompt. With backstory="" and goal="Research stuff", the LLM gets almost no behavioral guidance — it will produce a generic, unfocused summary with no SEO framing, no depth constraints, and no consistent tone. No Python error is raised; the failure is silent and shows up only in output quality.
from crewai import Agent from crewai_tools import SerperDevTool search_tool = SerperDevTool() researcher = Agent( role="Senior SEO Researcher", goal="Find the top 5 search intents and keyword clusters for 'crewai tutorial'.", backstory=( "You have 5 years of technical SEO experience. " "You prioritise search volume and user intent over keyword density." ), tools=[search_tool], llm="gpt-4o-mini" )
Each field maps directly to a section of the system prompt CrewAI assembles before the first LLM call. The list is appended as a JSON schema the model can invoke — without it, the agent can't search.
CrewAI appends a 'Tools' section to the system prompt listing each tool's name, description, and input schema. With tools=[], that section is empty and the LLM can only reason over text already in context — it cannot fetch live search results. The agent still runs; it just hallucinates or reasons from stale training data.
writer = Agent( role="SEO Content Writer", goal=( "Write a 1 200-word tutorial page for 'crewai tutorial' " "that targets the top keyword clusters the researcher found." ), backstory=( "You write developer-focused tutorials. " "You structure content with H2s, code blocks, and a FAQ section." ), tools=[], # writer reasons over researcher output only llm="gpt-4o-mini" )
The writer gets no search tool deliberately — its job is to synthesise, not to fetch. Keeping tools scoped prevents the agent from re-doing the researcher's work and inflating token cost.
The writer could call the search API mid-draft, potentially fetching redundant data the researcher already gathered. Each tool call adds latency and API cost. More subtly, the writer's goal no longer forces it to synthesise — it may defer judgment to search results instead of the researcher's curated output, undermining the division of labor.
# A new requirement: fact-check every claim before publishing. # Complete the agent below — fill in the TODO lines. fact_checker = Agent( role="SEO Fact Checker", goal=TODO, # what specific output should this agent produce? backstory=( "You verify factual claims in developer content " "against authoritative sources." ), tools=TODO, # which tool(s) does this role uniquely need? llm="gpt-4o-mini" )
Stop — attempt both TODOs before revealing. Hint 1: the goal should name a concrete deliverable, not a vague activity. Hint 2: ask yourself what capability this agent has that the researcher and writer don't.
Changed lines and why:
goal="Return a list of every factual claim in the draft, each marked VERIFIED or NEEDS_SOURCE with a citation URL."
— A concrete deliverable (a structured list) forces the LLM to produce checkable output, not a vague 'I checked it'.
tools=[SerperDevTool()]
— The fact-checker needs live search to verify claims, just like the researcher. The key distinction is its GOAL and BACKSTORY, not its tool — it uses search to verify, not to discover. If your goal was too vague or tools=[], the agent would hallucinate verifications silently.
agent.system_prompt and confirm the role, goal, and backstory appear verbatim and in the right order.tools=[] has a non-empty description — a missing description means the LLM won't know when to call it.You now have a researcher and a writer, each with a scoped role, a concrete goal, and the right tools. But an agent sitting alone does nothing — it needs a that tells it exactly what to produce and how success is measured.
Imagine handing your researcher agent a sticky note that says only 'research SEO'. It has no deadline, no format, and no definition of done — so it writes whatever feels complete. The next module fixes this by pairing each agent with a Task object that carries a description, an , and a direct agent assignment.
A well-scoped is what turns 'research stuff' into 'a markdown table of 5 keyword clusters with monthly search volume' — and that precision is what prevents vague, unusable results.
Write CrewAI Task objects that pair a description, expected_output, and an agent — then see how a well-scoped expected_output prevents vague results. You'll define the research task and the draft-writing task for the SEO page.
How to write CrewAI Task objects that pair a description, expected_output, and an assigned agent — then chain tasks together with context=.
Why this matters: Precise task definitions are what turn your agents into a working SEO pipeline; vague tasks produce unpredictable output that breaks downstream steps.
In module 1 you built a researcher and a writer agent. Each has a , a goal, and a . These three fields become the system prompt.
An knows who it is, but it needs to know what to do right now. A fills that gap. This module covers it.
A CrewAI pairs a natural-language description with an and an assigned .
The description tells the agent what to do. The expected_output tells it what done looks like.
A vague expected_output like "a good summary" gives no stopping condition. The model over-generates or stops too early.
A precise one like "5 ranked keywords with monthly search volume" acts as a built-in acceptance criterion the model can self-check.
You're building two tasks for the "crewai tutorial" SEO page: keyword research and draft writing.
Here's the same research task written two ways:
expected_output="A summary of relevant keywords." The agent might return two words or two pages.expected_output="A markdown table of exactly 5 keywords with monthly searches and ranking difficulty." The agent has a clear shape to fill.The precise version makes downstream tasks reliable. The writer agent knows exactly what format to expect.
from crewai import Task research_task = Task( description=( "Search for the top keywords around 'crewai tutorial'. " "Focus on informational and tutorial intent queries." ), expected_output=( "A markdown table of exactly 5 keywords. " "Columns: keyword phrase | monthly searches | difficulty (easy/medium/hard)." ), agent=researcher, # the Agent object from module 1 )
This is the minimal, correct shape of a Task: description + expected_output + agent.
The specifies format (markdown table), count (5), and column names — so the researcher has no ambiguity about what to produce.
Both. CrewAI injects the description as the task directive and the expected_output as the completion criterion into the agent's prompt. The agent uses expected_output to self-check whether its response is done.
draft_task = Task( description=( "Write a 600-word SEO page for the query 'crewai tutorial'. " "Use the keyword table from research to place terms naturally." ), expected_output=( "A markdown document with: H1 title, 40-60 word answer capsule, " "three H2 sections, and a 3-question FAQ." ), agent=writer, # the writer Agent from module 1 context=[research_task], # feeds research_task output as input )
The parameter is how you chain tasks: CrewAI appends the output of every listed task to this task's prompt before the agent runs.
Without context=, the writer agent starts from scratch and ignores the keyword research entirely — a common silent failure.
The writer gets no keyword table. It generates a draft using only its own knowledge, so the SEO keywords are absent or invented — the output looks plausible but misses the research entirely. No error is raised; the failure is silent.
# New requirement: add a meta-description task after draft_task. # The SEO writer should produce a 155-character meta description # drawn from the finished draft. meta_task = Task( description="Write a search-engine meta description for the crewai tutorial page.", expected_output=# TODO: write a precise expected_output here agent=writer, context=[draft_task], )
Stop — attempt the TODO before revealing. The gap is the string: write one that gives the agent an unambiguous acceptance criterion for a meta description.
Hints: think about character limit, tone, and what the string must contain.
Changed line — expected_output:
"A single sentence of exactly 140–155 characters that includes the phrase 'crewai tutorial', states what the reader will learn, and ends with a call to action."
Why this works: it gives a character range (measurable), a required keyword (SEO constraint), a content rule (what the reader learns), and a structural rule (call to action). The agent can self-check all four criteria before returning.
Three failure patterns to watch for — and what each one looks like at runtime:
context=.You now have two agents and two tasks with precise and correct chains.
Hand them to a object. Choose or hierarchical mode. Call with your inputs to run the pipeline.
Module 3 covers how Crew wires agents and tasks, what process mode changes, and how to read after kickoff.
Instantiate a Crew with your agents and tasks, choose between sequential and hierarchical process modes, and call kickoff() with inputs — then read the UsageMetrics and final output. You'll run the full SEO-page crew end to end for the first time.
Instantiate a CrewAI Crew with agents and tasks, choose a process mode, and call kickoff() to run the full pipeline and read its output.
Why this matters: This is the step that turns your individually defined agents and tasks into a running SEO-page pipeline — without it, nothing executes.
Decision this forces: Should this crew use sequential or hierarchical process, and why?
Answer: every Task needs a description, an expected_output, and an agent. A precise expected_output stops the agent from returning vague or over-long results.
You now have two agents and two tasks for the 'crewai tutorial' SEO page. The missing piece is the — the object that holds those agents and tasks, picks an execution order, and fires the run. That's what this module builds.
A is the top-level orchestrator in CrewAI.
It holds a list of agents, a list of tasks, and a process mode.
The process mode decides execution order.
Calling starts the run and blocks until every task finishes.
It returns a result object containing the final output string and (token counts for the whole run).
The process mode is the only structural decision you make at the Crew level.
Everything else — prompts, tools, task scope — was set in Modules 1 and 2.
from crewai import Crew, Process seo_crew = Crew( agents=[researcher, writer], # from Module 1 tasks=[research_task, draft_task], # from Module 2 process=Process.sequential, verbose=True, )
This wires your existing agents and tasks into a runnable Crew. means research_task runs first; its output is automatically available to draft_task via .
verbose=True prints each agent's reasoning steps to stdout — leave it on while building so you can see what's happening.
The writer runs first with no research to draw on, so it hallucinates or produces a generic draft. Sequential process respects list order exactly — there is no dependency check. Always put upstream tasks earlier in the list.
result = seo_crew.kickoff( inputs={"topic": "crewai tutorial"} ) print(result.raw) # final output string print(result.token_usage) # UsageMetrics: prompt + completion tokens
kickoff() accepts an inputs dict whose keys match the {placeholders} in your task descriptions. The return value exposes result.raw for the final text and result.token_usage for the full-run .
result.token_usage is a UsageMetrics object with prompt_tokens, completion_tokens, and total_tokens summed across every agent call in the run. You check it to catch runaway loops (unexpectedly high totals) and to estimate cost before moving to production.
# Assume: researcher, writer, editor agents defined # Assume: research_task, draft_task, edit_task defined # edit_task.agent = editor seo_crew = Crew( agents=[researcher, writer, editor], tasks=[research_task, draft_task, __TODO__], process=Process.sequential, verbose=True, ) result = seo_crew.kickoff(inputs={"topic": "crewai tutorial"})
A third agent — an editor — has been added to the SEO crew. Your job: fill in the __TODO__ so the crew runs all three tasks in the correct order.
Replace __TODO__ with edit_task.
Changed line: tasks=[research_task, draft_task, edit_task]
Why position matters: Process.sequential runs tasks in list order with no dependency check. Placing edit_task third means the editor receives the writer's draft as context — put it second and the editor runs on raw research with no draft to polish.
When you call seo_crew.kickoff(inputs={"topic": "crewai tutorial"}), CrewAI runs the researcher first.
It stores the researcher's output, then hands it to the writer as context.
No glue code needed.
Confirm success by checking two things:
result.raw is non-empty and reads like a real SEO draft.result.token_usage.total_tokens is in a plausible range (not near zero).Zero tokens signal a task was skipped or cached unexpectedly.
The next module — Agent Collaboration and Context Flow — opens up how stored output travels between tasks.
You'll trace the mechanism step by step.
You'll see how the writer agent's backstory shapes what it does with the researcher's output.
| Option | Task order control | Needs a manager agent | Best for linear pipelines | When to choose | Cost | Complexity |
|---|---|---|---|---|---|---|
| Process.sequential | Fixed: tasks run in list order | No — crew runs the list directly | Yes — the default for research-and-write flows | Choose when tasks have a clear, fixed order and each step feeds directly into the next — e.g. research → draft → review. | Lower token usage; no manager LLM calls | Low — no extra agent or prompt needed |
| Process.hierarchical | Dynamic: manager decides at runtime | Yes — must set manager_llm or manager_agent | Overkill; adds cost with no benefit | Choose when task order is dynamic, agents need to delegate sub-tasks, or a coordinator must decide which agent handles what at runtime. | Higher token usage; manager adds extra LLM calls per decision | Higher — requires a manager_llm or manager_agent |
Three failure patterns show up most often when wiring a Crew for the first time:
{topic} but you call kickoff(inputs={}) without that key, CrewAI raises a KeyError before any agent runs. Fix: match every {placeholder} in task descriptions to a key in the inputs dict.process=Process.hierarchical without also setting manager_llm raises a validation error at Crew instantiation: "manager_llm or manager_agent is required for hierarchical process". The fix is either adding manager_llm or switching back to sequential.result.raw contains generic filler. The only signal is suspiciously low token_usage on the research task. Always verify list order matches your intended data flow.agents=[] is actually defined and imported — generated code often references a variable name that doesn't exist yet.inputs keys match all {placeholders} in task descriptions — run a quick string search.Trace how CrewAI passes a finished task's output as context to downstream tasks, revisit the agent role definitions from Module 1 to see how backstory shapes interpretation, and complete a partially wired context chain for the SEO page's editor agent.
How CrewAI passes a finished task's output to downstream agents using context= wiring, and when sequential order alone is enough.
Why this matters: Getting context wiring right is what turns a list of agents into a real pipeline — without it, your editor agent fact-checks nothing and your crew silently produces bad output.
Answer: . The names the agent; the goal states what it must achieve; but the tells the model how to think — its expertise, voice, and lens.
When an receives another agent's output as context, the backstory determines what it notices. An editor focused on SEO clarity trims differently than one focused on brand voice.
Your driving question: which tasks need an explicit context= list, and which rely on sequential order alone?
In a sequential , each automatically receives the prior task's output. That implicit handoff works for straight-line pipelines.
When a task needs output from two or more earlier tasks — or from a non-predecessor — wire context= explicitly. CrewAI appends each listed task's expected_output to the agent's prompt.
Rule of thumb: if skipping a task leaves the downstream agent missing critical information, list it in context=.
Your SEO crew has three tasks: research_task → draft_task → edit_task. Here's how context flows — and where it breaks without explicit wiring.
draft_task runs right after research_task: sequential order delivers the research output automatically. No context= needed.edit_task is the direct successor of draft_task, so it gets the draft automatically. But the editor also needs the original research to fact-check claims — that's two tasks back. Without context=[research_task], the editor only sees the draft and can't verify sources.context=.The pattern: sequential order handles the one-step-back case; context= handles everything else.
edit_task = Task( description="Edit the draft for SEO clarity and factual accuracy.", expected_output="A polished, fact-checked article ready to publish.", agent=editor_agent # No context= — editor only sees the draft, not the research )
This task compiles without error — the bug is silent. The editor agent receives the draft but has no access to the research findings, so it can't fact-check claims against sources.
The editor's prompt contains only the draft text (the immediate predecessor's output). The research task's keyword list, source URLs, and factual claims are absent. The editor may silently rewrite or drop facts it can't verify — no error is raised, but the published article can contradict the research.
edit_task = Task( description="Edit the draft for SEO clarity and factual accuracy.", expected_output="A polished, fact-checked article ready to publish.", agent=editor_agent, context=[research_task, draft_task] # both outputs injected )
Adding context=[research_task, draft_task] appends both tasks' strings to the editor's prompt. The editor now sees the keyword targets from research alongside the draft, enabling real fact-checking.
Yes. Sequential order always delivers the immediate predecessor's output regardless of context=. Listing draft_task in context= is redundant but harmless — it just means the draft appears twice in the prompt. The important addition is research_task, which would otherwise be skipped.
In mode, CrewAI inserts a manager agent above your task list. After each task completes, the manager inspects the output and decides whether to accept it, request a revision, or it to a different agent.
This is the key difference from sequential mode: the manager can loop a task back, so the pipeline is no longer strictly linear. A research output that looks thin can be sent back to the researcher before the writer ever sees it.
The tradeoff: hierarchical mode costs more tokens (the manager's reasoning adds calls) and can loop indefinitely if the manager's goal is too vague. Set a max_iter on the crew to cap runaway loops.
brand_editor_agent = Agent( role="Brand Voice Editor", goal="Rewrite the article to match the brand's conversational tone.", backstory="You are a senior copywriter who enforces brand guidelines.", llm=llm ) brand_edit_task = Task( description="Adjust tone and style for brand consistency.", expected_output="Brand-aligned article, ready for CMS upload.", agent=brand_editor_agent, context=[TODO] # ← which tasks does this agent need? ) crew = Crew( agents=[researcher, writer, editor_agent, brand_editor_agent], tasks=[research_task, draft_task, edit_task, brand_edit_task], # … )
Stop — attempt the TODO before revealing. The brand editor runs last and must apply brand tone to the already-edited article while staying faithful to the research.
context=[edit_task] ← CHANGED LINE
Why: edit_task is the direct predecessor, so its output arrives automatically — but listing it explicitly is fine and makes intent clear. research_task is NOT needed here: the brand editor's job is tone, not fact-checking; the SEO editor already verified facts. Adding research_task would bloat the prompt with data the brand editor doesn't use. If your brand editor also fact-checks, add research_task too — but that's a scope decision, not a wiring rule.
context= raises no error — the agent works with less information. Symptom: the editor's output contradicts facts from research.expected_output string.context= inflates the prompt and raises token cost. Check — if tokens spike, audit which context entries are used.context attribute before kickoff and confirm the listed Task objects are correct.The next module covers Failure Modes, Cost Control, and Verifying AI Output — token runaway, missing termination conditions, and bad task boundaries.
Identify role theater, runaway token costs, missing termination conditions, and bad task boundaries in the SEO-page crew — then apply concrete fixes and a verification checklist to confirm the AI-generated output meets the page spec.
How to spot wasted agents, control token costs, and verify that a CrewAI-generated SEO page meets its spec before publishing.
Why this matters: A crew that looks correct can silently burn budget or produce off-spec output — this module gives you the audit and verification tools to catch both before they reach production.
Answer: CrewAI uses . A downstream lists the upstream task in its context field. The finished output injects into the next agent's prompt automatically.
That wiring is powerful. But every agent in the chain burns tokens, whether or not it adds real value. Module 5 asks: which agents earn their cost? How do you confirm the final page meets the spec?
happens when an rolebackstory but brings no unique tool, information source, or decision right.
The symptom: the agent's output is a light restatement of its input. It paraphrases rather than transforms. Each task triggers a full LLM call, so a theatrical agent adds latency and cost with no quality gain.
The fix is one question: "What can this agent do or know that the previous one cannot?"
expected_output field.Imagine the SEO-page crew has three agents: a Researcher, an Outline Editor, and a Writer. The Outline Editor's only job is to reorder the Researcher's bullet points before passing them to the Writer.
Apply the audit question: the Outline Editor uses no unique tool, accesses no new data, and has no approval authority. Its output is a cosmetically reordered version of the Researcher's output.
The fix: delete the Outline Editor agent and its task. Move the ordering instruction — "structure findings as H2 sections in priority order" — into the Writer task's expected_output field. The Writer now receives the Researcher's raw output via context and applies the structure itself.
After returns, exposes total_tokens, prompt_tokens, and completion_tokens. Multiply total tokens by your model's per-token price.
Two common budget failures: (1) runaway loopsexpected_output causes infinite retries; (2) context bloat — passing a 4,000-token dump to every downstream task multiplies cost by agent count.
Concrete fixes: set max_iterAgent to 5–8 for deterministic tasks (default is 25). Summarise large context outputs before passing them downstream.
Missing termination condition: if max_iter stays at default and the task is ambiguous, the agent spins through 25 LLM calls before failing — costing 10–25× normal with no useful output.researcher = Agent( role="SEO Researcher", goal="Find top-ranking facts for 'crewai tutorial'", backstory="Expert in search-intent analysis.", max_iter=6, # cap retry loops max_tokens=800, # cap per-call output length ) result = crew.kickoff(inputs={"topic": "crewai tutorial"}) metrics = crew.usage_metrics print(f"Total tokens: {metrics.total_tokens}") print(f"Est. cost @ $0.002/1k: ${metrics.total_tokens / 1000 * 0.002:.4f}")
This fragment shows the two guardrail levers — max_iter to cap retry loops and max_tokens to cap output length — then reads after kickoff to compute a concrete dollar estimate.
usage_metrics shows 2–3× expected tokens. Removing the theatrical agent produces the same page. Cause: an agent with no unique capability still triggers a full LLM call.
Observable: the run hangs for minutes, then raises TaskError: max iterations reachedexpected_output says "a good draft" instead of "800-word draft with H2 sections and meta description ≤160 chars".
context to three downstream tasks costs 12,000 prompt tokens just for re-injection. Fix: summarise to ≤500 tokens before passing downstream.
The Writer re-researches facts the Researcher already found. Cause: task descriptions overlap — both say "gather relevant facts". Fix: make each task mutually exclusive and reference the upstream output explicitly.
def verify_seo_output(result, metrics, budget_tokens=5000): output = result.raw checks = { "h1_present": output.startswith("# "), "word_count_ok": 700 <= len(output.split()) <= 900, "meta_desc_ok": # TODO: extract <meta> and check len ≤ 160 "faq_present": "FAQ" in output or "## Frequently" in output, "under_budget": metrics.total_tokens <= budget_tokens, } failed = [k for k, v in checks.items() if not v] return failed # empty list = pass
This completion fragment implements four of the five verification checks against the SEO-page spec; your job is to fill in the meta_desc_ok check. The function returns a list of failed check names so you can act on each one programmatically.
# Changed line (meta_desc_ok):
"meta_desc_ok": len(next((l.replace("meta:","").strip() for l in output.splitlines() if l.startswith("meta:")), "")) <= 160
# Why: next() finds the first matching line without crashing if absent (defaults to "", which has len 0 — a safe fail). replace() strips the prefix before measuring. This is the crux: the other four checks are structural (startswith, word count, keyword, token count); this one requires parsing a specific field from the output, which is the pattern you'll reuse for any spec-driven verification.
Before trusting any CrewAI-generated SEO page, run through these five concrete checks:
usage_metrics.total_tokens) are within your budget ceiling.role theaterexpected_output is specific enough to check manually in under 30 seconds.
You've built, wired, run, and stress-tested a full multi-agent crew. The solo capstone challenge asks you to design a new crew from scratch — picking agents, scoping tasks, setting guardrails, and verifying output — with no scaffolding.
Before reading the summary: from memory, list the five build steps in order, name the two process modes and when you'd pick each, and describe what happens to a task's output after it finishes. Then check your answer against the buildOrder below.
Apply what you learned to SEO/GEO page — the page title is the H1 and the exact search query. OPEN with a 40-60 word self-contained, quotable answer capsule that names the entity explicitly in sentence one (no "in this lesson…" preamble) — this is the sentence an LLM lifts. Name the entity by its full name every time (not pronoun-only). Structure each section as ONE sub-question (How it works · X vs Y · When to use it · Example · Common mistakes), each opening with its own 1-2 sentence direct answer then depth. End with a genuine 3-5 question FAQ phrased as real user questions ending in "?" (these become FAQPage schema + the knowledge check). Prefer quotable specifics — concrete numbers, defaults, version names, one short snippet — over vague prose. Self-contained for a reader who arrived cold from a search engine or an LLM. Intent = tutorial: numbered steps + one short runnable code snippet + a common-mistakes section. Target query: "crewai tutorial"..
A CrewAI Agent is defined with four core fields. Which combination below is correct?
agent = Agent(
role="SEO Writer",
goal="Draft keyword-rich content",
backstory="You are a seasoned content strategist.",
tools=[search_tool]
)
All four fields shape the LLM system prompt: role sets the persona, goal sets the directive, backstory adds context that steers reasoning style, and tools lists what the agent can call. Saying backstory and tools are optional with no effect is wrong — backstory meaningfully changes how the model reasons, and tools not attached to an agent are invisible to it. Backstory does not replace the system prompt; it is injected into it. Tools are attached at the Agent level, not the Crew level.
You have a Task defined like this:
task2 = Task(description="Summarize findings", expected_output="A 3-bullet summary", agent=editor, context=[task1])
What does context=[task1] do?
context= chains tasks by passing the upstream task's output as additional input to the downstream task's prompt — that is how one agent's findings reach the next agent. It has nothing to do with parallelism (sequential process runs tasks in order), re-running upstream tasks, or sharing tools. Tools belong to agents, not tasks.
When should you choose Process.hierarchical over Process.sequential in a CrewAI Crew?
Process.hierarchical adds a manager agent that can re-route or re-assign tasks dynamically — the right choice when the workflow is conditional or when no fixed order can be predetermined. Process.sequential is the correct pick for a fixed, predictable pipeline. Hierarchical mode adds a manager LLM call, so it costs more tokens, not fewer. Sequential mode works fine with two agents; there is no minimum agent count.
You add a third 'Editor' agent to an existing two-agent CrewAI crew (Researcher + Writer). What two things must you do to wire the Editor into the task chain without breaking the existing context flow?
Adding an agent alone does nothing — you must also create a Task assigned to that agent. Setting context= on the new task to reference the prior task ensures the output chain is unbroken. Forgetting either step (the task assignment or the context wiring) leaves the editor either idle or working without the writer's output.
Which of the following is the clearest sign of 'role theater' in a CrewAI crew?
Role theater is when an agent exists in name only — it has a label but brings no unique tool access or decision authority, so it adds token cost without adding capability. Two agents sharing a model is fine as long as their roles, tools, and decision rights differ. Process choice is unrelated to role theater. The relative length of expected_output versus description is a task-scoping concern, not a role theater signal.