Have you ever watched a well-run kitchen? The sous chef preps, the line cook assembles, and the finishing chef plates. Each person does one focused job — and the dish passes from hand to hand until it’s ready to serve. AI agent pipelines work the same way.
In this post, we’ll walk through a real code example that chains three AI agents together — a Planner, a Researcher, and a Writer — so each one builds on the work of the one before it. By the end, you’ll understand how to build your own sequential pipelines using the Microsoft Agent Framework.
The Problem With One Big Agent
When you first start building AI tools, it’s tempting to write one long system prompt that does everything:
“You are a research assistant. Given a topic, come up with questions, research them, and then write a polished report.”
This works for simple tasks. But as complexity grows, a single agent starts to struggle:
- It tries to do too much at once and loses focus
- It’s hard to debug which step went wrong
- You can’t improve one part without affecting everything else
The sequential pipeline pattern solves this by giving each agent one job and letting them pass their work down the line.
The Architecture: Three Focused Agents
Here’s the pipeline we’ll build:
┌──────────┐ ┌────────────┐ ┌────────┐
│ Planner │────▶│ Researcher │────▶│ Writer │
└──────────┘ └────────────┘ └────────┘
- Planner — Takes a topic and produces exactly 3 focused research questions
- Researcher — Reads those questions and writes factual findings for each
- Writer — Reads both the questions AND findings, then synthesizes a polished report
The magic is in that last point: every agent downstream sees the full conversation history. The Researcher doesn’t get a blank slate — it sees what the Planner wrote. The Writer sees everything.
Writing the Agent Instructions
Each agent is defined by a clear, strict set of instructions. Think of these as job descriptions.
PLANNER_INSTRUCTIONS = """
You are a research planner.
Given a topic, produce EXACTLY 3 focused research questions — numbered list, one per line.
No preamble. No explanation. Just the numbered list.
""".strip()
Notice how specific this is. The planner doesn’t need to know how to research anything — it just creates questions. Tight instructions = predictable, reliable output.
RESEARCHER_INSTRUCTIONS = """
You are a research analyst.
You will receive a list of research questions (from the Planner's message above yours).
Answer EACH question with a concise factual finding in 2-4 sentences.
Format your response as:
FINDING 1: <answer to question 1>
FINDING 2: <answer to question 2>
FINDING 3: <answer to question 3>
""".strip()
The researcher’s instructions specifically tell it where the questions come from (“from the Planner’s message above yours”). This sets the right mental model for the agent about its context.
WRITER_INSTRUCTIONS = """
You are a technical writer.
You will receive research questions (from Planner) and findings (from Researcher) above.
Synthesise them into a structured markdown report with:
- # Title (H1)
- One-paragraph introduction
- ## Section per finding (H2), using the question as the heading
- ## Conclusion section (H2)
Use the findings verbatim — do not add information not present in the findings.
""".strip()
The writer gets a strict template, ensuring the final output is always structured consistently. Notice the constraint: “do not add information not present in the findings.” This prevents the writer from hallucinating new content.
Creating the Agents
With instructions defined, creating the agents is clean and readable:
async def run_sequential_pipeline(topic: str) -> None:
chat_client = OpenAIChatClient()
planner = chat_client.as_agent(
name="Planner",
instructions=PLANNER_INSTRUCTIONS,
)
researcher = chat_client.as_agent(
name="Researcher",
instructions=RESEARCHER_INSTRUCTIONS,
)
writer = chat_client.as_agent(
name="Writer",
instructions=WRITER_INSTRUCTIONS,
)
Each agent is just a name + instructions. No tools, no databases, no complexity — just focused language model roles.
Wiring Them Together with SequentialBuilder
Here’s where the framework shines. Instead of manually calling each agent and passing output to the next, SequentialBuilder handles all of that:
workflow = SequentialBuilder(
participants=[planner, researcher, writer],
intermediate_outputs=True,
).build()
agent = workflow.as_agent(name="ResearchPipeline")
The participants list defines the order. SequentialBuilder will:
1. Run planner with the initial user message
2. Append the planner’s response to the conversation
3. Run researcher with the full conversation (user message + planner response)
4. Append the researcher’s response
5. Run writer with all three messages
The intermediate_outputs=True flag means you can see what each agent produced before the pipeline finishes — great for debugging.
You then treat the whole pipeline as a single agent:
response = await agent.run(f"Research topic: {topic}")
One call in, a complete multi-stage report out.
Reading the Results
The response contains every message produced during the pipeline run. Here’s how the example code reads them:
if response.messages:
for msg in response.messages:
name = getattr(msg, "author_name", None) or getattr(msg, "role", "?")
role_str = str(getattr(msg.role, "value", msg.role)).lower()
if role_str == "user":
print(f"\n[USER]\n{msg.text}\n")
else:
print(f"\n{'─'*60}")
print(f"[{str(name).upper()}]\n{msg.text}")
This loops through all messages, labels them by author, and prints them in order. You’ll see output like:
[USER]
Research topic: Quantum computing and its impact on cybersecurity
────────────────────────────────────────────────────────────
[PLANNER]
1. What are the primary cryptographic algorithms threatened by quantum computing?
2. What is the current state of quantum-resistant cryptography standards?
3. What timeline are security researchers projecting for quantum threats?
────────────────────────────────────────────────────────────
[RESEARCHER]
FINDING 1: ...
FINDING 2: ...
FINDING 3: ...
────────────────────────────────────────────────────────────
[WRITER]
# Quantum Computing and Cybersecurity: A Research Summary
...
The Key Insight: Context Accumulates Naturally
The most important concept here is that you don’t have to manually pass outputs between agents. The framework appends each agent’s response to the shared conversation thread. Every downstream agent sees the full history.
Think of it like a relay race where the baton carries all previous context, not just the most recent handoff.
This design means:
– Less glue code — you don’t write string-parsing logic to extract outputs and re-inject them
– Better context — the writer doesn’t just get dry findings; it sees the original questions too, giving it better framing
– Easier debugging — you can inspect the full conversation to see exactly where something went wrong
When Should You Use a Sequential Pipeline?
Use SequentialBuilder when:
| Situation | Example |
|---|---|
| Each step depends on the previous step | Plan → Research → Write |
| You want to break a complex task into auditable stages | Draft → Review → Edit |
| Output format from one step feeds the next | Outline → Expand → Format |
| You want to independently improve one stage | Swap out the Writer without touching the Planner |
Avoid it when steps are independent and could run in parallel (that’s a different pattern — ParallelBuilder), or when you need dynamic branching based on intermediate results (use an orchestrator agent instead).
Putting It All Together
Here’s the complete flow in plain English:
- You call
run_sequential_pipeline("Quantum computing and cybersecurity") - The user message hits the Planner, which outputs 3 numbered questions
- The conversation now has: user message + planner questions
- The Researcher reads it all and adds 3 findings
- The conversation now has: user message + planner questions + researcher findings
- The Writer reads it all and produces a structured markdown report
- You get back all messages, neatly labeled
Try It Yourself
Here are some fun topics to run through this pipeline:
await run_sequential_pipeline("The future of remote work")
await run_sequential_pipeline("How large language models actually work")
await run_sequential_pipeline("Climate tech innovations in 2025")
Challenge: Try swapping the Writer’s template. What happens if you change it to produce a bulleted executive summary instead of a formatted report? That’s the beauty of this architecture — you only need to change one agent’s instructions.
Summary
| Concept | What it means |
|---|---|
| Sequential pipeline | Agents run in order, each building on the last |
SequentialBuilder |
Framework class that wires agents into a pipeline |
| Shared conversation | Each agent sees all previous messages, not just the last one |
| Tight instructions | Each agent has one job, described precisely |
intermediate_outputs=True |
See each agent’s output before the pipeline completes |
The sequential pipeline pattern is one of the most useful tools in multi-agent AI development. It keeps your system modular, debuggable, and easy to improve — one stage at a time.
Leave a Reply