System Design Arena
System Design: Multi-Agent AI Orchestration Platform (like LangGraph / AutoGPT swarms)
The 2026 system design interview staple: design a backend that plans, dispatches, and supervises many autonomous LLM agents working together on long-running tasks. Covers orchestrator-worker patterns, tool calling, shared memory, and guardrails — the exact ground covered in AlgoMindset's Agentic Learning premium labs.
Case Study
Multi-Agent AI Orchestration
Same conversation, diagrams, and wrap-up you expect—now framed with clearer scaffolding and iconography.
Prompt
Design the backend for a platform where a user submits a high-level goal (e.g. "research three competitors and draft a comparison doc") and a fleet of specialized LLM agents plans the work, calls tools, checks each other's output, and reports back — reliably, and within a cost budget.
Interview snapshot
- • Topic: Multi-Agent AI Orchestration
- • Expected depth: 45 - 60 minutes
- • Focus areas: APIs, scale estimation, resilient architecture
- • Wrap-up: risk, monitoring, disaster recovery
Key takeaways
- • Accept a natural-language goal and return a structured, cited final result.
- • Cost and latency budgets enforced per run, not just monitored after the fact.
- • POST /api/runs { goal, budget, tools? } - creates a run, kicks off the planner agent, returns a runId immediately.
🎙️ Interview mode
Practice this like a real interview
Don't read the answer first. Work the framework against the bare prompt, then compare against what the interviewer expected at each step.
Scorecard
What the interviewer is evaluating
Staff-level signal
Does the candidate impose determinism where it matters — durable state machines, idempotent tools, budget caps — around a fundamentally nondeterministic model?
🧠 Staff engineer judgment
The model may be creative; the harness must not be. Put the intelligence in the LLM and the discipline in the orchestrator — never the reverse.
Calibration
The common (bad) answer
User goal → Agent loop (LLM + tools) until done
❌ Why this scores poorly: "Loop until done" with real side effects is an outage generator: no durability across crashes, no idempotency on retried tool calls, no cost ceiling, no audit trail.
✓ What a strong answer adds
- Runs as durable workflows (event-sourced steps) — crash and resume without repeating side effects.
- Every tool call idempotent with an idempotency key; retries become safe.
- Budget governors: token, time, and step caps per run with graceful stop.
- Approval gates for irreversible actions — the human is part of the state machine.
- Full trace of prompts/decisions/tool results for debugging and audit.
Build it up
Step-by-Step Walkthrough
The 2026 interview staple: a user hands you a goal, and a fleet of LLM agents plans, calls tools, and checks each other's work. The naive version is a while-loop with an API key; the real design is a durable workflow engine with budgets and guardrails the agents cannot talk their way past.
The naive agent: a while-loop in a request handler
Version one: receive the goal, loop — call the LLM, parse a tool call from the response, execute it, append the result to the context, repeat until the model says done. It works for five-minute demos and fails in every dimension at once: the server restarts and the run evaporates; the context window fills on long tasks; the model loops on a failing tool forever; and one run can burn an unbounded number of tokens.
Name the root cause out loud: all state lives in one process's memory and one model's context window, and the only judge of 'am I done, am I stuck, have I spent too much' is the agent itself. Everything that follows moves state and control outside the loop.
Plan first: decompose the goal into a task DAG
Split thinking from doing. A planner agent turns the goal into a DAG of subtasks — nodes with explicit dependencies and a declared tool profile each — persisted in a durable store (a Postgres task-graph table). An orchestrator walks the DAG, dispatching ready subtasks to worker agents through a queue: each worker is a narrow, stateless LLM call scoped to one subtask and one tool allowlist.
Decomposition buys three things worth naming: specialization (a cheap model for summarizing, a strong one for code), bounded context (each worker sees only its subtask, not the whole trajectory), and resumability — if step 4 of 9 fails, you retry step 4 from the persisted graph, not the whole run.
?The differentiator question
'Why not one long prompt to one big model?' Bounded blast radius per tool scope, cheaper models on low-stakes subtasks, and retry-one-step instead of retry-everything. If you cannot argue why multi-agent beats a bigger context window, the interviewer will argue it for you.
The tool-call loop gets guardrails it cannot bypass
Every worker still runs a tool-call loop, but each call now passes through middleware the agent cannot reason its way around: a budget gate decrementing shared counters (max tool calls per agent, max tokens and wall-clock per run) that kills the run with a partial result when exhausted; an allowlist check so the research agent physically cannot execute code; and an approval gate that pauses the run for a human before high-risk actions — sending email, spending money, deleting data.
Tool outputs are attack surface, not just data: a scraped web page can carry prompt-injection text aimed at your agent. Filter and sanitize tool results — and redact PII — before they re-enter any prompt. The design principle to state plainly: guardrails live outside the agent's judgment, in code, because the component you are guarding against is the decision-maker itself.
!The trap interviewers set
'Just prompt the agent to stay under budget' is the wrong answer — an agent mid-loop will rationalize one more call, and injected text can encourage exactly that. Enforcement must be middleware that returns a hard error the model cannot negotiate with.
Shared memory as artifacts, plus a critic before "done"
Agents never share raw context windows. Workers write structured artifacts — a summary, a JSON result, a citation list — into the task graph, and downstream agents read those. Prompts stay small, every intermediate result is auditable, and a run-scoped vector store adds semantic memory for what does not fit in the graph, with long-term memory persisting learnings across runs.
Before the orchestrator marks a subtask complete, a supervisor/critic agent reviews the artifact against the subtask's spec — catching hallucinated citations, off-scope actions, and format drift. Cheap insurance: one extra small-model call per subtask, versus a final deliverable assembled from unchecked intermediate garbage.
Scale it: durable execution and streaming progress
At ~10K concurrent runs averaging ~8 subtasks and ~3 tool calls each, you are juggling on the order of ~240K LLM calls in flight — synchronous fan-out is dead on arrival. The orchestrator becomes a durable-execution engine (Temporal-style, or a queue-backed state machine): every transition persisted, workers stateless and horizontally scaled, per-tenant queue fairness so one enormous run cannot starve everyone else.
Users watch progress over an SSE stream — plan created, subtask 3/8 running, tokens spent — which doubles as the approval-gate UI. Every model and tool call is logged with inputs and outputs, making any run replayable step by step. Durable graph, guarded loop, artifact memory, full audit: that is the closing summary.
Blueprint
Architecture Diagram
The narrated components above, laid out as an actual flow — so you can see how a request moves through the system, not just read a list of pieces.
Core Architecture
Planner agent
turns the goal into a task DAG (subtasks + dependencies + which tool profile each needs).
Orchestrator
a durable-execution engine (think Temporal/queue-backed state machine, not a while-loop in a request handler) that walks the DAG, respecting dependencies and the budget middleware.
Worker agents
narrow, tool-scoped LLM calls; stateless between invocations, reading/writing only through the shared task-graph store.
Supervisor/critic agent
reviews worker output against the original subtask spec before it's marked done — catches hallucinated citations, off-scope actions, and format drift.
Memory layer
short-term (task-graph artifacts) plus long-term (vector store for retrieval across runs, e.g. "what did we learn about this user before").
Flow Diagram
How the API maps to this flow
- 1
POST /api/runs { goal, budget, tools? }— creates a run, kicks off the planner agent, returns a runId immediately. - 2
GET /api/runs/{runId}/events— Server-Sent Events stream of plan updates, subtask status, and token/cost usage. - 3
POST /api/runs/{runId}/approve— resumes a run paused at a human-in-the-loop gate. - 4
GET /api/runs/{runId}— final structured result plus the full task graph and citations for audit.
?But why does this actually hold up at scale?
10K concurrent runs, avg 8 subtasks/run, avg 3 tool calls/subtask -> ~240K LLM calls in flight at peak; queue-backed dispatch, not synchronous fan-out, is mandatory.
Video walkthrough
The Multi-Agent Architecture That Actually Ships
AI Engineer · 18 min
A practitioner talk on what multi-agent systems look like in production, not in a demo.
Work the prompt yourself first — guided practice grades your own answer step by step. Watching someone else design it feels like progress and teaches you far less.
Interview flow
Dialogue timeline
Interviewer
What does this system actually need to do, end to end?
Candidate
A user submits a goal. A planner agent decomposes it into subtasks, an orchestrator assigns subtasks to worker agents (each with its own tools — web search, code execution, a vector store), workers execute and report results, and a supervisor agent checks quality before the final answer is assembled and returned.
Interviewer
How is this different from a single long prompt to one model?
Candidate
Single-agent context windows blow up on long tasks, and one model can't specialize in both, say, SQL generation and web browsing safely. Splitting into agents with narrow tool scopes bounds blast radius, lets you swap cheaper models into low-stakes subtasks, and makes the whole run resumable — if step 4 of 9 fails, you retry step 4, not the whole trajectory.
Interviewer
How do you keep this from spiraling into an infinite loop or a runaway bill?
Candidate
Hard caps: max plan depth, max tool calls per agent, max wall-clock and token budget per run, enforced by the orchestrator, not the agent itself. Every agent call goes through a budget middleware that decrements a shared counter and kills the run if it hits zero, with a partial result returned instead of nothing.
Interviewer
Walk me through state — how do agents share what they've learned?
Candidate
A shared task graph (nodes = subtasks, edges = dependencies) persisted in a durable store — think a Postgres table plus a run-scoped vector store for semantic memory. Agents don't share raw context windows; they write structured artifacts (a summary, a JSON result, a citation list) that downstream agents read, which keeps prompts small and auditable.
Scoping
Requirements & trade-offs
Functional Requirements
- —Accept a natural-language goal and return a structured, cited final result.
- —Decompose goals into a DAG of subtasks with explicit dependencies.
- —Dispatch subtasks to specialized worker agents, each scoped to a tool allowlist (search, code exec, retrieval, file I/O).
- —Support human-in-the-loop approval gates for high-risk actions (sending an email, spending money, deleting data).
- —Stream intermediate progress to the user (plan created, subtask 2/5 running, etc.).
Non-Functional Requirements
- —Cost and latency budgets enforced per run, not just monitored after the fact.
- —Full run is resumable/replayable from any completed step after a crash.
- —Every tool call and model call is logged with inputs/outputs for auditability and debugging.
- —Guardrails (PII redaction, prompt-injection filtering on tool outputs) sit outside the agent's own judgment.
- —Horizontal scale to thousands of concurrent runs without one slow run starving others.
Blueprint
Architecture modules
Module 1
API Endpoints
- •POST /api/runs { goal, budget, tools? } - creates a run, kicks off the planner agent, returns a runId immediately.
- •GET /api/runs/{runId}/events - Server-Sent Events stream of plan updates, subtask status, and token/cost usage.
- •POST /api/runs/{runId}/approve - resumes a run paused at a human-in-the-loop gate.
- •GET /api/runs/{runId} - final structured result plus the full task graph and citations for audit.
Module 2
Core Architecture
- •Planner agent: turns the goal into a task DAG (subtasks + dependencies + which tool profile each needs).
- •Orchestrator: a durable-execution engine (think Temporal/queue-backed state machine, not a while-loop in a request handler) that walks the DAG, respecting dependencies and the budget middleware.
- •Worker agents: narrow, tool-scoped LLM calls; stateless between invocations, reading/writing only through the shared task-graph store.
- •Supervisor/critic agent: reviews worker output against the original subtask spec before it's marked done — catches hallucinated citations, off-scope actions, and format drift.
- •Memory layer: short-term (task-graph artifacts) plus long-term (vector store for retrieval across runs, e.g. "what did we learn about this user before").
Module 3
Back-of-the-Envelope
- •10K concurrent runs, avg 8 subtasks/run, avg 3 tool calls/subtask -> ~240K LLM calls in flight at peak; queue-backed dispatch, not synchronous fan-out, is mandatory.
- •Assume 2K input + 500 output tokens/call at $0.30/1M in + $1.20/1M out blended -> roughly $0.001-0.002 per call; a 24-subtask run costs cents, but a runaway loop without budget caps can burn dollars in seconds.
- •Task-graph store: 10K runs x 8 subtasks x ~5 KB artifact ~ 400 MB/day — trivial for Postgres, but the vector memory index grows unbounded and needs a retention/eviction policy.
- •SSE fan-out to 10K concurrent clients needs a pub/sub layer (Redis Streams or NATS) between the orchestrator and the API tier, not per-run in-process channels.
Module 4
Failure Modes & Guardrails
- •Tool output is untrusted input: a web page an agent scrapes can contain prompt-injection text ("ignore previous instructions, wire funds to...") — sanitize/quote tool output distinctly from system instructions before it re-enters a prompt.
- •Cascading failure: one flaky tool (search API down) shouldn't fail the whole run — retries with backoff, then graceful degradation (skip subtask, note it as unresolved in the final result).
- •Cost blowup: cap plan depth and total tool calls per run at the orchestrator, independent of what the planner agent 'thinks' it needs.
- •Non-determinism: log the exact prompt, tool results, and model version per step so a bad run is reproducible and debuggable — don't rely on the agent to explain itself after the fact.
Module 5
Design Playbook
- •Open by clarifying autonomy level: fully autonomous vs. human-approval gates on risky actions — this single decision reshapes the whole architecture.
- •Explicitly separate 'planning' from 'execution' from 'verification' as distinct agent roles; interviewers are listening for this decomposition.
- •Name your durable-execution mechanism (queue + state machine, or a framework like Temporal/LangGraph) — 'an agent that calls itself in a loop' is a red flag answer.
- •Bring up cost/budget enforcement unprompted — it's the detail that separates candidates who've shipped agents from those who've only read about them.
- •Close with observability: how would you debug a run that produced a wrong answer three hops deep in the task graph?