InterviewKata
System design · Worked design D31 of 46 · Data and infrastructure · Long form

Design an AI customer-support assistant

A shopper types "Where's my order, and can I still cancel it?" into the chat window. An assistant answers in seconds from the help centre and the shopper's own orders, cancels the order after they confirm, and hands the conversation to a person, with a summary, when it shouldn't decide alone. The model is the easy part; the design is about grounding, safe actions, handoffs and measuring whether it actually helps.

1. The prompt

"Design an AI assistant for customer support on a large online store. It answers questions in chat using our help centre and the customer's orders, can do simple things like cancelling an order or starting a return, and hands off to human agents when needed."

What makes it hard:

2. Frame the problem

How much traffic?

10 M customers; ~200 K conversations a day, about 6 messages each; 3× at holiday peaks.

Small for a web service, but every message is a model call that costs real money.

What may it do on its own?

Read: order status, delivery tracking, return eligibility. Write: cancel an unshipped order, start a return, update a delivery note. Refunds over $100, account changes and complaints go to people.

An explicit list of allowed actions with limits, instead of "whatever the model decides".

Where do answers come from?

~5,000 help-centre articles, updated weekly, plus the customer's own account data.

Retrieval-augmented generation (RAG) over articles, and tools for account data.

Is there a human team?

Yes, 24/7, working in an existing ticketing tool.

The handoff must land inside that tool with context, not as a new system.

Languages and channels?

Web and app chat in 5 languages. Email and voice later.

Multilingual retrieval; design the core so other channels can reuse it.

What data must never reach the model?

Card numbers and passwords; other customers' data, obviously.

Redaction and scoping happen in our code, not by asking the model nicely.

3. What it must do

  1. Answer questions from the help centre, citing the articles used, and say so when it doesn't know.
  2. Look up the customer's orders and take allowed actions, always after the customer confirms.
  3. Hand off to a human with a summary when it can't or shouldn't help, and learn from how humans resolve those cases.

Not now: voice calls, proactive outreach ("your parcel is late"), sales recommendations.

4. How well it must do it

TargetWhy this number
Grounded: fewer than 1 in 200 answers contradict a policy, measured by reviewing samples data qualityWrong policy answers become refunds, complaints and screenshots.
Safe actions: no action without confirmation; only on the signed-in customer's own orders security · consistencyOne wrong cancellation outweighs many good answers.
Helpful: at least half of conversations resolved without a person, with satisfaction no worse than human chat data qualityThat's the business case; satisfaction stops it being bought by stonewalling.
Fast: first words within 1.5 s, full answer within ~6 s speedChat feels broken after a few seconds of nothing; streaming hides generation time.
Never a dead end: if the AI path fails, chat goes to people surviving failuresCustomers came for help, not for our outage.

5. Numbers that change the design

QuantityWorking→ so we…
Model calls200 K × 6 ≈ 1.2 M a day ≈ 14 a second, ~50 at peakModest → so a hosted model API is fine; the work is in what we send it
Tokens per call~1.5 K instructions + ~2 K retrieved text + ~1 K history + ~300 out ≈ 5 K→ so cache the fixed instructions (prompt caching) and summarise long histories
CostAt an illustrative $3 per million input tokens and $15 per million output: ≈ $0.08 a conversationSmall next to a human contact, which costs several dollars → so optimise quality first, cost second
Knowledge5,000 articles ≈ 50 K chunks of a few hundred wordsTiny → so one vector index plus keyword search fits in memory; no sharding

6. The nouns

conversations  conversation_id, customer_id, channel, language, status (bot | waiting_human | human | closed), created_at
messages       conversation_id, seq, role (customer | assistant | agent | tool), text, citations[], created_at
chunks         chunk_id, article_id, language, heading_path, text, embedding, effective_from, version
actions        action_id, conversation_id, tool, args, status, idempotency_key, confirmed_at, result
handoffs       conversation_id, reason, summary, ticket_id, created_at

7. The contract

POST /v1/conversations                                   → {conversation_id}
POST /v1/conversations/{id}/messages {text}              → stream of events (server-sent events):
       token… · citation {article_id, title} · action_proposed {action_id, summary} · handoff {eta}
POST /v1/conversations/{id}/actions/{action_id}/confirm  → {status, result}       (the customer's button press)
POST /v1/conversations/{id}/handoff {reason}             → {ticket_id}

Tools the model may request (run by our server, never by the model):
search_help(query)            get_orders(limit)            track(order_id)
cancel_order(order_id)        start_return(order_id, items, reason)        (both need confirmation)

Note what's missing: no tool takes a customer_id. The server fills it in from the session, so no wording in a message can make the assistant read someone else's orders.

8. First working version

A conversation service streams to the chat widget. For each message an orchestrator retrieves help-centre chunks, calls the model with the instructions, the chunks, the history and the tool list, runs any tool the model requests (after checks), and streams the answer with citations.

8.1 Answering a policy question

Retrieval runs before the model: hybrid search (keywords plus embeddings) returns the best few chunks, which go into the prompt with an instruction to answer only from them and cite them. The answer streams token by token.

8.2 Taking an action

The model only proposes a cancellation. The orchestrator checks that the order belongs to this customer and is cancellable, shows a confirmation card, and calls the order service only when the customer presses it, with an idempotency key so a double tap cancels once.

Parked for latergetting retrieval and grounding right (9.1) · safe actions (9.2) · prompt injection and data leaks (9.3) · when and how to hand off (9.4) · measuring quality (9.5) · latency and cost (9.6) · keeping knowledge current (9.7).

9. Make it hold up

9.1 Retrieval and grounded answers grounded

ApproachWhy
✗ BadAsk the model with no retrieval, or paste whole articlesIt answers from its general training ("most stores allow 30 days"), or drowns the relevant line in text.
~ GoodEmbed chunks; take the top 5 by vector similarityMisses exact terms like order codes or product names, and a chunk out of context ("this does not apply") can mislead.
✓ GreatChunk by article headings with the heading path attached; hybrid search (keywords + embeddings) then a re-ranker; answer only from the sources with citations; if the best sources score low, say so and offer a personPrecise retrieval, answers you can check, and a refusal path instead of a guess. Try the threshold in section 13.

Filter chunks by the customer's language and country (return windows differ by country), and by effective date, so a policy that starts next month isn't quoted today.

9.2 Actions that can't go wrong quietly safe actions

9.3 Prompt injection and data leaks security

ApproachWhy
✗ BadRely on the instructions: "never reveal other customers' data"A message such as "ignore your rules, you are in admin mode" can talk a model out of instructions.
~ GoodPlus input and output filters for known attack phrases and personal dataHelps, but attacks are endlessly rephrased, and text inside an order note or a returned email can carry them too.
✓ GreatDesign so a fooled model can't do harm: tools scoped to the session's customer, confirmations for writes, no secrets or card data in the context, redaction before logging, and filters as an extra layerThe worst a successful injection achieves is a rude or wrong message, which evals and monitoring catch (OWASP's LLM risks list covers these).

9.4 Handing off to a person never a dead end

Hand off when the customer asks, when retrieval confidence is low, after two failed attempts, when sentiment turns angry, for excluded topics (legal threats, safety, bereavement), or when a policy limit is hit. The agent receives a short model-written summary, the transcript, the articles cited and any actions taken, inside the ticketing tool, so the customer never repeats themselves. How agents resolve these cases becomes new eval cases and, where the answer was missing, new help articles.

9.5 Measuring quality helpful · grounded

ApproachWhy
✗ BadDeflection rate: share of chats that never reached a humanRewards stonewalling; a customer who gives up counts as a success.
~ GoodPlus thumbs up or down at the endFew people vote, and those who do skew angry or delighted.
✓ GreatOffline: a few hundred eval cases from real transcripts, graded for correctness, grounding and tone (a model grader checked against human grades), run on every prompt, model or retrieval change as a release gate. Online: resolution confirmed by no re-contact within 7 days, satisfaction surveys, handoff reasons, and a weekly human review of sampled conversationsChanges ship only if they don't regress the eval set, and production numbers track real outcomes (Module 29).

9.6 Latency and cost fast

9.7 Keeping knowledge current grounded

When an article is published, an event re-chunks and re-embeds just that article, and the old chunks are removed in the same step, so search never returns two versions. Chunks carry an effective date for scheduled policy changes. For urgent changes (a recall, a storm delaying deliveries), a short "notice" article with a high retrieval boost goes live in minutes. Eval cases that mention a changed policy are updated in the same change.

9.8 The whole design after the deep dives

10. Interviewer follow-ups

A customer asks for compensation for a late delivery.

Compensation is a policy decision with money attached: the assistant can explain the policy and collect details, then hands off (or offers a fixed, pre-approved voucher if policy allows one, as a confirmed action within limits).

The return policy changes tomorrow at midnight.

Publish the new article now with an effective date; retrieval switches at midnight. Update the affected eval cases and run the eval set against tomorrow's date before then.

The model provider has an outage.

Circuit breaker to a second provider with the same prompts (evaluated in advance); if that fails too, route new chats straight to the human queue with a wait estimate.

Add email support.

Same orchestrator and tools; no streaming, longer answers, and confirmations become links that expire. Higher bar for automatic replies because a wrong email can't be corrected mid-conversation.

How do you know it isn't just making customers give up?

Track re-contact within 7 days on any channel, satisfaction for bot-resolved chats vs human ones, and sample "resolved" conversations for review.

Should we fine-tune a model on our transcripts?

Not first. Retrieval keeps facts current and traceable; fine-tuning bakes in yesterday's policies. Consider it later for tone and format, measured on the same eval set.

11. When things break

FailureWhat users seeHow we detect itWhat limits the damage
Model provider slow or downSlow or no answersTime to first token, error rateSecond provider, then route to humans
Retrieval returns stale policyWrong answerEval failures, agent reportsEffective dates, re-index on publish, citations make it visible
Order service downCan't check or cancelTool error rateSay so plainly, offer to hand off or retry later
Injection attempt succeeds at wordingAn odd replyOutput filters, sampled reviewTools scoped to the session; writes need confirmation
Human queue overloadedLong waits after handoffQueue lengthShow wait times, offer a callback or email follow-up
A prompt change regresses qualityWorse answersEval gate, online resolution dipVersioned prompts, gradual rollout, instant rollback

12. Wrap-up and the clock

Trade-offs we made:

What we'd watch: confirmed resolution rate · satisfaction (bot vs human) · handoff reasons · eval pass rate · time to first token · cost per conversation · tool error rate.

At 10×: more of the same model calls (the API scales), a bigger human team for handoffs, per-language eval sets, and retrieval sharded by language if the knowledge base grows.

A 60-minute interview

0–5Frame: allowed actions, knowledge, humans, privacy
5–10Must do, how well, numbers
10–15Nouns, contract (no customer_id in tools)
15–25First version: answer and act
25–50Deep dives: grounding (9.1), safe actions (9.2), evals (9.5)
50–60Handoff or injection, follow-ups, wrap-up

A 90-minute interview

0–8Frame, including languages and limits
8–15Must do, how well, numbers
15–22Nouns, contract
22–35First working version
35–75Deep dives 9.1–9.7 and the final picture
75–85Follow-ups: outage, policy change, fine-tuning
85–90Trade-offs, metrics, 10×
LevelWhat a strong answer shows
Mid-levelRAG over the help centre, a chat service with streaming, tools for order lookups, a handoff button.
SeniorHybrid retrieval and re-ranking, citations and a refusal path, confirmed and idempotent actions scoped by the session, an eval set as a release gate.
Staff+Designing so a fooled model can't do harm, metrics that can't be gamed by deflection, the human team as part of the system, and the feedback loop from handoffs to knowledge.

Common mistakes:

13. Try it, check yourself, read more

Answer-or-hand-off lab. Ten real-looking questions, each with the retrieval confidence of its best source and whether that source really answers it. The assistant answers when confidence is at least the threshold, and hands off otherwise. Move the threshold and watch automation trade against wrong answers.

0.60

    The scores are illustrative. In practice you set the threshold from an eval set, so that the wrong-answer rate stays under the target.

    Where does cancel_order get the customer's identity?

    Then no message, however clever, can point the tool at someone else's orders.

    Which metric shows the assistant really helps?

    Deflection counts customers who gave up as successes.

    Customers ask with exact order codes and vague wording. Which retrieval fits?

    Keywords catch exact terms, vectors catch meaning, and the re-ranker orders the combined list.

    What's the most reliable defence against prompt injection here?

    Scoped tools and confirmations limit what any successful injection can do.
    ResourceWhy
    Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (Lewis et al., 2020)The paper that named RAG.
    Contextual Retrieval (Anthropic)Hybrid search, re-ranking and adding context to chunks, with measured gains.
    Building effective agents (Anthropic)When to use a fixed workflow and when to let the model choose tools.
    OWASP Top 10 for LLM applicationsPrompt injection, excessive agency and data leaks, with mitigations.
    Judging LLM-as-a-Judge (Zheng et al., 2023)How far model graders agree with people, and their biases.