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:
- A confident wrong answer is worse than no answer. Inventing a refund policy costs money and trust.
- Actions are real. Cancelling the wrong order, or someone else's, is a serious incident.
- Success is hard to measure. A closed chat can mean "solved" or "gave up".
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
- Answer questions from the help centre, citing the articles used, and say so when it doesn't know.
- Look up the customer's orders and take allowed actions, always after the customer confirms.
- 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
| Target | Why this number |
|---|---|
| Grounded: fewer than 1 in 200 answers contradict a policy, measured by reviewing samples data quality | Wrong policy answers become refunds, complaints and screenshots. |
| Safe actions: no action without confirmation; only on the signed-in customer's own orders security · consistency | One wrong cancellation outweighs many good answers. |
| Helpful: at least half of conversations resolved without a person, with satisfaction no worse than human chat data quality | That's the business case; satisfaction stops it being bought by stonewalling. |
| Fast: first words within 1.5 s, full answer within ~6 s speed | Chat 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 failures | Customers came for help, not for our outage. |
5. Numbers that change the design
| Quantity | Working | → so we… |
|---|---|---|
| Model calls | 200 K × 6 ≈ 1.2 M a day ≈ 14 a second, ~50 at peak | Modest → 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 |
| Cost | At an illustrative $3 per million input tokens and $15 per million output: ≈ $0.08 a conversation | Small next to a human contact, which costs several dollars → so optimise quality first, cost second |
| Knowledge | 5,000 articles ≈ 50 K chunks of a few hundred words | Tiny → so one vector index plus keyword search fits in memory; no sharding |
6. The nouns
- Conversation and message; the conversation belongs to one signed-in customer.
- Article and its chunks, each with an embedding and an effective date.
- Action: a proposed tool call (cancel order 123), with a status: proposed, confirmed, done, failed.
- Handoff: a ticket for a human with the summary and transcript.
- Eval case: a question with what a correct answer must and must not say.
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.
9. Make it hold up
9.1 Retrieval and grounded answers grounded
| Approach | Why | |
|---|---|---|
| ✗ Bad | Ask the model with no retrieval, or paste whole articles | It answers from its general training ("most stores allow 30 days"), or drowns the relevant line in text. |
| ~ Good | Embed chunks; take the top 5 by vector similarity | Misses exact terms like order codes or product names, and a chunk out of context ("this does not apply") can mislead. |
| ✓ Great | Chunk 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 person | Precise 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
- The server owns authority. Tools are an allowlist; arguments are validated; the customer comes from the session; each tool calls the same order APIs (and rules) the website uses.
- Propose, confirm, execute. Anything that changes state shows a card in plain words ("Cancel order #4821, 2 items, $63.10?") and runs only on the customer's press.
- Idempotency keys on every write, so retries and double taps are harmless (Module 22).
- Limits by policy, in code: refunds over $100, repeated cancellations, or flagged accounts route to a human whatever the model says.
- Audit log of every proposal, confirmation and result, linked to the conversation.
9.3 Prompt injection and data leaks security
| Approach | Why | |
|---|---|---|
| ✗ Bad | Rely 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. |
| ~ Good | Plus input and output filters for known attack phrases and personal data | Helps, but attacks are endlessly rephrased, and text inside an order note or a returned email can carry them too. |
| ✓ Great | Design 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 layer | The 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
| Approach | Why | |
|---|---|---|
| ✗ Bad | Deflection rate: share of chats that never reached a human | Rewards stonewalling; a customer who gives up counts as a success. |
| ~ Good | Plus thumbs up or down at the end | Few people vote, and those who do skew angry or delighted. |
| ✓ Great | Offline: 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 conversations | Changes ship only if they don't regress the eval set, and production numbers track real outcomes (Module 29). |
9.6 Latency and cost fast
- Stream every answer; show "checking your order…" while a tool runs (Module 19).
- Route by difficulty: a small, fast model classifies intent and handles simple turns ("thanks!"); a stronger model handles policy reasoning.
- Prompt caching for the long fixed instructions and tool definitions cuts cost and time to first token.
- Summarise history beyond a few turns instead of resending everything.
- Fallbacks: a second model provider for outages, and humans if both fail (Module 24).
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
| Failure | What users see | How we detect it | What limits the damage |
|---|---|---|---|
| Model provider slow or down | Slow or no answers | Time to first token, error rate | Second provider, then route to humans |
| Retrieval returns stale policy | Wrong answer | Eval failures, agent reports | Effective dates, re-index on publish, citations make it visible |
| Order service down | Can't check or cancel | Tool error rate | Say so plainly, offer to hand off or retry later |
| Injection attempt succeeds at wording | An odd reply | Output filters, sampled review | Tools scoped to the session; writes need confirmation |
| Human queue overloaded | Long waits after handoff | Queue length | Show wait times, offer a callback or email follow-up |
| A prompt change regresses quality | Worse answers | Eval gate, online resolution dip | Versioned prompts, gradual rollout, instant rollback |
12. Wrap-up and the clock
Trade-offs we made:
- Answer less often, but correctly: low-confidence questions go to people.
- Confirmation steps for every write, at the cost of one extra tap.
- Retrieval instead of fine-tuning, so facts stay current and citable.
- Quality gates on every change, which slows prompt tweaks.
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–5 | Frame: allowed actions, knowledge, humans, privacy |
| 5–10 | Must do, how well, numbers |
| 10–15 | Nouns, contract (no customer_id in tools) |
| 15–25 | First version: answer and act |
| 25–50 | Deep dives: grounding (9.1), safe actions (9.2), evals (9.5) |
| 50–60 | Handoff or injection, follow-ups, wrap-up |
A 90-minute interview
| 0–8 | Frame, including languages and limits |
| 8–15 | Must do, how well, numbers |
| 15–22 | Nouns, contract |
| 22–35 | First working version |
| 35–75 | Deep dives 9.1–9.7 and the final picture |
| 75–85 | Follow-ups: outage, policy change, fine-tuning |
| 85–90 | Trade-offs, metrics, 10× |
| Level | What a strong answer shows |
|---|---|
| Mid-level | RAG over the help centre, a chat service with streaming, tools for order lookups, a handoff button. |
| Senior | Hybrid 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:
- Letting the model pass customer IDs to tools.
- Actions without confirmation or idempotency.
- Measuring deflection instead of resolution.
- No path to a human when the AI is unsure or down.
- Shipping prompt changes without an eval run.
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.
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?
Which metric shows the assistant really helps?
Customers ask with exact order codes and vague wording. Which retrieval fits?
What's the most reliable defence against prompt injection here?
| Resource | Why |
|---|---|
| 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 applications | Prompt 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. |