Queues, Graphs, or Event Streams: Picking the Right Agent Orchestration Topology
Compare queue, graph, and event-stream agent orchestration topologies on reliability, scaling, observability, and cost—plus a decision framework and hybrid patterns.
Most teams pick an agent orchestration framework before they define their topology. That's backward.
The framework decision feels concrete—LangGraph versus Temporal versus a queue library versus a managed workflow service—so it gets made first. The topology decision feels abstract, so it gets deferred. Six months later, the team discovers that their fan-out workload fights a DAG engine, that their multi-step reasoning agent has no reliable way to pause for human approval, or that replaying a failed run means reconstructing state from scattered logs because nothing in the stack was designed to record it.
Topology is the architecture bet underneath the framework. It determines how work moves, where state lives, how failures propagate, and what you can actually see when something goes wrong. Topology and framework are more coupled than vendors admit—your topology is usually encoded in the framework's data model, whether that's a checkpoint store, an event history, or a consumer offset. That coupling is exactly why getting topology right first matters: changing it later means migrating both.
This article compares three agent orchestration topologies—queues, graphs, and event streams—on the dimensions that matter in production: reliability, scaling, observability, and cost. It closes with a decision framework and the hybrid patterns most mature teams end up running.
Why Agent Orchestration Topology Is the First Decision
An agent orchestration topology is the structure that governs how tasks are dispatched, sequenced, and coordinated across agents, tools, and humans. Get it wrong and every downstream choice gets harder.
The three topologies at a glance
- Queue: A producer enqueues work items; independent workers pull and process them. Coordination is implicit in the queue.
- Graph: Agents and tools are nodes in a directed acyclic graph (or a controlled cyclic graph); edges encode dependencies and branching. Coordination is explicit in the structure.
- Event stream: An append-only log records every event; consumers react to events as they arrive. Coordination is implicit in the event contract.
Each is a legitimate architecture. None is universally correct.
What "topology" actually constrains
Before you compare libraries, understand what the topology locks in:
- Reliability: Which failure modes are native (retries, dead-lettering, replay) versus bolted on.
- Scaling: Whether you scale by adding workers, widening the graph, or adding consumer partitions.
- Observability: Whether you can reconstruct exactly what happened and why, after the fact.
- Cost: Where compute idles, where state accumulates, and how much operational surface you carry.
One clarification: "workflow engine" and "agent orchestration" overlap but aren't identical. A workflow engine executes a declared set of steps, possibly with branching and loops; agent orchestration must also accommodate a model choosing among those transitions at runtime. The constraint isn't determinism per se—Temporal handles non-deterministic LLM calls cleanly by wrapping them as activities. The constraint is that deterministic engines require you to declare the graph of possible transitions up front. A model selecting among declared branches is fine. A model inventing a new branch the engine doesn't know about is not. (See our breakdown of workflow engines vs. agent orchestration.)
The topology you choose is the set of failure modes you're signing up to operate. Choose it deliberately, not by accident of framework.
Queue-Based Orchestration: Work Distribution and Long-Running Agents
Queues are the oldest and most battle-tested pattern in distributed systems, and they map cleanly onto agent workloads that look like independent units of work.
How it works
A producer (an API handler, a scheduler, an upstream agent) writes a task to a queue. Worker processes pull tasks, execute them—often invoking an LLM or a tool—and acknowledge completion. If a worker fails or times out, the message becomes visible again and another worker retries it. After a configured number of attempts, the message routes to a dead-letter queue for inspection rather than looping forever.
This gives you retries, at-least-once delivery, and horizontal scaling with minimal custom code. Visibility timeouts, prefetch limits, and concurrency caps give you backpressure without building it yourself.
Where queues win
- Fan-out workloads. Summarize 10,000 documents, classify 50,000 tickets, enrich a million records. Add workers; throughput scales close to linearly until the broker or a downstream dependency becomes the bottleneck—and that ceiling assumes stateless workers.
- Long-running agents. A research agent that runs for 20 minutes shouldn't hold an HTTP connection. Queue it, isolate it on a worker, and let the worker's lifecycle manage it.
- Backpressure and isolation. A slow or expensive task type gets its own queue and its own worker pool, so it can't starve fast tasks.
- Burst tolerance. Queues absorb spikes; workers drain them at a sustainable rate.
Where queues break down
At-least-once means your workers must be idempotent. This is the failure mode that bites teams first. If a worker times out after calling an external tool—sending an email, writing a CRM record, charging a card—the retry will call it again. Every side-effecting tool call needs an idempotency key or a deduplication layer keyed on the task ID. Build that before you build the queue, not after the first double-charge.
Queues also have no native dependency modeling. If task C requires outputs from A and B, that relationship lives in your application code, not in the topology. You end up building a coordination layer: polling for completion, correlating IDs, or chaining queues.
State sprawl follows. Each worker holds partial state; the "current status" of a multi-step agent run is scattered across queue metadata, a database row, and logs. Ordering is also weak—most queues guarantee ordering only within a partition or a FIFO group, and parallel consumers break it further. (For mitigation tactics, see handling state sprawl in distributed agents.)
Graph-Based Orchestration: Explicit Dependencies and Deterministic Flow
Graphs make the structure of a multi-step agent visible. If your workload is a sequence of dependent reasoning steps, a graph is often the most honest representation.
How it works
Nodes represent agents, tools, or human approval steps. Edges represent transitions, and conditional edges encode branching—route to the retrieval node if the query needs context, otherwise go straight to synthesis. Execution walks the graph, and a checkpoint after each node gives you a resumable record of where the run is.
Where graphs win
- Dependent reasoning. Retrieval → critique → revise → synthesize is a graph, and modeling it as one makes the dependency explicit instead of implicit in code.
- Human-in-the-loop. A node can block on an approval step and resume from a checkpoint when the human responds. This is the pattern queues handle worst and graphs handle best.
- Auditable branching. Because transitions are declared, you can enumerate the paths a run could take and reason about coverage.
- Deterministic replay. With a checkpoint store, you can resume a failed run at the last good node instead of restarting it.
Where graphs break down
Cycles are where agent loops live—and where cost runs away. A graph engine that permits cycles needs an explicit termination condition: a max-iteration cap, a token budget, or a dedicated exit node. Without one, an agent that keeps deciding to "revise" will burn budget silently until someone notices the invoice.
Graphs assume you know the shape of the work. If the set of possible transitions isn't knowable at design time—because the agent's next step depends on open-ended reasoning—you'll either over-declare the graph (every possible transition, most unused) or fight the engine to add transitions dynamically. Neither is fun.
State lives in the checkpoint store, and that store becomes critical infrastructure. Losing it means losing the ability to resume, and the schema of what you checkpoint is now part of your API surface.
Event Stream-Based Orchestration: Append-Only Audit and Reactive Consumers
Event streams trade coordination for a durable record. If you need to know exactly what happened and react to it in multiple places, this is the topology that delivers.
How it works
Every meaningful action—a task submitted, an agent decision made, a tool result returned—is written to an append-only log partitioned by key. Consumers in consumer groups read the log at their own offset and react. Scaling means adding partitions and consumers, not adding workers to a shared queue.
Where event streams win
- Audit and replay. The log is the history. You can rewind a consumer to any offset and reprocess, or spin up a new consumer that reads the entire history to rebuild derived state.
- Multiple independent consumers. One consumer indexes for search, another triggers notifications, a third feeds a dashboard—all reading the same events without coordinating with each other.
- Ordering per key. Partitioning by run ID gives you strict ordering within a single agent run while allowing parallelism across runs.
Where event streams break down
You get a record of what happened, not a mechanism for "wait for A and B, then run C." Event streams are excellent at reacting and poor at coordinating. If your workload needs join semantics—fan-in from multiple upstream tasks before a downstream step—you'll build that on top, usually with a state store keyed by run ID. That's the same coordination layer queues force you to build.
Retention is the cost driver. Keeping the log long enough to replay a failed run from three days ago means paying for three days of retention across every partition. Tune retention to your actual replay window, not to a default.
Consumer rebalancing is an operational hazard. When a consumer joins or leaves a group, partitions reassign, and in-flight work may be reprocessed. Same idempotency requirement as queues, plus a rebalancing event you have to reason about.
Comparing the Three on Production Dimensions
| Dimension | Queue | Graph | Event stream |
|---|---|---|---|
| Native retries | Yes | Yes (per node) | No (consumer's job) |
| Dead-lettering | Yes | Partial (failed-node state) | No |
| Dependency modeling | No | Yes | No (build on top) |
| Human-in-the-loop | Bolted on | Native | Bolted on |
| Replay | Limited | Checkpoint resume | Full log replay |
| Scaling mechanism | Add workers | Widen graph / add nodes | Add partitions + consumers |
| Ordering | Per partition / FIFO group | Implicit in edges | Per key |
| Idempotency burden | High | Medium | High |
| Cost driver | Worker idle time | Checkpoint storage + loop cost | Log retention |
| Best observability story | Per-task traces | Per-run graph state | Full event history |
A Decision Framework
Ask three questions in order:
- Is the work independent units, or dependent steps, or reactions to events? Independent units → queue. Dependent steps → graph. Multiple consumers reacting to the same history → event stream.
- Does a human need to approve mid-run? If yes, weight toward graph. Queues and streams can do it, but you'll build the pause/resume machinery yourself.
- Do you need to replay history to rebuild derived state? If yes, weight toward event stream. If you only need to resume a failed run, a graph checkpoint gets you there more cheaply.
If the answers conflict—and they usually do—you're looking at a hybrid.
Hybrid Patterns Mature Teams Run
- Queue front, graph back. A queue absorbs and distributes incoming tasks; each worker runs a graph for the dependent reasoning inside a single task. This is the most common production pattern: queues for fan-out and isolation, graphs for the reasoning that needs structure.
- Graph front, event stream back. The graph orchestrates the run, and every node transition emits an event to a stream for audit, search indexing, and downstream reactions. The graph owns coordination; the stream owns the record.
- Event stream front, queue back. Events arrive on the stream, a router consumer decides which queue to enqueue work onto, and workers process from there. Useful when you have many event sources and want one ingestion point.
The pattern to avoid is running all three as peers with no clear ownership of coordination. Pick one topology to own coordination; let the others serve supporting roles.
The topology you choose is the set of failure modes you're signing up to operate. Pick the failure modes you can staff, instrument, and afford.