A crewai sequential process tutorial needs to show more than toy snippets—you need a working pipeline where tasks execute in order, each feeding the next. In this guide we build a two-agent research-and-write crew that runs tasks back-to-back using Process.sequential, and verify outputs at each step. You’ll leave with a pattern you can copy into production.
Prerequisites
- Python 3.10 or newer
crewaiinstalled (>=0.28.0; Agent/Task/Crew APIs are stable here)- An LLM endpoint. OpenAI works out of the box; alternatively, point CrewAI at any OpenAI-compatible server. If you’d rather not juggle multiple provider keys, an OpenAI-compatible gateway like n4n.ai can serve as a drop-in
base_urlfor CrewAI’s LLM config, with automatic fallback across providers. OPENAI_API_KEY(or equivalent) exported in your shell
Install and configure
pip install crewai
export OPENAI_API_KEY=sk-...
If you use a gateway, configure the LLM wrapper before defining agents:
from crewai import LLM
llm = LLM(
model="gpt-4o-mini",
base_url="https://api.n4n.ai/v1", # OpenAI-compatible endpoint
api_key="your-gateway-key",
)
The LLM class mirrors LangChain’s chat model kwargs. Use the model name exactly as your provider expects.
Define agents
Two agents: one retrieves facts, one writes. Keep roles narrow.
from crewai import Agent
researcher = Agent(
role="Senior Research Analyst",
goal="Find concise, factual information about {topic}",
backstory="You dig through sources and return bullet-point briefs.",
llm=llm,
verbose=True,
)
writer = Agent(
role="Technical Writer",
goal="Turn research briefs into a clean markdown summary",
backstory="You write for engineers who want no fluff.",
llm=llm,
verbose=True,
)
verbose=True streams each agent’s internal steps to stdout, which makes the sequential handoff visible.
Define tasks with dependencies
Tasks are the units of work. In a sequential crew, order is the list order you pass to Crew. The output of task N is injected as context into task N+1 automatically.
from crewai import Task
research_task = Task(
description="Research the topic: {topic}. Return 3 key facts with sources.",
expected_output="Bullet list of 3 facts, each with a one-line source.",
agent=researcher,
)
write_task = Task(
description="Using the research brief, write a 150-word markdown summary.",
expected_output="Markdown summary with a heading and the 3 facts woven in.",
agent=writer,
)
You do not need to manually set context=; Process.sequential handles it. If you later move to Process.hierarchical, you’d need explicit context or a manager.
Assemble the crew with Process.sequential
from crewai import Crew, Process
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task],
process=Process.sequential,
verbose=True,
)
result = crew.kickoff(inputs={"topic": "vector databases"})
print(result)
That’s the whole crewai sequential process tutorial core: agents, ordered tasks, Process.sequential.
Run and inspect outputs
Execute the script. Checkpoint after the first task completes:
[Senior Research Analyst] Task output:
- Fact 1: Vector databases index embeddings for similarity search. (Source: Pinecone docs)
- Fact 2: HNSW graphs enable fast approximate nearest neighbor lookup. (Source: arXiv:1603.09320)
- Fact 3: Many support metadata filtering alongside vectors. (Source: Weaviate docs)
The writer then receives that text under a Context header and produces:
# Vector Databases
Vector databases index embeddings for similarity search. HNSW graphs enable fast
approximate nearest neighbor lookup. Many support metadata filtering alongside vectors.
These properties make them core to retrieval-augmented generation pipelines.
The final printed result is the writer’s markdown string.
Accessing intermediate results
After kickoff, each Task object holds its output. Use this for logging or downstream piping:
print("Research raw:", research_task.output.raw)
print("Write raw:", write_task.output.raw)
.raw is the string the agent returned. .json_dict or .pydantic are available if you set output_json/output_pydantic on the task, but for sequential text flows .raw suffices.
Expected output walkthrough
The sequential process guarantees research_task finishes before write_task starts. With verbose=True on the crew you’ll see a linear log:
├── Task 1: Research the topic...
│ └── Agent: Senior Research Analyst
├── Task 2: Using the research brief...
│ └── Agent: Technical Writer
No interleaving. That determinism is why a crewai sequential process tutorial matters: you can reason about data flow and cost. The second agent’s prompt automatically includes prior output. Override by setting context=[research_task] explicitly if you want to be declarative.
When to use sequential vs hierarchical
Sequential fits straight-line pipelines: research → draft → edit. Hierarchical (Process.hierarchical) adds a manager agent that delegates dynamically, better for ambiguous multi-step jobs. For batch content gen or LLM-ETL, sequential wins on predictability and token cost. Trade-off: no mid-flight re-planning. If research fails, the crew raises unless you catch it.
Common pitfalls
- Missing inputs. Tasks with
{topic}requireinputs=inkickoff. Omit it and CrewAI throws a template error. - Assuming parallelism. Sequential is one-after-another. Multiple agents don’t run concurrently here.
- Bloated descriptions. Put the action in
description, format rules inexpected_output. - Model name mismatch. With a gateway, the
modelstring must be supported by the endpoint exactly as named.
Extending the pattern
Add a proofread step by appending a task:
proof_task = Task(
description="Fix grammar in the summary without changing facts.",
expected_output="Corrected markdown string.",
agent=researcher,
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task, proof_task],
process=Process.sequential,
)
This crewai sequential process tutorial would be incomplete without showing that scaling is just list appends. Because the process is sequential, the new task slots in last. You can also attach task_callback to persist each output.
Full script reference
from crewai import Agent, Task, Crew, Process, LLM
llm = LLM(model="gpt-4o-mini", base_url="https://api.n4n.ai/v1", api_key="key")
researcher = Agent(role="Senior Research Analyst", goal="Find facts about {topic}",
backstory="Concise briefs.", llm=llm, verbose=True)
writer = Agent(role="Technical Writer", goal="Summarize briefs",
backstory="Engineer-focused.", llm=llm, verbose=True)
research_task = Task(description="Research {topic}. 3 facts with sources.",
expected_output="Bullet list.", agent=researcher)
write_task = Task(description="Write 150-word markdown summary from brief.",
expected_output="Markdown.", agent=writer)
crew = Crew(agents=[researcher, writer], tasks=[research_task, write_task],
process=Process.sequential, verbose=True)
print(crew.kickoff(inputs={"topic": "vector databases"}))
Run it. You have a deterministic, observable linear crew.