MAF workflows — multi-agent orchestration
MAF workflows are graphs of agents (executors) for sequential, parallel, conditional, and looping orchestration. Here's a 3-agent planner → executor → reviewer pattern.
What you'll learn
- When to reach for a workflow vs. a single agent with tools
- The four orchestration shapes — sequential, parallel, conditional, loop
- Executors as nodes — agents, functions, and custom logic on the same graph
- A 3-agent planner → executor → reviewer workflow you can adapt
Before you start
You watch a teammate’s ChatAgent system prompt grow from 80 words to
600 over a sprint. It’s now juggling “first plan the steps, then
execute, then double-check your work, but only if the user asked for
high accuracy, and never reveal internal IDs, oh and also format the
output as markdown.” Quality is sliding, hallucinations are creeping
in, and nobody can tell which instruction caused which regression.
That’s the moment to stop adding instructions and start splitting
the work across agents.
A single ChatAgent with good tools handles most jobs. Workflows
are what you reach for when one agent isn’t enough — when you need a
researcher to feed a writer, a planner to dispatch to specialists, or a
loop that refines an answer until a quality bar is met. Workflows in
MAF are explicit graphs: you wire executors (the nodes in a workflow
graph — any agent, plain function, or custom logic class) together with
edges and conditions, and MAF runs the DAG. Because the sequencing is
encoded in the graph rather than in a single agent’s instructions, each
node stays focused and the coordination logic is explicit and auditable.
A MAF workflow is a graph: ChatAgent nodes joined by edges, with conditional edges for loops and branches.
When to use a workflow
The honest test: don’t build a workflow until a single agent demonstrably fails. Workflows multiply latency, cost, and debugging surface. But when the task genuinely has stages with different contexts, a workflow beats jamming everything into one agent’s instructions.
Good fits:
- Pipeline tasks — research → draft → review → publish.
- Routing — classify the request, dispatch to a specialist.
- Refinement loops — generate → critique → revise until good enough.
- Parallel synthesis — three agents each summarize a doc, a fourth merges.
Bad fits:
- One agent + a few tools would do it.
- The “agents” are really just different prompts on the same model — that’s just chaining, use a workflow only if the orchestration is genuinely conditional.
The four shapes
MAF workflows give you four building blocks:
| Shape | What it does |
|---|---|
| Sequential | A → B → C. Each executor’s output is the next one’s input. |
| Parallel | A fans out to B, C, D running concurrently; results merge. |
| Conditional | A decides which branch (B or C) runs based on output. |
| Loop | Repeat an executor (or sub-graph) until a condition is met. |
You compose these — a sequential workflow can have a parallel step, which can have a loop inside it. The graph is the architecture.
A planner → executor → reviewer workflow
Here’s the canonical 3-agent pattern: a planner breaks the task into steps, an executor does the work, a reviewer checks quality. If the reviewer rejects, loop back to the executor.
# requires: pip install agent-framework + Azure credentials to run.
# This is the real MAF shape — a reference you'd paste into a project.
from agent_framework import ChatAgent, WorkflowBuilder
# Assume chat_client is already built (see maf-overview lesson).
# chat_client = AzureOpenAIChatClient(...)
planner = ChatAgent(
chat_client=chat_client,
name="planner",
instructions=(
"You receive a user task. Return a numbered plan of 3-5 steps. "
"Each step should be one sentence, action-oriented."
),
)
executor = ChatAgent(
chat_client=chat_client,
name="executor",
instructions=(
"You receive a plan. Execute it and return the result. "
"Be concrete; avoid generic statements."
),
)
reviewer = ChatAgent(
chat_client=chat_client,
name="reviewer",
instructions=(
"Review the executor's output against the original task. "
"Respond with exactly one of: APPROVE or REVISE: <reason>."
),
)
# Build the graph. Edges define the flow.
workflow = (
WorkflowBuilder()
.add_node(planner)
.add_node(executor)
.add_node(reviewer)
.add_edge(planner, executor)
.add_edge(executor, reviewer)
# Conditional: if reviewer says REVISE, loop back to executor.
.add_conditional_edge(
reviewer,
condition=lambda out: "REVISE" in out.text,
target=executor,
)
.set_entry(planner)
.build()
)
# Run it. The workflow returns when the reviewer says APPROVE
# (or when max_iterations is hit — always cap loops).
async def main():
result = await workflow.run(
"Write a 3-bullet executive summary of why our Q1 churn dropped.",
max_iterations=5,
)
print(result.final_output)
print("Shape only — needs Azure credentials to actually run.")
The key idea: executors aren’t all agents. A node in the graph can also be a plain Python function (for deterministic logic like formatting or validation) or a custom executor class. Agents are just the most common kind.
Parallel fan-out
When subtasks are independent, run them concurrently. Here’s the shape:
researcher_finance = ChatAgent(...)
researcher_legal = ChatAgent(...)
researcher_market = ChatAgent(...)
synthesizer = ChatAgent(...)
workflow = (
WorkflowBuilder()
.add_parallel_step([researcher_finance, researcher_legal, researcher_market])
.add_node(synthesizer)
# Edge from the parallel step to the synthesizer — exact method name
# varies by MAF version; check current docs for the parallel→node edge API.
.add_edge_from_parallel(synthesizer)
.build()
)
Three researchers run in parallel, each on the same input but with different specialist instructions. The synthesizer receives all three outputs and produces a combined answer. The latency is the slowest researcher, not the sum.
State between executors
Each executor produces a message; downstream executors see the previous message as input. For richer state (counters, retrieved documents, intermediate scores), use a workflow state object — typically a Pydantic model that nodes can read from and write to. The exact API name and shape varies by MAF version, so check the docs for the current pattern.
When workflows beat single agents
The clearest sign you need a workflow: the agent’s system prompt is becoming a manual. If you’re writing 500 words of instructions to make one agent juggle five different jobs, split it into a workflow. Specialized agents with focused instructions consistently beat one agent with a giant prompt — same model, sharper context, fewer hallucinations.
The clearest sign you don’t: you can describe the task in one sentence and one tool list. Don’t build a 4-node graph for “answer questions about our docs.” That’s RAG + one agent.
In one breath
- A workflow is an explicit graph of executors (agents, plain functions, or custom classes) — reach for it only when a single agent demonstrably fails.
- Four shapes compose freely: sequential (A→B→C), parallel (fan-out/merge), conditional (branch on output), loop (repeat until a bar is met).
- The canonical pattern is planner → executor → reviewer with a conditional edge looping back on
REVISE— always cap it withmax_iterations. - The win is focused agents over a 500-word catch-all prompt: same model, sharper context, fewer hallucinations — but parallel multiplies cost (~3× for three agents).
- The tell you don’t need a workflow: you can state the task in one sentence and one tool list (that’s just RAG + one agent).
Quick check
Quick check
Next
Workflows handle multi-agent orchestration. The next lesson covers middleware — the cross-cutting concerns (logging, guardrails, rate limiting) that wrap around every agent call regardless of workflow shape.
Practice this in an interview
All questionsUse multiple agents when a task decomposes into distinct specialties or parallel subtasks that exceed one agent's context or reliability; avoid it when a single agent suffices, since multi-agent systems add coordination overhead, latency, cost, and error propagation. A supervisor architecture has an orchestrator routing work to specialized sub-agents, while a swarm lets peer agents hand off control to one another without a central coordinator.
ML workflows are multi-step DAGs with dependencies, and an orchestrator gives you dependency management, retries, backfills, caching, observability, and lineage that chained cron jobs cannot. Airflow is a general-purpose task orchestrator defining DAGs in Python, while Kubeflow Pipelines is ML-native, passing typed artifacts between containerized steps on Kubernetes with conditional logic like deploy only if accuracy exceeds a threshold. Choosing depends on whether you need generic scheduling or ML-specific, container-based pipelines.
An agent is an LLM placed in a loop where it reasons, chooses and calls tools or actions, observes the results, and repeats until a goal is met, rather than producing one response and stopping. The key differences are autonomy, tool use, memory and state, and multi-step control flow driven by the model's own decisions.
ReAct interleaves reasoning traces with actions step by step, deciding the next tool call based on the latest observation. Plan-and-Execute first drafts a full multi-step plan and then executes it, which is more efficient and predictable for complex tasks but less adaptive, while Reflexion adds a self-reflection step where the agent critiques past failures and retries with that feedback.