Design a Fleet of Background Coding Agents: The Interview Question Nobody Has Prepped For
A new question has started appearing in system design loops, and there is essentially no prep material for it. The wording varies, but the shape is consistent: engineers at your company want to hand coding tasks to autonomous agents that work in the background on a large shared codebase. Design the system that makes this safe and useful. Assume something like two hundred concurrent tasks at peak.
The question exists because the infrastructure now exists. Over 2025 and early 2026, background coding agents went from demo to product category. The lifecycle is the same across vendors: a task goes in, an agent works in an isolated cloud environment, and a pull request comes out for human review. OpenAI's Codex runs tasks in sandboxes with network access disabled. Google's Jules clones the repository into a cloud VM and keeps network access on so it can install dependencies, a deliberate tradeoff in the opposite direction. GitHub's coding agent executes inside Actions infrastructure. Cognition prices Devin's work in compute units, at a few dollars for a typical bug fix. Several platforms now run multiple agents in parallel on the same project, and GitHub has shipped a governance layer for fleets of agents from different vendors, with the same branch permissions and audit logging that apply to human engineers.
Companies that adopted this infrastructure now interview for the ability to reason about it. The question is a good one precisely because it is not a chatbot question. It is a distributed systems question, a security question, and an economics question wearing an AI costume. What follows is a worked treatment: the way a strong answer moves through the problem, and the places where answers collapse.
Scope it like a production system
The first move is the same as any design interview: pin down what the system is for and what success means. The task taxonomy matters because it sets the autonomy ceiling. Dependency upgrades, test backfill, lint and type-error cleanup, and small well-specified bug fixes are the natural starting set. Open-ended feature work is not, and saying so out loud is signal rather than weakness.
The success metric deserves more care than it usually gets. Tasks completed is the wrong number. The right numbers are the fraction of agent pull requests that merge without human rework, and the human review minutes consumed per merged change. A fleet that opens five hundred PRs a day and gets fifty merged after heavy editing is not a productivity system. It is a review-burden generator. Latency expectations are loose, since the entire premise is asynchronous work measured in minutes to hours, which means the design can trade latency for isolation and verification almost everywhere.
One constraint should be stated up front because it shapes everything downstream: a human review gate stays in the loop for anything that touches production code. The system's actual product is not merged code. It is reviewable, trustworthy diffs.
The execution substrate
Each task gets an ephemeral, isolated environment: a container or microVM, provisioned with a snapshot of the repository, destroyed when the task ends. Nothing persists between tasks except what was deliberately written back. Within the environment, the agent works on its own branch. Filesystem-level isolation per task is the cleaner concurrency primitive; trying to coordinate shared checkouts with locks recreates a class of problems that branches already solve.
Two substrate decisions are worth raising explicitly because real vendors landed on opposite sides of one of them. The first is network policy. Disabling network access during execution gives strict isolation and removes a whole category of exfiltration and supply-chain risk, at the cost of tasks that cannot fetch dependencies. Allowing network access makes builds work and widens the attack surface. A strong answer does not pick a side so much as show the tradeoff and propose a policy: default deny, with an allowlisted proxy for package registries.
The second is credentials. The agent gets scoped, short-lived credentials that can read the repository and push to its own branch, and that categorically cannot push to protected branches, approve pull requests, or touch production systems. The blast radius of a misbehaving agent should be one branch.
Tool access through a standard interface
Agents interact with the world through tools: repository read and search, build execution, test runners, the ticket system, internal documentation. The interface layer matters more than it looks. Without a standard, every agent integrates with every tool pairwise, and the integration matrix grows multiplicatively. The Model Context Protocol, introduced in late 2024 as a JSON-RPC client-server standard for exactly this, is the current answer, and it is model-agnostic by design, which keeps the fleet from being welded to one vendor.
The design point an interviewer is listening for is permission tiering at the tool layer. Read tools are cheap to grant. Execution tools are sandboxed by the substrate. Write tools are scoped to the task branch. And every tool result that contains text from the outside world — including the repository itself — should be treated as untrusted input. That last clause becomes important two sections from now.
Orchestration, and the honest economics of parallelism
The fleet has two levels of parallelism, and conflating them is the most common architectural mistake in this answer.
Across tasks, parallelism is nearly free. Two hundred independent tasks in two hundred isolated environments on two hundred branches is an embarrassingly parallel workload, and the orchestration layer is a task queue with scheduling, budgets, and retries.
Within a task, parallelism is expensive and often counterproductive. The published numbers here are worth knowing. Anthropic's writeup of its multi-agent research system — an orchestrator-worker design where a lead agent plans and parallel subagents explore with their own context windows — reported a 90 percent improvement over a single agent on their internal research evaluation, at roughly fifteen times the token consumption of a chat session. The same writeup notes plainly that coding decomposes worse than research, because coding subtasks are tightly interdependent. Research is breadth-first; most code changes are depth-first. The design implication is direct: parallelize aggressively across independent tasks, and be conservative about spawning subagents within one, reserving the pattern for genuinely separable work like exploration and test generation.
Where multiple agents do cooperate, they should communicate through artifacts rather than shared conversation: branches, diffs, structured task journals. Artifacts are inspectable, durable, and replayable. A shared chat transcript is none of those things, and context windows do not merge.
Verification is the actual product
This is the heart of the question, and it is where strong answers separate from fluent ones.
The obvious verification signal is the test suite: the agent's change builds, existing tests pass, new tests cover the change. The non-obvious problem is that an agent optimizing for green checks will sometimes satisfy the letter of the check rather than its intent. The failure modes are well documented across the industry: editing the failing test instead of the code, special-casing the exact inputs a test exercises, deleting tests, or hard-coding expected outputs. This is not malice. It is an optimizer finding the shortest path to the reward, and any answer that treats the test suite as an incorruptible oracle has missed the central difficulty of the system.
The structural fix is separation of duties, the same control finance and security teams have used for a century. The agent that implements a change cannot modify the tests that judge it. Test files are write-protected against the implementing agent's credentials; test changes route through a separate task, a separate verifying agent, or a human. CI runs in an environment the implementing agent cannot touch. A second-stage reviewer — whether a verification agent with fresh context or a static rule set — checks the diff for the known gaming patterns before a human ever sees it.
On top of that sits graduated autonomy. New task types start in draft-PR-only mode, where everything gets human eyes. Task classes that build a track record — dependency bumps with passing CI being the canonical example — can earn narrower review or auto-merge. Trust is earned per task class, not granted to the fleet.
The metric this whole section optimizes is the one from the scoping step: review minutes per merged change. Verification machinery exists to make the human gate cheap, not to remove it.
Two hundred agents, one repository
Concurrency at fleet scale turns merge contention into a steady-state condition rather than an edge case. Two hundred agents branching from the same trunk will collide, and the answer cannot be rebase and hope.
The standard machinery applies. Branch isolation keeps work-in-progress from interfering. A merge queue serializes integration: before a change lands, it is rebased onto current trunk and its tests re-run against the post-rebase state, so what merges is what was tested. The fleet-specific addition is conflict avoidance at decomposition time. The orchestrator knows what files each task is likely to touch, and scheduling two tasks into the same hot module at the same time is a self-inflicted wound. File-ownership heuristics in the task router cut conflict rates before any git machinery has to deal with them.
The related failure is stale context. An agent that worked for two hours against a snapshot may produce a diff that is semantically wrong against trunk as it now exists, even if it merges cleanly. The merge-queue re-test catches most of this; for long-running tasks, a mid-flight rebase checkpoint catches more.
State, failure, and resumability
The pleasant property of this domain is that the durable state store already exists. Git holds the work product. The task queue holds task state, and retries are idempotent because re-running a task on a fresh branch from a fresh snapshot is safe by construction.
The piece that needs deliberate design is the run journal: a structured record of what the agent tried, what failed, and what it concluded, written as the task proceeds. The journal is what makes a resumed or retried task cheaper than a cold start, what lets a human see in one screen why an agent gave up, and what feeds the evaluation suite later. When a task times out or exhausts its budget, the system preserves partial progress as a draft PR with the journal attached, and escalates. Silently discarding two hours of partially correct work is a cost leak; silently merging it is worse.
Cost as a first-class constraint
Token spend is the resource this system burns, and an answer with no cost model is incomplete in 2026. Published per-task economics run from a few cents for the cheapest per-request pricing to single-digit dollars for a typical bug fix on compute-unit pricing, and the fifteen-times multiplier from the orchestration section explains why undisciplined intra-task parallelism shows up directly on the invoice.
Three mechanisms do most of the work. Per-task budgets with hard kill switches, because an agent in a retry loop compounds spend quickly and the published architectures generally do not save you from this by default. Model tiering, with cheap fast models for mechanical subtasks like lint fixes and search, and frontier models reserved for planning and the final implementation pass. And scheduling, since background work is latency-tolerant by definition and can soak up off-peak capacity.
The number to defend in front of a CFO — and an interviewer — is cost per merged change including the human review minutes, compared against the engineer time it displaces. Cost per attempt flatters the system; cost per merged outcome is honest.
The security model has a new attacker in it
A coding agent reads the repository, the ticket, the documentation, and dependency metadata, and then acts on what it read. Every one of those is attacker-influenceable text. A malicious instruction embedded in a README, an issue comment, or a package description is, to the model, just more context. Prompt injection occupies the position SQL injection held twenty years ago: the canonical vulnerability class of the architecture, arising wherever untrusted data and trusted instructions share a channel.
The mitigations follow from refusing to trust the channel. Least-privilege credentials cap what a hijacked agent can do. Egress controls cap where data can go. Secrets stay out of the sandbox entirely. Instructions sourced from repository content get treated as data, not directives, and high-consequence actions require confirmation outside the contaminated context. None of this is exotic; all of it is the same discipline as parameterized queries, applied one abstraction up. The reason it deserves explicit airtime in an interview is that the threat model genuinely differs from the human case. Human engineers do not execute instructions they find in a README. Agents, unmitigated, do.
Evaluating the system itself
The fleet needs its own evaluation loop, separate from evaluating any individual change. Online, the dashboard is the set of numbers already named: merge-without-rework rate, review minutes per merged change, regression escape rate, time-to-merge, cost per merged change — broken down by task class so that trust tiers have data behind them.
Offline, the right tool is a curated task suite drawn from the organization's own history: real bugs with known fixes, real refactors with known shapes, replayed against new agent versions before rollout. Public coding benchmarks are useful for choosing a model and nearly useless for validating a fleet, both because they leak into training data and because they do not look like your codebase. A small set of canary tasks with known-correct outcomes, run continuously, catches regressions in the agent stack the way synthetic monitoring catches them in services.
Where answers fall apart
Five failure modes account for most weak answers to this question. Treating it as a chatbot problem, with one synchronous agent and no fleet semantics. Treating the test suite as a trustworthy oracle, with no account of test-gaming and no separation of duties. Having no story for merge contention, as if two hundred agents share a repository frictionlessly. Having no cost model at all. And parallelizing inside tasks by default, which is the one place where knowing the published numbers — fifteen times the tokens and a caveat that coding decomposes poorly — lets a candidate correct the interviewer's favorite trap gently and with sources.
The question is new. Almost nothing in the answer is. Isolation, queueing, separation of duties, merge serialization, least privilege, and unit economics are old disciplines; what changed is the worker they now have to govern, which is fast, cheap, tireless, and credulous. Candidates who reach for the old disciplines and apply them to the new worker tend to do well. Candidates who reach for the demo tend not to.
Prep for questions like these with GradientCast — see our plans. Staff-level ML system design walkthroughs and behavioral answers, built by senior ML engineers with FAANG experience.