A researcher finds three facts. A writer produces a fluent paragraph containing four. Did adding a second agent improve the work? CrewAI gives us a way to separate responsibilities, but we still need to examine what travels between them.
Before you begin: Understand the agent loop and have a Python environment for optional provider calls.
A role is a prompt, a task is a contract
CrewAI organizes agents, tasks, and a process for running them. An agent's role and goal shape its instructions. They do not confer professional knowledge or independent judgment. A task describes work and its expected output. A crew connects the tasks and agents.
For this exercise, the input is a fictional notice: “W1 starts at 15:00. Capacity is 12. Booking status is not listed.” One task extracts stated facts. A second writes a concise explanation from those facts. A sequential process makes the dependency visible: writing follows extraction.
Before trying two agents, write the desired answer yourself. It should mention the start time and capacity without inventing remaining seats. This reference lets you evaluate behavior instead of admiring how many roles are involved.
Construct a small crew
This is a complete provider integration example, reviewed against CrewAI documentation on September 10, 2026. It has not been run against a paid model here. Install crewai in a compatible virtual environment. Configure the selected provider's credentials and set CREWAI_MODEL to its supported model identifier.
import os
from crewai import Agent, Task, Crew, Process
model = os.environ["CREWAI_MODEL"]
extractor = Agent(
role="Fact extractor",
goal="Preserve only facts stated in the supplied notice.",
backstory="You produce short evidence notes for an editor.",
llm=model,
allow_delegation=False,
max_iter=3,
)
writer = Agent(
role="Notice editor",
goal="Explain the evidence without adding booking claims.",
backstory="You keep unknown information explicit.",
llm=model,
allow_delegation=False,
max_iter=3,
)
extract = Task(
description=(
"Extract facts from this fictional source N1: "
"W1 starts at 15:00. Capacity is 12. "
"Booking status is not listed."
),
expected_output="Facts with source N1; distinguish unknown booking status.",
agent=extractor,
)
write = Task(
description="Explain W1 using only the extracted facts. Preserve unknowns.",
expected_output="Two short sentences with source N1.",
agent=writer,
context=[extract],
)
result = Crew(
agents=[extractor, writer],
tasks=[extract, write],
process=Process.sequential,
verbose=False,
).kickoff()
print(result.raw)
The explicit context relationship tells the writing task which earlier result it needs. The task's expected_output is an instruction, not a schema validator. The iteration bound limits agent work but does not prove task success. None of these fields guarantees that source N1 survives unchanged.
Compare work, not personalities
Inspect the extraction result before reading the final paragraph. If the unknown booking status disappeared during extraction, the writer never received the key qualification. If extraction preserved it but writing dropped it, the second task is the likely failure point.
Record the number of model calls, elapsed time, and accepted answers for the same inputs under one-agent and two-task versions. Use actual observations. Two roles may make debugging easier while still costing more and making the answer worse. The useful architecture is the one that meets your task's evidence and operating requirements.
Repair the handoff
An extractor writes “W1 has 12 seats.” The writer turns that into “12 seats are available.” What information should the intermediate contract carry?
Compare a stronger contract
Carry named facts: capacity: 12, booking_status: unknown, and a source ID. Retain the original evidence as well as the summary. Validate the final answer against these fields. A second agent repeating a first agent's ambiguous wording does not provide independent verification.
For practice, add a contradictory second notice with a different date. Require the extractor to preserve both dates and flag the conflict. The writer should explain the conflict or apply an explicit freshness rule, not silently select its preferred number.
Next, compare these frameworks on one shared task so that changes in the workload do not masquerade as improvements in the framework.
Sources
CrewAI agents documents direct agent configuration. Crews explains execution processes and outputs. Tasks describes task context and result contracts.