Skip to main content
← Applied / Agentic AI Engineer

The System Design Round

Both Anthropic and Sierra call this round system design, and it is the round that decides most offers: a hypothetical product asks for “an agent that does X,” and for 45–60 minutes you think out loud while the interviewer plays the stakeholder, adding constraints and pushing on where it breaks. Below is the framework, then three full walkthroughs, written the way the room actually sounds.

45–60 minutesHighest weight in the loopThe round that actually decides most offers

The framework, before the scenarios

Every version of this round follows the same underlying shape, no matter the product. The interviewer is grading the process, not just the destination — the same five moves work whether the product is a support bot, an internal tool, or a coding assistant.

  1. 1

    Scope what the agent can actually do before anything else

    What actions is it allowed to take, and which ones require a human? “Answer questions” and “take actions on a customer’s account” are different systems with completely different risk profiles.

  2. 2

    Design the guardrail layer before the intelligence layer

    What can this agent never do, no matter what a prompt or a user says? Naming the hard boundaries first keeps the rest of the design honest instead of retrofitted.

  3. 3

    Map the data and tools it actually needs

    What does it need to read, and what does it need to call? You’re almost never starting from a blank slate — you’re integrating with a knowledge base, a ticketing system, or an internal API that already has its own quirks.

  4. 4

    Design for evaluation from the start, not as an afterthought

    How will you know it’s working, and how will you know when a change made it worse? An agent you can’t measure is an agent you can’t safely improve.

  5. 5

    Propose a phased rollout, not a big-bang launch

    Shadow mode, then a narrow pilot, then a wider rollout, each gated on evidence from the previous phase. It’s also the fastest way to find out where the design was wrong before it’s expensive to fix.

The single most common failure mode: naming an architecture before scoping the risk. Jumping to “I’d use a multi-agent setup with a vector database” in the first two minutes reads as a red flag, not a strength. Nobody has earned the right to propose an architecture yet.

Customer support agentInternal RAG assistantMulti-agent coding assistant

Three full walkthroughs follow — different products, same underlying discipline. Read them the way you’d rehearse for the real thing: notice where the candidate asks a question instead of guessing.

Three end-to-end walkthroughs

Case study 1 · Customer support agent

An agent that handles refunds and plan changes

“Support gets buried in refund requests and plan-change questions. We want an agent that can just handle it.”

Interviewer

“We’re a subscription company. Support gets buried in refund requests and plan-change questions. We want an agent that can just handle it. Where would you start?”

Candidate

Before anything else — when you say “handle it,” do you mean answer questions about refunds and plans, or actually issue refunds and change plans?

Interviewer

“Both, eventually. Right now a human does both, and it’s slow.”

Candidate

Those are very different risk levels, so I’d want to split them from the start. Answering questions accurately is one problem. Actually issuing a refund or changing billing is a different one, because a mistake there costs real money and touches a customer’s trust directly. What does the refund policy actually look like — is it a fixed rule, or does it involve judgment calls?

Interviewer

“Mostly rules — refund within 14 days, no questions asked. Outside that window it needs a human’s judgment call.”

Candidate

That’s a clean line to design around. I’d let the agent handle the in-policy case end to end, and hand anything outside the window straight to a human, no attempt to be clever about it. What tools or systems would the agent actually need access to — a billing API, a CRM, something else?

Interviewer

“A billing API that can issue refunds and change plans, and a CRM with the customer’s history. Both have real write access — this isn’t just a read-only lookup tool.”

Candidate

Given that a tool call here can move real money, I want a hard guardrail layer that sits between the agent’s reasoning and those write calls, not just a prompt asking it to be careful. Concretely: a rules engine checks eligibility — is this within 14 days, has this customer already gotten a refund this month — before the refund tool is even callable, regardless of what the agent’s reasoning concluded.

Interviewer

“What if the agent gets talked into it? Customers will absolutely try to convince it they qualify when they don’t.”

Candidate

That’s exactly why the eligibility check can’t live in the prompt. It has to be a deterministic check in code, outside the model’s control entirely, so no amount of clever phrasing from a customer changes the answer. The agent can be as persuadable as it wants in conversation; the tool it calls simply won’t execute if the rule fails.

Interviewer

“Okay. And plan changes?”

Candidate

Same shape, different rule set — some plan changes are free, some involve proration or a contract term, and I’d expect the proration math to be genuinely fiddly. First phase, I’d actually keep plan changes as agent-drafts-the-change, human-confirms, since the failure mode of a wrong proration is messier to unwind than a straightforward refund.

Interviewer

“What ships first, given we want something live in six weeks?”

Candidate

The in-policy refund flow only, in shadow mode for the first week or two — the agent proposes the action, a human clicks confirm, and we log how often the agent’s proposal matches what a human would have done. Once that agreement rate is high and we’ve seen a real week of production traffic, we flip refunds to fully automated within the 14-day rule. Plan changes stay human-confirmed a while longer, since the rules are messier and the blast radius of a mistake is larger.

The architecture that comes out of this

How this decomposes

  1. 1

    Phase 0 — retrieval-only support agent

    The agent answers questions about policy, billing, and account status using retrieval over docs and CRM data. No write tools yet, so the failure mode is a wrong answer, not a wrong action.

  2. 2

    Phase 1 — shadow-mode refund proposal

    A deterministic eligibility check (14-day rule, refund frequency cap) gates whether the refund tool is even callable. The agent proposes an action, a human confirms, and agreement rate is logged before anything is automated.

  3. 3

    Phase 2 — automated in-policy refunds

    Once shadow-mode agreement is high and proven over real traffic, in-policy refunds execute automatically. Anything outside the rule (past the window, repeat refund) routes straight to a human, no agent attempt.

  4. 4

    Phase 3 — human-confirmed plan changes

    Plan-change proration is fiddlier and higher-blast-radius than a refund, so the agent drafts the change and a human confirms for longer before this path is considered for automation too.

Where this could fall apart

Guardrails living in the prompt instead of in code

A persuasive customer can talk a model into believing an exception is warranted. Eligibility has to be a deterministic check the model can’t reason its way around, not an instruction it’s asked to follow.

Treating all actions as equally risky

Lumping refunds and plan changes into one “automate it” bucket ignores that a wrong proration is far messier to unwind than a straightforward refund — they deserve different rollout speeds.

Skipping shadow mode to hit a launch date

Automating a money-moving action on day one, without first measuring how often the agent would have agreed with a human, removes the one signal that tells you whether it’s actually safe.

No fallback path when the agent is unsure

Without an explicit “hand this to a human” exit, an agent under pressure to resolve everything will sometimes force an answer instead of admitting it doesn’t know, which is worse than a slower correct one.

Case study 2 · Internal RAG assistant

A permission-aware knowledge assistant over Confluence, Slack, and Jira

“Engineers waste hours searching Confluence, Slack, and Jira for answers that already exist. Build an assistant that just knows.”

Interviewer

“Our engineers waste hours searching Confluence, Slack, and old Jira tickets for answers that already exist somewhere. We want an internal assistant that just knows the answer. How would you build it?”

Candidate

Before the retrieval design, one question that changes everything: do all of those sources have the same access permissions, or does some of that content vary by team or seniority?

Interviewer

“It varies a lot, actually. Some Confluence spaces are restricted, some Slack channels are private, and there are Jira tickets with customer PII in them that only certain people should see.”

Candidate

Then permission-aware retrieval isn’t a nice-to-have here, it’s the central design constraint — a wrong answer is annoying, but leaking a restricted document through the assistant is a much bigger problem, and one that’s easy to introduce accidentally with a naive vector index. How is access actually controlled today across these three systems — is there a common identity or permission model?

Interviewer

“All three use the same SSO identity, but the permission checks live separately in each system’s own access control.”

Candidate

That’s workable, but it means the retrieval layer can’t just embed everything into one flat index and hope for the best — at query time, I’d need to filter results down to only what this specific user is actually allowed to see, checked against each source’s real permission model, not a cached snapshot that could go stale. What’s the actual query pattern going to look like — a chat interface, something in Slack, an IDE plugin?”

Interviewer

“Probably a Slack bot to start, since that’s where people already ask each other questions.”

Candidate

Good, that also gives a natural place to collect feedback — a thumbs up or down on each answer is a cheap way to start building an eval set instead of guessing whether the assistant is any good. Given the permission complexity, I’d actually start with the least sensitive source first rather than trying to do all three sources at once.

Interviewer

“Which one’s that?”

Candidate

Confluence is the most structured and probably the easiest to reason about permission-wise. I’d ship retrieval over public and semi-restricted Confluence spaces first, with the permission filter proven out at that smaller scale, before adding Slack history and Jira, which both have messier structure and more sensitive content mixed in.

Interviewer

“What happens if it gives someone a wrong answer instead of no answer?”

Candidate

That’s the other reason I want an eval set early — I’d rather the assistant say “I couldn’t find a confident answer” than hallucinate something plausible-sounding from a stale doc. I’d set an explicit confidence threshold based on retrieval score, and below that threshold it says so and links what it did find, rather than guessing.

Interviewer

“Given a one-quarter timeline, what actually ships?”

Candidate

A Slack bot answering questions over Confluence only, permission-filtered per user, with a thumbs up/down feedback loop building an eval set from day one. Slack and Jira ingestion, plus any Jira PII handling, is phase two, once the permission model and the eval process are both proven at smaller scale.

The architecture that comes out of this

How this decomposes

  1. 1

    Phase 1 — Confluence-only retrieval, permission-filtered

    The lowest-sensitivity, most structured source ships first, with per-user permission filtering checked against real access control at query time, not a cached snapshot.

  2. 2

    Phase 2 — feedback loop becomes an eval set

    Thumbs up/down on every answer, from day one, gets collected into a small hand-labeled set so retrieval and answer quality can be measured, not guessed at, before more sources are added.

  3. 3

    Phase 3 — add Slack and Jira, permission model first

    Each new source is added only after its own permission-filtering is verified in isolation — Jira in particular needs an explicit pass for PII-containing tickets before ingestion, not after a leak is reported.

  4. 4

    Phase 4 — confidence threshold tuning and IDE integration

    Once the eval set is large enough to trust, the confidence threshold for “I don’t know” gets tuned against it, and the assistant expands beyond Slack into an IDE plugin or similar surface.

Where this could fall apart

Permission leakage through a flat vector index

Embedding everything into one index without query-time access filtering is the single most damaging mistake here — it turns a helpful assistant into a data-exfiltration path for restricted content.

Stale permission snapshots

Caching who-can-see-what at ingestion time instead of checking it at query time means a permission revoked yesterday can still leak through today.

Confident hallucination over honest uncertainty

An assistant that always produces a fluent-sounding answer, even from thin or stale retrieval, erodes trust faster than one that sometimes says it doesn’t know.

No eval set before scaling sources

Adding Slack and Jira before Confluence retrieval quality is actually measured means any regression from the added complexity is invisible until users start complaining.

Case study 3 · Multi-agent coding assistant

A plan-code-review pipeline under a hard token budget

“We want a coding assistant with separate planner, coder, and reviewer agents, but we have a hard per-request cost cap.”

Interviewer

“We want a coding assistant that can plan a feature, write the code, and review it, using separate agents for each step. But we have a hard per-request cost cap from finance. Design it.”

Candidate

Before I split anything into multiple agents — what’s driving the multi-agent idea specifically? A single agent with a good loop and the right tools can go pretty far, and every extra agent is extra token spend, which matters a lot given the cap you just mentioned.

Interviewer

“Fair pushback. We assumed separate planner, coder, and reviewer agents would each do their one job better than one agent doing all three.”

Candidate

That can be true, but it’s worth testing rather than assuming, especially under a token budget. I’d actually start with a single agent doing plan-then-code-then-self-review as one loop, and use that as the baseline both for quality and for cost. Multi-agent only earns its complexity if it measurably beats that baseline on the same eval set.

Interviewer

“Say the baseline isn’t good enough and we do need to split it. How do you keep it inside the budget?”

Candidate

First, I’d put a shared token budget tracker across the whole request, not a separate budget per agent — otherwise three agents each assuming they have the full budget blows through the cap immediately. Every agent call decrements from one shared counter, and any agent can check how much is left before deciding how much context to pull in.

Interviewer

“What happens when the budget actually runs low mid-task?”

Candidate

That’s the part I’d design for explicitly rather than let happen by accident. Graceful degradation — if the reviewer agent is running low on budget, it falls back to a cheaper, faster model instead of skipping review entirely, or it reviews only the diff instead of the full file. The system should degrade in a controlled way, not just fail or blow the budget.

Interviewer

“What about a task that just needs more tokens than the cap allows, no matter what you do?”

Candidate

Then I’d rather the system say so early and clearly — “this task is estimated to exceed budget, here’s a partial plan” — than silently produce a truncated, half-finished result and present it as complete. I’d build a rough cost estimate at the planning stage, before the coder agent starts, so we catch that case before spending most of the budget getting there.

Interviewer

“How do the agents actually hand off work to each other without wasting tokens re-explaining context?”

Candidate

I’d pass a structured summary between agents rather than the full conversation history — the planner hands the coder a concrete spec, not a transcript of how it arrived there. That’s both cheaper and, honestly, usually produces a cleaner handoff than dumping raw context and hoping the next agent extracts the right part.

Interviewer

“Given all that, what ships first?”

Candidate

The single-agent plan-code-review baseline, measured against a small eval set of real tickets, with the shared token tracker built in from day one even before any multi-agent split. If the baseline’s quality genuinely falls short on some class of task, I’d split just that piece into a second agent, rather than committing to a three-agent architecture up front on an assumption.

The architecture that comes out of this

How this decomposes

  1. 1

    Phase 1 — single-agent baseline with a shared token tracker

    One agent handles plan, code, and self-review as a loop, with a shared token budget counter built in from the start, and its quality measured against a small eval set of real tickets.

  2. 2

    Phase 2 — split only where the baseline measurably falls short

    A second agent (for example, a dedicated reviewer) is introduced only for a task class where the baseline’s eval score is genuinely worse, not as a default architectural choice.

  3. 3

    Phase 3 — graceful degradation under budget pressure

    When the shared budget runs low mid-task, agents degrade in a controlled way — cheaper model, narrower scope — instead of silently exceeding the cap or failing outright.

  4. 4

    Phase 4 — upfront cost estimation at the planning stage

    Before the coder agent starts, a rough token estimate flags tasks likely to exceed budget, so the system can say so early instead of producing a silently truncated result.

Where this could fall apart

Splitting into multiple agents before testing a single-agent baseline

Multi-agent architectures add real token and latency cost. Without a baseline to compare against, there’s no way to know whether the split actually improved anything.

Per-agent budgets instead of one shared tracker

If each agent assumes it has the full budget, three agents can each independently blow through what was meant to be one shared cap.

Failing hard instead of degrading gracefully

A task that simply errors out when the budget runs low is worse than one that finishes with a cheaper model or a narrower scope and says so clearly.

Passing full conversation history between agents

Re-sending raw context at every handoff is an easy way to quietly multiply token spend across a multi-agent pipeline — a structured summary is usually cheaper and clearer.