datarekha

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.

8 min read Advanced Agentic AI Lesson 43 of 71

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.

WorkflowBuilder graph — ChatAgent nodes connected by edgesinputplannerChatAgentdecompose taskexecutorChatAgentdo the workreviewerChatAgentjudge outputdoneAPPROVEconditional edge: REVISE → executorSequential edges + one conditional fork = the canonical 3-agent patternEach node is a focused agent; the graph encodes who calls whomalways cap loops with max_iterations

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:

ShapeWhat it does
SequentialA → B → C. Each executor’s output is the next one’s input.
ParallelA fans out to B, C, D running concurrently; results merge.
ConditionalA decides which branch (B or C) runs based on output.
LoopRepeat 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 with max_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

0/2
Q1What's the main reason to split a task across multiple agents in a workflow?
Q2In a planner → executor → reviewer workflow, what does the conditional edge from reviewer back to executor do?

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.

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Practice this in an interview

All questions
When should you use a multi-agent system versus a single agent, and what is the supervisor versus swarm pattern?

Use 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.

Why use a pipeline orchestrator like Airflow or Kubeflow instead of cron scripts for ML workflows?

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.

What is an AI agent, and how does it differ from a single LLM call?

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.

Explain the ReAct agent pattern and how it compares to Plan-and-Execute and Reflexion.

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.

Related lessons

Explore further

Skip to content