Learn

Agent orchestration patterns for multi-agent systems

Five agent orchestration patterns for multi-agent systems, from sequential and routing to hierarchical, when to use each, and how to build them in Dynamiq.

Oleksii BabychMachine learning engineer7 min readUpdated

In short

Most multi-agent systems combine five orchestration patterns: sequential, routing, parallel, hierarchical and evaluator loops. Linear orchestration runs agents in a fixed order, for processes where every step must happen; adaptive orchestration lets a manager agent pick the next specialist, for open-ended work. In Dynamiq you build both with the Graph Orchestrator and a manager agent.

Multi-agent systems coordinate specialized agents in one of two basic ways. A linear pattern runs them in an order you define, like an assembly line; an adaptive pattern lets a manager agent decide at run time which specialist works next. In Dynamiq, the Graph Orchestrator covers linear and branching flows, and a manager agent that uses other agents as tools covers adaptive delegation.

If you used an earlier version of the SDK, you may remember separate LinearOrchestrator and AdaptiveOrchestrator classes. The current SDK expresses both patterns with the building blocks in this guide, and all code below uses the current API.

What does an orchestrator do in a multi-agent system?

An orchestrator is the part of a multi-agent system that decides who does what, in which order, with which context. It does five jobs:

  • Breaks down the task into steps a single agent can handle.
  • Assigns each step to the agent with the right role and tools.
  • Passes context from one step to the next, without flooding each agent with everything.
  • Combines the results into one answer.
  • Enforces limits such as maximum loops, so a confused agent cannot run forever.

In an enterprise setting it has a sixth job: leaving a record. Every decision the orchestrator makes should be visible afterward, which is why every run in Dynamiq is traced.

What are the common agent orchestration patterns?

Most multi-agent systems are built from five orchestration patterns. Production systems usually combine several of them, and add a person at the steps that need approval.

Pattern How it works Use it when In Dynamiq
Sequential (linear) Agents run in a fixed order, each passing its output to the next Every step must happen, such as a due diligence checklist Graph Orchestrator states joined by edges, or a workflow
Routing A classifier or a rule sends each request to one specialist Requests fall into clear types, such as billing versus fraud The Choice node, or conditional edges in the Graph Orchestrator
Parallel (fan-out and fan-in) Several agents work at once and a final step merges their results Checks or sources are independent, such as screening many parties Independent workflow branches run at the same time; the Map node runs one step per item
Hierarchical (adaptive) A manager agent decides which specialist works next until the goal is met The path cannot be planned in advance, such as open-ended research A manager agent with the Graph Orchestrator
Evaluator loop One agent drafts, another checks the draft against criteria, and it loops back until it passes Output must meet a quality bar, such as a report or a code change A conditional edge back to an earlier state, bounded by max_loops

The rest of this guide goes deep on the two most common choices, linear and adaptive orchestration, and how to build each.

What is linear orchestration?

Linear orchestration runs agents in a sequence you define. Each agent receives the output of the previous step, and the last agent produces the answer. The path is known before the run starts.

This suits processes that must happen the same way every time. A vendor due diligence review, for example, always gathers information first, assesses it against the firm's criteria second and writes the summary last. A bank's compliance team wants that order to be fixed and provable.

What is adaptive orchestration?

Adaptive orchestration gives a manager agent a set of specialist agents and lets it decide, step by step, which one to call next. The manager can call several specialists in parallel, check their work and loop until the task is done.

This suits open-ended work where the path depends on what the agents find, such as research questions, investigations or support requests that could need any of several specialists.

Linear or adaptive: which should you use?

Linear (graph) Adaptive (manager-led)
Who decides the path You, when you design the graph The manager agent, at run time
Predictability High: same steps every run Lower: the path can change between runs
Cost and latency Easier to predict Varies with how many calls the manager makes
Auditability Straightforward to review Needs traces to follow each decision
Best for Reviews, approvals, document processing Research, investigations, open-ended requests
Dynamiq SDK GraphOrchestrator with edges An Agent with other agents in tools

For regulated processes, start linear and add branches where you need them. Use an adaptive manager inside a well-defined step, not as the outer layer of a process an auditor needs to follow.

How do you build a linear flow with the Graph Orchestrator?

The example below runs a three-step vendor due diligence review. Install the SDK with pip install dynamiq and set OPENAI_API_KEY and TAVILY_API_KEY first.

from dynamiq import Workflow
from dynamiq.connections import OpenAI as OpenAIConnection
from dynamiq.connections import Tavily as TavilyConnection
from dynamiq.flows import Flow
from dynamiq.nodes.agents import Agent
from dynamiq.nodes.agents.orchestrators.graph import END, START, GraphOrchestrator
from dynamiq.nodes.agents.orchestrators.graph_manager import GraphAgentManager
from dynamiq.nodes.llms import OpenAI
from dynamiq.nodes.tools.tavily import TavilyTool

llm = OpenAI(connection=OpenAIConnection(), model="gpt-4o", temperature=0.1)
search = TavilyTool(connection=TavilyConnection())  # reads TAVILY_API_KEY

researcher = Agent(
    name="Researcher",
    role=(
        "Find recent public information about the company: ownership, sanctions news, "
        "litigation and major events. Cite every source."
    ),
    llm=llm,
    tools=[search],
    max_loops=8,
)

risk_analyst = Agent(
    name="Risk analyst",
    role=(
        "Assess the research against the firm's vendor risk criteria. Rate each risk as "
        "low, medium or high with a reason. End with one line: RISK: LOW, RISK: MEDIUM or RISK: HIGH."
    ),
    llm=llm,
)

writer = Agent(
    name="Writer",
    role="Write a one-page due diligence summary for a compliance reviewer, with open questions at the end.",
    llm=llm,
)

orchestrator = GraphOrchestrator(name="vendor-due-diligence", manager=GraphAgentManager(llm=llm))
orchestrator.add_state_by_tasks("research", [researcher])
orchestrator.add_state_by_tasks("assess", [risk_analyst])
orchestrator.add_state_by_tasks("write", [writer])

orchestrator.add_edge(START, "research")
orchestrator.add_edge("research", "assess")
orchestrator.add_edge("assess", "write")
orchestrator.add_edge("write", END)

workflow = Workflow(flow=Flow(nodes=[orchestrator]))
result = workflow.run(input_data={"input": "Run vendor due diligence on Example Logistics Ltd."})
print(result.output[orchestrator.id]["output"]["content"])

Each state holds one or more tasks, and edges fix the order. The GraphAgentManager turns the conversation so far into a clear task for the agent in each state, so the analyst sees what the researcher found.

How do you add a branch, such as escalation to a person?

Real processes are rarely a straight line. A conditional edge lets a Python function pick the next state from the shared context. Here, a high-risk rating skips the automated summary and routes the case to a compliance analyst. Add these lines before you run the workflow; the conditional edge replaces the fixed edge from assess to write.

def route_by_risk(context: dict, **kwargs) -> str:
    """Send high-risk vendors to a person instead of the writer."""
    last_message = context.get("history", [{}])[-1].get("content", "")
    return "escalate" if "RISK: HIGH" in last_message else "write"


def escalate(context: dict, **kwargs) -> dict:
    """Record the escalation; your case system would pick it up here."""
    return {"result": "Escalated to a compliance analyst for manual review.", "escalated": True}


orchestrator.add_state_by_tasks("escalate", [escalate])
orchestrator.add_conditional_edge("assess", ["write", "escalate"], route_by_risk)
orchestrator.add_edge("escalate", END)

A plain Python function can be a state too. It receives the shared context, and the keys it returns, apart from result, are merged back into that context for later states.

How do you build adaptive orchestration with a manager agent?

For adaptive work, pass specialist agents in a manager agent's tools list. The manager reads each specialist's description, decides whom to call and with what task, and assembles the answer.

from dynamiq.nodes.types import Behavior, InferenceMode

research_analyst = Agent(
    name="Research analyst",
    description="Finds recent, reputable public sources on a topic and returns cited highlights.",
    role="Find recent, reputable sources on the topic you are given and return cited highlights.",
    llm=llm,
    tools=[search],
    inference_mode=InferenceMode.XML,
    max_loops=6,
    behaviour_on_max_loops=Behavior.RETURN,
)

brief_writer = Agent(
    name="Brief writer",
    description="Turns research highlights into a short brief for a named audience.",
    role="Turn research highlights into a concise brief. Keep every citation.",
    llm=llm,
    inference_mode=InferenceMode.XML,
    max_loops=4,
    behaviour_on_max_loops=Behavior.RETURN,
)

manager = Agent(
    name="Manager",
    role=(
        "Plan the work, delegate research and writing to your sub-agents and check their output. "
        "Call sub-agents with {'input': '<task>'} payloads and assemble the final brief."
    ),
    llm=llm,
    tools=[research_analyst, brief_writer],
    inference_mode=InferenceMode.XML,
    parallel_tool_calls_enabled=True,
    max_loops=10,
    behaviour_on_max_loops=Behavior.RETURN,
)

workflow = Workflow(flow=Flow(nodes=[manager]))
result = workflow.run(
    input_data={"input": "Brief the risk committee on this month's regulatory news about AI in EU banking."}
)
print(result.output[manager.id]["output"]["content"])

parallel_tool_calls_enabled=True lets the manager fan out independent subtasks, such as researching two regulators at once. behaviour_on_max_loops=Behavior.RETURN makes an agent return its best answer instead of raising an error when it hits its loop limit.

The orchestrators documentation covers the full API, and the SDK repository includes complete graph examples, from a code assistant to a customer service concierge.

How do you see what the orchestrator did?

Multi-agent runs are only as trustworthy as your ability to replay them. Every run on the Dynamiq platform is traced: each manager decision, agent step, tool call and model call, with inputs, outputs, cost and latency. SDK workflows can send the same traces to the platform with a callback handler.

On top of the traces, an AI agent reviews production runs and surfaces failures, regressions and other issues for your team to check. See observability for how that works.

Can you build these patterns without code?

Yes. Agent Builder offers the same building blocks on a visual canvas, including a Graph Orchestrator and agents that call other agents. The canvas and the SDK run on the same engine, so a team can start in one and continue in the other.

In regulated workflows, pair either pattern with approvals: an approval pauses any tool step for a person, who can edit its fields before it runs. Our guide to multi-agent systems covers the design trade-offs in more depth.

FAQ

What is agent orchestration?

Agent orchestration is the coordination layer of a multi-agent system. It decides which agent handles each step, passes context between them, combines their results and enforces limits, such as how many steps a run may take.

What is the difference between linear and adaptive orchestration?

In linear orchestration, you define the order of the steps before the run, and every run follows it. In adaptive orchestration, a manager agent decides at run time which specialist to call next, so the path can change from run to run.

What happened to LinearOrchestrator and AdaptiveOrchestrator in Dynamiq?

The current SDK replaces them with two more general building blocks. Linear and branching flows use GraphOrchestrator, and adaptive delegation uses an Agent that lists other agents in its tools. The concepts in this guide carry over; only the class names changed.

Can you combine linear and adaptive orchestration?

Yes, and it is often the best design. Use a graph for the outer process so the order of steps is fixed and auditable, and put an adaptive manager agent inside a single state where the work is open-ended, such as research.

How do you keep a multi-agent system auditable?

Trace every run, keep the outer process as a defined graph, route high-risk cases to a person with a conditional edge or an approval, and turn failed runs into evaluation cases so the same mistake is caught next time.

Put this into practice.

See an agent built for your workflow, running in your environment, with our engineers.