Skip to content
DERKONLINE

Orchestrate Multiple Agents Without Losing Control of the Flow

Supervisor, handoff, and shared-state patterns plus inspectable state and gated destructive actions keep multi-agent systems debuggable.

Derrick S. K. Siawor7 min read

The demo always works. One agent calls another, which calls a third, and out comes a confident answer. Then it ships, and a week later a customer reports that the system gave a refund it should not have, and you open the logs to find out why. What you find is a wall of model output, a chain of handoffs with no clear record of who decided what, and no way to reconstruct the path from input to that wrong refund. The system was never debuggable. It just looked fine until it did not.

Multi-agent systems fail in a specific way: not loudly, but opaquely. The individual agents work. The orchestration that connects them is where control quietly leaks away. If you cannot answer "which agent made this decision, with what context, and why," you do not have a system, you have a black box that happens to produce text. The patterns below are how you keep the box transparent.

Three patterns, three different control models

There is no single right architecture. There are three established patterns, each trading control for flexibility differently, and the mistake is picking one by default instead of by fit.

Supervisor (orchestrator-worker)

A single supervisor agent owns the global state and dispatches sub-tasks to specialist workers. It decomposes the user's request into steps, sends each step to the right specialist, collects results, and updates its plan as it goes. The workers do not talk to each other; everything routes through the supervisor.

Supervisor agent pattern: dispatch to workers, persist inspectable state, gate destructive actions for approval

This is the most debuggable pattern, and it is the one to reach for first. Because every decision and every handoff passes through one coordinator, that coordinator is also your single source of truth for what happened. You inspect the supervisor's state and you have the whole resolution chain. The cost is that the supervisor is a bottleneck and a single point of failure, and its planning prompt becomes complex as the number of specialists grows.

Handoff (decentralized)

In the handoff pattern there is no central coordinator. Each agent assesses the current task and decides whether to handle it itself or transfer control, along with the accumulated context, to a more appropriate specialist. Control moves one way, like a baton in a relay. A triage agent hands off to a billing agent, which hands off to a refunds agent.

This scales better than a supervisor because no single agent has to understand the whole problem, and it maps naturally onto customer-support-style flows where the right specialist changes as the conversation develops. The danger is exactly the opacity from the opening of this post. With no central record, a chain of handoffs can become impossible to trace unless you deliberately log each transfer with the context that moved. Decentralized control is decentralized accountability unless you build the audit trail in.

Shared state (graph or swarm)

Multiple agents read from and write to a common, persistent state object that carries context across every step and every agent boundary. The state is passed to all agents through an invocation parameter so they share context and configuration without that context having to be stuffed into the LLM prompt itself. This keeps the model's context window clean while still letting agents coordinate through a structure they all see.

This is the most flexible and the most powerful, and also the easiest to turn into a mess. Shared mutable state across concurrent agents reintroduces every classic concurrency problem: lost updates, race conditions, two agents writing the same field. It also makes keeping the agent's context window managed harder, since every agent's writes compete for the same finite budget. If you go this route, the state object needs the same discipline you would give any shared data structure, with clear ownership of who writes what and guards against concurrent clobbering. The same care that keeps agent tool calls idempotent before they double-charge a customer applies here to every write.

The non-negotiable: state you can inspect and replay

Whichever pattern you pick, the thing that separates a production system from a demo is persistent, inspectable state. In real deployments, that means backing the conversation state in a real store, Redis or PostgreSQL, indexed by a conversation id. This is not premature infrastructure. It buys you three concrete capabilities:

  • Resumability. An agent run that gets interrupted, a disconnection, a timeout, a crash, can pick up from the last committed state instead of starting over.
  • Audit. Every privileged decision is recorded against the conversation id, so when the refund goes out wrong, you can pull the exact chain that produced it. This is the agent equivalent of audit logs that actually help after a breach.
  • Inspection after the fact. A supervisor or an engineer can read the full resolution chain and see which agent decided what, with what inputs, the kind of visibility that traces and spans give you when an agent goes off the rails. This is the capability whose absence makes the opening scenario unsolvable.

If your agents pass context only through the prompt and keep no durable record, you have built a system that cannot explain itself. The first time it does something expensive and wrong, that gap is what turns a ten-minute investigation into a day of guessing.

Treat agent decisions like privileged operations

The hardest lesson in multi-agent design is that an agent confidently deciding to do something is not the same as that thing being safe to do. The model will sound certain about an action that should never run without a human in the loop. The architecture, not the prompt, has to enforce the boundary.

The pattern that works: classify every action an agent can take by its blast radius, and gate the dangerous ones. Read-only and reversible actions run freely. Irreversible or destructive actions, deleting data, moving money, running a command that could take a server down, require an explicit approval step before they execute. The agent proposes; a guardrail in the orchestration decides whether it runs or pauses for sign-off. This is the same boundary that lets you hand your deploy pipeline to an agent and still sleep at night.

This is exactly the principle behind LadenX, the AI site-reliability engineer we built. It classifies every command it might run on a server and refuses the destructive ones without human sign-off, the same way you give autonomous fixes guardrails before they touch production. The intelligence lives in the diagnosis; the safety lives in the refusal. An agent that can run rm -rf because it decided that was the fix is not autonomous, it is a liability waiting for the wrong context. The classification-and-gate pattern is what makes autonomy survivable, and it also keeps tool-using agents safe against prompt injection from untrusted content that tries to trick the model into proposing the destructive action in the first place.

Frameworks help, but the patterns are yours

The tooling has matured fast. OpenAI shipped an Agents SDK, Google an Agent Development Kit, and Anthropic the Claude Agent SDK, and the orchestration primitives vary: OpenAI's handoffs are the cleanest typed delegation, Google's ADK gives you an explicit routing graph, and the Claude SDK leaves agent-to-agent handoffs more to you. The newer frameworks bake in production telemetry so the handoff chain is observable by default rather than something you reverse-engineer from logs.

Use them, but do not let the framework choose your architecture. The framework gives you handoffs and shared state as primitives; deciding whether your problem wants a supervisor's central control, a handoff chain's flexibility, or a shared-state graph's power is a design decision you own. And no framework absolves you of the two rules that actually keep the system honest: persist inspectable state, and gate destructive actions behind a guardrail the model cannot talk its way past.

The test for whether you got it right

Before you ship a multi-agent system, run one exercise. Pick a decision the system might make that would be expensive to get wrong. Then ask: can I, from the logs and the stored state, reconstruct exactly which agent made it, what context it had, and why it chose that action? If the answer is yes, you have a debuggable system. If the answer is "somewhere in the model output," you have a black box, and the first costly mistake will prove it.

Multi-agent orchestration is not about chaining more agents together. It is about keeping control and accountability intact as the chain grows. Build for the moment something goes wrong, because in production, eventually, it will. This is the discipline we bring to every AI system we build, and it is the difference between an impressive demo and a system you can actually run.