Vibe Engines
YouTube

Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path

AI System Design

Design an Adaptive AI Tutor

Step 1 / 9

Learn AI system design by building an adaptive tutoring system like Khanmigo or Duolingo's AI tutor step by step.

The numbers to beatper-skillnot one global levelupdatesafter every attempttargetszone of proximal difficulty

The whole design, in writing

Every step of the build above, written out: the problem each piece solves, the option that was taken and the ones that were not, the numbers, and how it fails in production.

The big idea

What makes a tutor "adaptive"?

Bolt an LLM onto a fixed list of practice problems and you've built a chatbot with homework attached — every student gets the same order, the same explanations, no matter what they already know or what specifically confused them. What actually makes a tutor adaptive isn't the LLM at all — it's a model of what this learner knows, driving what to ask next and how to explain it.

Studentanswering, asking
New in this step: Student.

We'll build the pieces most "AI tutor" demos skip: a per-skill mastery model, a grading path that reaches for an exact checker before it ever reaches for an LLM, explanations grounded in a vetted curriculum instead of free generation, and hints that deliberately don't just hand over the answer.

What the new pieces do

Studentclient
The learner — attempting problems, asking questions, sometimes getting stuck and needing a nudge, not the answer.

Step 1 · The baseline

A fixed list of problems

Simplest version: every student gets problems in the same fixed order, chapter by chapter. What actually goes wrong with this for real learners?

Tutor APIsession orchestrationProblem Selectorfixed order (for now)
New in this step: Tutor API, Problem Selector.

Every student sees the same fixed problem order. What's the core failure?

  1. A single fixed order can't simultaneously be right for a student who already knows the first three chapters AND a student who needs to slow down on chapter one — "good for everyone" and "one fixed order" are in direct tension.

  2. A fixed order treats every learner identically regardless of their actual knowledge state. A student who has already mastered a skill is bored repeating it; a student who hasn't mastered a prerequisite is pushed forward into material built on a foundation they don't have yet.

  3. A list of practice problems is tiny; storage isn't remotely the constraint here. The failure is pedagogical, not infrastructural.

A fixed order can't be right for every learner at once — it's simultaneously too slow for students who've already mastered a skill and too fast for students missing a prerequisite. Real personalization needs the system to actually know what this specific student knows.

Why this piece earns its place

The baseline is worth building deliberately rather than treating it as a placeholder, because what a fixed order really encodes is not the list — it is a prerequisite structure flattened into a line. Someone decided fractions come after division. Step 2 discards the line, and discards that judgement with it, unless the judgement was written down separately as edges between skills: this one depends on that one. That graph is authored content rather than code, and it is what later lets a wrong answer point at a missing prerequisite instead of only at the skill that happened to be on screen. The second thing fixed here is the problem bank's metadata. Every piece that follows — mastery, grading routes, review scheduling — reads a per-item label saying which skill this problem exercises and roughly how hard it is. Nothing can be personalized against items that carry no skill tags, and retro-tagging thousands of authored problems is content work, not engineering work, so the cost lands on the people least able to absorb it. Tag at authoring time and it is invisible. The operational tell that you got this wrong: item analytics that can only report one global pass rate, because there is no dimension to group by.

What the new pieces do

Tutor APIgateway
Orchestrates a tutoring session: which problem to show, how to grade the response, when to call the LLM.
Problem Selectorservice
Decides what to ask next — starts as a fixed curriculum order, becomes mastery-aware from Step 2.

Step 2 · The mastery model

Track what this student actually knows

You need to pick the next problem to be neither trivially easy nor hopelessly hard for THIS student, on THIS skill, right now. What decides that?

Problem Selectormastery-awareMastery Modelper-skill estimate
New in this step: Mastery Model.

How does the system decide the right next problem for a specific student's current level?

  1. Self-reported skill is notoriously unreliable — students (especially struggling ones) are often poor judges of their own gaps, which is part of why they need a tutor in the first place.

  2. One data point is noisy — a lucky guess or a careless slip shouldn't swing the whole selection; you want an estimate that accumulates evidence over multiple attempts.

  3. A mastery model accumulates evidence over many attempts into a probabilistic estimate per skill, and problem selection targets difficulty just above what the student can already reliably do — hard enough to stretch them, not so hard it's just frustration, and not so easy it wastes their time.

Maintain a per-skill mastery model — a probabilistic estimate (Bayesian Knowledge Tracing or similar) that updates after every attempt. The Problem Selector uses it to target each student's zone of proximal difficulty: challenging enough to be worth doing, achievable enough not to be discouraging.

Why this piece earns its place

Treat the stored estimate as a derived view, not the record. The durable thing is the attempt log — who answered what, when, and how it was graded — and mastery is recomputed from it. That distinction is what lets you change the model at all. Retuning a skill's guess and slip parameters, or moving from one estimator to another, silently changes the meaning of every number already sitting in the table; with raw attempts you replay and rebuild, without them you have a column whose units shifted mid-corpus and no way to tell which rows are which. Version the estimator beside the values it wrote. The other thing to say out loud is cold start. A brand-new student has no evidence at all, so their first few problems are really a placement probe, and the priors you seed matter more than the estimator does — seed everyone as a beginner and strong students sit through a tedious first session, seed optimistically and weak students meet material built on a prerequisite they never had. Neither shows up as an error.

  • per-skillnot one global level
  • updatesafter every attempt
  • targetszone of proximal difficulty

What the new pieces do

Mastery Modeldata
A per-skill estimate of what this specific learner actually knows — the thing that makes the tutor "adaptive" instead of just a quiz app.

Step 3 · Grading: symbolic first, LLM second

Don't use an LLM to check 2+2

A student submits an answer — sometimes a number, sometimes code, sometimes a written explanation. Should everything route through the LLM for grading?

Tutor APIsession orchestrationMastery Modelper-skill estimateHybrid Gradersymbolic + LLM
New in this step: Hybrid Grader.

Answers range from "42" to a paragraph explaining a concept. Should an LLM grade all of it?

  1. LLM grading is probabilistic and can be inconsistent run to run, and it's slower and more expensive than a symbolic check — using it for something with one exactly-correct answer is strictly worse on cost, speed, AND reliability than a deterministic checker.

  2. A symbolic checker for "does this equal 42" or "do these unit tests pass" is instant, deterministic, and free of any grading-inconsistency risk. The LLM is reserved for exactly the cases that NEED judgment — evaluating whether a written explanation demonstrates real understanding — where no exact check exists.

  3. String matching fails immediately on anything with multiple valid forms (2+2, 2 + 2, four) or any open-ended written response — it's only viable for the narrowest structured cases, not a general grading strategy.

Build a hybrid grader: structured answers (numeric, symbolic math, code with test cases) go to a deterministic exact checker — fast, free, perfectly consistent. Only genuinely open-ended answers (written explanations, proofs, reasoning) are routed to the LLM, which is the one grading tool actually suited to judgment calls.

Why this piece earns its place

Two implementation details decide whether this stays clean. First, the route belongs to the item, not to the answer. The problem declares its answer type at authoring time, so a numeric item is always checked symbolically; sniffing the submitted string at runtime means a student who types a sentence into a numeric field quietly falls through to the expensive path, and LLM spend then grows with the weirdness of your users rather than the shape of your content. Second, the LLM path should return a rubric, not a score. Which criterion did the answer miss — the reasoning, the notation, the conclusion? A bare wrong is enough to move mastery and nothing else; a named failing criterion is what Step 5 hands the explainer, so the hint can address this student's actual misconception instead of re-teaching the topic generically. There is a quieter payoff too, though only if you go and get it. The two paths never see the same submissions — the route is fixed by the item — so symbolic correctness cannot by itself reveal that the LLM grader drifted after a model change. What it hands you is free labels: shadow-grade a frozen sample of structured items with the LLM, off the student's path, and that is your regression set. Open-ended answers need a held-out set someone scored by hand against the rubric.

  • instant + freesymbolic checker path
  • LLMonly for open-ended judgment
  • 0 grading varianceon the structured path

What the new pieces do

Hybrid Graderservice
Grades structured answers (math, code) with an exact symbolic checker; routes only genuinely open-ended answers to the LLM.

Step 4 · Close the loop

Every grade updates the mastery model

A grading result — right, wrong, partially right — is only useful if it actually changes what happens next.

Tutor APIsession orchestrationMastery Modelper-skill estimateHybrid Gradersymbolic + LLM
The system as it stands at this step.

Every graded attempt feeds back into the mastery model immediately: a correct answer nudges that skill's estimate up, an incorrect one nudges it down (and, ideally, flags a related prerequisite skill to revisit). The next problem the Selector picks reflects the updated estimate — this closes the loop between "how did the student just do" and "what should they see next," which is the actual mechanism of adaptivity, not a one-time setup step.

Why this piece earns its place

The interesting bug here is credit assignment. Most real problems exercise more than one skill — a word problem about fractions is also arithmetic, also reading — so a wrong answer has to be attributed to something before any estimate can move, and attributing it to the wrong skill is completely invisible. Nothing errors. The student is simply sent to practise something they already do well while the real gap goes untouched, and the dashboards show a healthy loop throughout. Prefer items tagged with one primary skill, use the grader's rubric to disambiguate where you have one, and be willing to record a low-confidence attribution as weaker evidence rather than forcing a clean choice. The second detail is that this is a read-modify-write on one row per student per skill, so it needs an attempt id and an idempotency rule. Retries, a double-tapped submit button, or an offline client syncing yesterday's work will otherwise count the same answer twice, and after the fact a doubled attempt is indistinguishable from genuine evidence.

Step 5 · Ground the explanations

Don't let the LLM freely teach facts

When a student gets something wrong, they need an explanation — and ideally one tailored to their specific misconception. Should the LLM generate that explanation purely from its own training?

Tutor LLMhints, explanationsCurriculum KBvetted source of truth
New in this step: Tutor LLM, Curriculum KB.

The LLM explains a concept the student got wrong. Generate freely, or ground it in something?

  1. A capable LLM is USUALLY right on well-known material, but "usually" is a dangerous bar for something explicitly being taught as fact to a learner who has no way to verify it — and curriculum-specific conventions (a syllabus's exact definitions, notation, or scope) aren't something the LLM's general training reliably matches.

  2. Grounding constrains what the LLM is allowed to assert as fact to vetted, curriculum-accurate source material, while still letting it do what LLMs are genuinely good at: adapting HOW the explanation is delivered to this student's specific error, in natural, conversational language.

  3. A fully static explanation misses the actual value an LLM adds — tailoring the explanation to the SPECIFIC way this student went wrong, which a pre-written generic paragraph can't do.

Retrieve relevant content from a vetted Curriculum Knowledge Base (RAG) before generating an explanation, and constrain the LLM to ground its answer in that retrieved material — it can still tailor the phrasing, examples, and framing to the student's specific mistake, but the underlying facts come from vetted source material, not free generation.

Why this piece earns its place

Grounding fixes what the tutor asserts; it does not fix what the tutor reaches for. Retrieval also has to be filtered to where this student actually is — the curriculum's own explanation of a concept can be perfectly accurate and still sit three chapters ahead, written in notation they have not met yet. That failure looks nothing like a hallucination, and no amount of vetting the knowledge base prevents it: the passage is correct, it is just the wrong passage for this learner. Put the constraint in the retrieval query, alongside the skill and the level the mastery model already knows, rather than asking the model to simplify afterwards. What this buys you elsewhere is a repair loop, but only if you record what went into each explanation. A hint is synthesised from several retrieved passages together with the student's mistake and the grader's verdict, so a teacher reporting a confusing hint is pointing at a set, not a sentence, and nobody can tell which passage misled it unless the generation logged the ids it was handed. Log them beside the hint. A bad explanation then becomes an edit to vetted source material that improves every future explanation drawing on it, rather than a prompt someone rewords and hopes about.

What the new pieces do

Tutor LLMservice
Generates hints and explanations — grounded in the curriculum, and deliberately gated to avoid just handing over the answer.
Curriculum KBdata
The vetted, syllabus-accurate knowledge the LLM retrieves from, instead of freely generating explanations from parametric memory alone.

Step 6 · Hints, not answers

The Socratic gate

A stuck student asks "just tell me the answer." Should the tutor comply immediately?

StudentTutor APIProblem SelectorMastery ModelHybrid GraderTutor LLMCurriculum KB
The system as it stands at this step. · swipe to pan the diagram

A struggling student directly asks for the answer. What should the tutor do?

  1. Immediately handing over the answer optimizes for the student's immediate comfort at the cost of the actual learning outcome — the productive struggle of almost-getting-there is often where real understanding forms.

  2. A hint ladder gives the student every chance to have the "aha" themselves first, which is where durable learning happens, while still guaranteeing they're never permanently stuck — the direct answer remains available as the last rung, not the first response.

  3. Refusing forever, even after a student has made genuine repeated attempts, just produces frustration and abandonment — the goal is productive struggle with a safety net, not struggle without end.

Build a hint ladder: the first response to "I'm stuck" is a pointer toward the relevant concept, not the answer. Further requests escalate — a more specific hint, then the exact next step — and only after genuine attempts have been made does the tutor give the full direct answer with explanation. This is a deliberate pedagogical gate, not a capability limitation.

Why this piece earns its place

The rung is server-side state, and that is the part people miss. Which hint level this student has reached on this problem has to persist — across a page reload, a second device, a new conversation — or the ladder is decorative. Students find the reset fast: if a fresh session restarts at rung one, asking three times in three tabs is quicker than thinking. What goes with it is your own measurement of the gate. Hint requests per problem is the number you would reach for to judge whether the ladder is working at all, and three tabs look like three learners needing help rather than one learner routing around the gate. The other thing to pin down is what counts as a genuine attempt, since that is what the last rung waits for. The only honest source is a graded submission — Step 3 already produces one — not a count of messages sent. Advance on turns instead and typing "I am stuck" three times walks the student to the bottom of the ladder with no work in between, which is the same outcome as having no gate, arrived at politely.

Step 7 · Remember across sessions

Learning happens over months, not one sitting

A student logs back in three weeks later. Should the tutor start from scratch, or remember that they were shaky on fractions and haven't practiced since?

Tutor APIProblem SelectorMastery ModelHybrid GraderTutor LLMCurriculum KBLearner Profile
New in this step: Learner Profile. · swipe to pan the diagram

Maintain a long-term Learner Profile, separate from any single session's working state — persistent mastery trends, known weak spots, and a forgetting-curve estimate per skill (skills genuinely decay without practice). The Problem Selector consults this profile to bring back a skill for review right around when it's predicted to be forgotten — spaced repetition — rather than only reacting to what happens inside today's session.

Why this piece earns its place

This store changes the product's obligations, not just its features. A months-long record of exactly what a named learner keeps getting wrong is sensitive in a way session state never was. If any of those learners are minors — and the moment you sell into a school they are — retention windows, export, deletion, and who may read it (the student, a parent, a teacher, a district) stop being policy questions and become requirements that land on this store specifically. Build deletion as a supported path and check the tutor still works afterwards, degraded to session-only behaviour rather than broken. The design decision to watch is arbitration. Two things now want to choose the next problem: the mastery model reaching for the right difficulty, and the profile saying a skill is due for review. With no explicit policy the review queue wins whenever a student has been away, so the session after a holiday is all revision and no progress — precisely when motivation is thinnest. Cap the share of review in a session and make that a tunable, not an emergent behaviour.

What the new pieces do

Learner Profiledata
Tracks this learner's weak spots and forgetting curve across weeks and months — separate from the single session's working state.

Step 8 · The sharp edges

Cost, latency, and staying on-curriculum

Hint generation is on the interactive path — a student waiting 8 seconds for a hint is a bad experience. Mastery-model and profile updates don't need to be instant. And an LLM asked an off-topic or inappropriate question needs to stay in its lane.

StudentTutor APIProblem SelectorMastery ModelHybrid GraderTutor LLMCurriculum KBLearner Profile
The system as it stands at this step. · swipe to pan the diagram

Split by latency requirement: hint/explanation generation uses a fast, cheap model tuned for low latency, since it's directly in the student's interactive loop; mastery-model recomputation and profile updates can run slightly deferred/batched, since a few seconds of lag there is invisible to the student. Layer guardrails on the LLM path specifically for the tutoring context: refuse to just do the student's homework verbatim, redirect off-curriculum or inappropriate requests, and never let a jailbreak attempt bypass the hint-ladder's "don't just give the answer" gate.

Why this piece earns its place

The guardrails are the one part of this design whose behaviour you do not own. The orchestrator picks which rung is due, so no model swap can move a student down the ladder — but the wording at that rung is generated, and a newer, more helpful model will cheerfully fold the answer into what is logged as a level-one hint. That failure is invisible from both ends: the ladder state says rung one, the student got the answer, and nothing in your metrics moves. Keep a frozen set of real tutoring transcripts, including the jailbreak attempts you have already seen, and replay it before any model or prompt change ships — scoring each reply on whether it withheld what it was meant to withhold, not on whether it sounds helpful. The cost picture is worth naming too, because it is inverted here. Inference spend scales with engagement, so your best students are your most expensive ones, and a flat per-student cap punishes exactly the behaviour the product exists to produce. Budget per session instead, and decide in advance what degrades when it runs out — shorter explanations, fewer LLM-graded open responses, symbolic-only practice — rather than discovering the answer in the month the bill arrives.

You did it

You just designed an adaptive AI tutor.

StudentTutor APIProblem SelectorMastery ModelHybrid GraderTutor LLMCurriculum KBLearner Profile
The finished design, end to end. · swipe to pan the diagram

Everything you assembled, in order

  • A fixed problem order can't be right for every learner — real adaptivity requires tracking a per-skill mastery estimate per student.
  • The mastery model targets each student's zone of proximal difficulty, and alone (even without an LLM) is already a legitimate adaptive tutor.
  • Grading routes structured answers to a deterministic symbolic checker and reserves the LLM only for genuinely open-ended judgment calls.
  • Every graded attempt feeds back into the mastery model, closing the loop that actually makes selection adaptive over time.
  • Explanations are grounded in a vetted curriculum knowledge base (RAG), not freely generated — a confidently wrong hint is worse than a slow one.
  • Hints escalate through a Socratic ladder instead of immediately giving the direct answer — a deliberate pedagogical gate, not a limitation.
  • A long-term learner profile, separate from session state, drives spaced repetition of skills predicted to be forgotten.
  • Latency-sensitive hint generation and latency-tolerant mastery/profile updates are split, and tutoring-specific guardrails keep the LLM on-curriculum.

Where an interviewer pokes next

Getting the boxes right is the easy half. These are the questions that separate a candidate who drew the diagram from one who has run the thing. Answer each one out loud before you open it.

  1. Could you skip the mastery model entirely and just have a very good LLM adapt in-context, within the conversation?

    In-context adaptation only sees the current conversation — it has no memory of the student's performance on unrelated skills last week, no probabilistic estimate that survives a context window reset, and no principled way to decide "should the NEXT problem be harder or easier" beyond whatever it infers from the last few messages. A dedicated mastery model gives you a persistent, queryable, auditable estimate of competence per skill that outlives any single conversation — which is also what lets the Problem Selector make a genuinely informed choice about what to show next, rather than a plausible-sounding guess.

  2. Why not have the LLM do the symbolic grading too, just to keep the architecture simpler with one component?

    Simplicity of architecture isn't free here — an LLM grading "does 2x+3=7 imply x=2" introduces exactly the failure modes a symbolic checker doesn't have: occasional inconsistency (the same answer graded differently on different runs), latency (a network call and generation instead of an instant deterministic check), and cost (paying for inference on something with one verifiably correct answer). The hybrid design has two components instead of one, but each component is being used for exactly what it's best at — that's a better trade than a simpler architecture that's worse at its actual job.

  3. How would grounding actually stop a hallucination in practice — walk through a concrete example?

    Say a student asks why a particular algorithm has O(n log n) complexity. Ungrounded, the LLM generates an explanation purely from its training data — usually right for something this common, but with no guarantee, and no way to distinguish "confident and correct" from "confident and subtly wrong" in the output. Grounded, the system first retrieves the curriculum's own vetted explanation of that specific algorithm's complexity analysis from the Curriculum KB, then prompts the LLM to explain THAT retrieved content in a way tailored to the student's specific confusion — the LLM's job shifts from "recall and state a fact" (risky) to "rephrase and adapt a fact that's already been verified" (much safer), which is the core value proposition of RAG applied to teaching specifically.

  4. Should the hint ladder ever be skippable, and if so, when?

    Yes — for a student who has clearly demonstrated mastery of a skill in the past (per the mastery model) and is just moving quickly through review material, forcing a full hint ladder on every question adds friction without pedagogical benefit; the system can reasonably shorten or skip the ladder based on that same mastery signal. The ladder matters most precisely when a student is encountering a skill they haven't yet mastered — which the mastery model already tells you — so the hint-gating policy itself can, and should, be adaptive too, not a fixed rule applied uniformly regardless of what's already known about the learner.

  5. What's the actual risk of a jailbreak attempt in a tutoring context, beyond generic LLM safety concerns?

    Beyond generic safety risks (harmful content, etc.), tutoring has a domain-specific failure mode: a student figuring out how to prompt the LLM into just outputting the direct answer, bypassing the hint ladder entirely — which defeats the actual pedagogical purpose of the whole system even though no "unsafe" content was produced. This means the guardrails here aren't only about content safety in the generic sense; they specifically need to detect and resist "give me the answer directly" framed as a system-prompt override, a roleplay request, or any other jailbreak pattern that would let the student route around the deliberate pedagogical gate from Step 6.

Check yourself — the answers, and why

Nine steps in, these are the calls you should be able to make cold. Pick one, then read why.

  1. What actually makes a tutoring system "adaptive"?

    Without a mastery estimate per student per skill, there's nothing to adapt TO — the LLM alone doesn't make selection personalized.

  2. A structured answer like a math expression or code with test cases should be graded by…

    A symbolic checker is faster, free, and perfectly consistent for anything with one verifiably correct answer.

  3. Explanations are grounded in a curriculum knowledge base (RAG) instead of freely generated because…

    Grounding constrains what the LLM asserts as fact to vetted material, while still letting it tailor the delivery.

  4. When a stuck student asks for the direct answer, the tutor should…

    Productive struggle drives durable learning; the direct answer remains a safety net, not the default first response.

  5. The long-term Learner Profile exists separately from session state to…

    Session state is short-lived working memory; the learner profile is what personalizes across the student's whole learning journey.

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

What it must do

Agree on these before drawing a single box.

  • Pick the next problem: choose what to ask next for this student’s current level, not a fixed order.
  • Grade: check structured answers exactly and route only open-ended ones to the LLM.
  • Explain: generate hints and explanations tailored to the student’s specific mistake.
  • Gate hints: escalate through Socratic hints instead of handing over the answer.
  • Remember: track weak spots and forgetting curves across sessions for spaced repetition.

The qualities that shape everything

Each one names the mechanism that buys it.

Personalize what to teach next
A per-skill Mastery Model (Bayesian-Knowledge-Tracing-style) updates after every attempt and targets the zone of proximal difficulty.
Grade cheaply, correctly, consistently
A Hybrid Grader routes structured answers to a deterministic symbolic checker and reserves the LLM only for open-ended judgment.
Adaptivity that actually adapts over time
Every graded attempt feeds back into the mastery model, closing the grade → mastery → selection loop.
No confidently-wrong teaching
Explanations are grounded in a vetted Curriculum KB (RAG); the LLM tailors delivery but the facts come from vetted source material.
Durable learning, not just comfort
A Socratic hint ladder escalates to the direct answer only after genuine attempts — a deliberate pedagogical gate.
Learning that spans months
A long-term Learner Profile, separate from session state, drives spaced repetition of skills predicted to be forgotten.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

A per-skill mastery model over a single fixed problem order

One fixed order is simultaneously too slow for students who’ve mastered a skill and too fast for those missing a prerequisite. You can’t personalize without tracking what this student knows.

A symbolic checker first over grading everything with the LLM

LLM grading is slower, costlier and inconsistent run-to-run for something with one exactly-correct answer. Reserve the LLM for cases that genuinely need judgment.

Grounded explanations (RAG) over free LLM generation

A confidently wrong hint taught as fact is worse than a slow one, and curriculum-specific conventions aren’t reliably in the model’s general training.

A Socratic hint ladder over giving the answer immediately

Handing over the answer optimizes for the student’s immediate comfort at the cost of learning; the productive struggle of almost-getting-there is where understanding forms.

A separate long-term profile over session state alone

Session state is short-lived working memory. The durable learner profile is what makes the tutor smarter about this individual over weeks, enabling spaced repetition.

The answer, out loud

What a strong answer to “Design an Adaptive AI Tutor” sounds like, first question to last trade-off. It is about 7 minutes of talking; the whiteboard and the interviewer fill the rest of the 45. Read it aloud once, then close the page and give it yourself.

  1. 0–3 min

    Name the part that is actually adaptive

    I'd start by saying what adaptive has to mean here, because the LLM isn't it. Bolt a model onto a fixed list of practice problems and every student still gets the same order and the same explanations, whatever they already know. The thing that makes a tutor adaptive is a model of what this particular learner knows, driving what to ask next and how to explain it. So the requirements I'd write down are: pick the next problem, grade the answer, explain the mistake, gate the hints, and remember across sessions.

  2. 3–8 min

    Start from the baseline and name its failure

    The skeleton is a student, a tutor API, and a problem selector. The naive version has the selector handing out a fixed curriculum order, and I want to say out loud why that fails rather than skip past it: one order is simultaneously too slow for a student who has already mastered the first chapters and too fast for one missing a prerequisite. You can't personalize without tracking what this specific student knows, so everything after this exists to build that estimate and use it.

    Built in step 1: A fixed list of problems
  3. 8–15 min

    The mastery model is the product

    So I'd add a per-skill mastery model — a Bayesian-Knowledge-Tracing-style estimate per student per skill, updated after every attempt. The selector reads it and targets that student's zone of proximal difficulty: hard enough to be worth doing, achievable enough not to be discouraging. The reason I'd reach for this over a single global level is that students aren't uniformly strong or weak; they're solid on one skill and shaky on its neighbour. And I'd point out that this plus a decent problem bank is already a legitimate adaptive tutor, with no LLM in it at all.

    Built in step 2: Track what this student actually knows
  4. 15–21 min

    Grade with the cheapest tool that is correct

    Grading I'd split. Structured answers — a number, an expression, code with test cases — go to a deterministic symbolic checker: instant, free, perfectly consistent. Only genuinely open-ended answers, a written explanation or a proof sketch, go to the LLM. The reason I'd reach for the checker first is that LLM grading is slower, costlier, and can grade the same answer differently on different runs, which is strictly worse for something with one exactly-correct answer. The LLM is reserved for the cases that actually need judgment.

    Built in step 3: Don't use an LLM to check 2+2
  5. 21–25 min

    Close the loop

    Then I'd close the loop, which is the part that makes any of this adaptive rather than a one-time setup. Every graded attempt feeds straight back into the mastery model — a correct answer nudges that skill up, an incorrect one nudges it down and flags a prerequisite worth revisiting — and the next problem the selector picks reflects the updated estimate. Grade feeds mastery, mastery feeds selection, selection produces the next attempt to grade. It's a loop that runs for the length of the session and beyond, not a pipeline.

    Built in step 4: Every grade updates the mastery model
  6. 25–32 min

    Ground the explanations

    Now the LLM earns its place, on explanations. When a student gets something wrong I want a hint tailored to their specific misconception — but I wouldn't let the model supply the facts. I'd retrieve the relevant material from a vetted curriculum knowledge base and have the model tailor the delivery of that retrieved content. A confidently wrong hint is worse than a slow one, because it teaches misinformation to someone with no way to check it, and a syllabus's own definitions and notation aren't reliably in a general model's training.

    Built in step 5: Don't let the LLM freely teach facts
  7. 32–37 min

    Hints, not answers

    For a stuck student asking me to just tell them, I'd build a hint ladder: first a pointer at the relevant concept, then the specific step, and only after genuine attempts the direct answer with a full explanation. That's a deliberate pedagogical gate, not a capability limit — left alone, a model optimized to be helpful will hand the answer straight over, which optimizes for the student's immediate comfort against the thing we're here for. The direct answer stays available as the last rung, so nobody is permanently stuck.

    Built in step 6: The Socratic gate
  8. 37–42 min

    Remember across sessions

    Then a long-term learner profile, kept separate from session state. Session state is working memory; the profile carries persistent mastery trends, known weak spots, and a forgetting-curve estimate per skill, because skills genuinely decay without practice. The selector consults it to bring a skill back for review right around when it's predicted to be forgotten — spaced repetition — instead of only reacting to what happened inside today's session. That's what makes the system get smarter about this individual over months rather than one sitting.

    Built in step 7: Learning happens over months, not one sitting
  9. 42–47 min

    The sharp edges, and what I would do next

    Two sharp edges to flag. Hint generation sits in the student's interactive loop, so it wants a fast, cheap model, while mastery and profile updates can run deferred — a few seconds of lag there is invisible. And the LLM path needs tutoring-specific guardrails: don't do the homework verbatim, redirect off-curriculum requests, and don't let a jailbreak route around the hint ladder. The trade-off I'd own is that every piece here buys personalization with state we then have to keep correct — lose the mastery model and it degrades to a fixed curve, cut grounding and it can teach something subtly wrong. With more time I'd work through what a teacher sees on the other side of all this, and how I'd prove the thing actually teaches — engagement is the easy number to move and it isn't the one we're here for.

    Built in step 8: Cost, latency, and staying on-curriculum

What this teaches

Learn AI system design by building an adaptive tutoring system like Khanmigo or Duolingo's AI tutor step by step. An interactive guide covering why a fixed question order fails every learner, a per-skill mastery model that picks the next problem, hybrid grading (symbolic checkers for structured answers, an LLM only for open-ended ones), closing the mastery feedback loop, grounding explanations in a curriculum knowledge base to prevent hallucinated facts, Socratic hint-gating instead of giving away answers, and a long-term learner profile for spaced repetition.

Key takeaways

  • A fixed problem order can't be right for every learner — real adaptivity requires tracking a per-skill mastery estimate per student.
  • The mastery model targets each student's zone of proximal difficulty, and alone (even without an LLM) is already a legitimate adaptive tutor.
  • Grading routes structured answers to a deterministic symbolic checker and reserves the LLM only for genuinely open-ended judgment calls.
  • Every graded attempt feeds back into the mastery model, closing the loop that actually makes selection adaptive over time.
  • Explanations are grounded in a vetted curriculum knowledge base (RAG), not freely generated — a confidently wrong hint is worse than a slow one.
  • Hints escalate through a Socratic ladder instead of immediately giving the direct answer — a deliberate pedagogical gate, not a limitation.
  • A long-term learner profile, separate from session state, drives spaced repetition of skills predicted to be forgotten.
  • Latency-sensitive hint generation and latency-tolerant mastery/profile updates are split, and tutoring-specific guardrails keep the LLM on-curriculum.

Concepts covered

  • What makes a tutor "adaptive"?
  • A fixed list of problems
  • Track what this student actually knows
  • Don't use an LLM to check 2+2
  • Every grade updates the mastery model
  • Don't let the LLM freely teach facts
  • The Socratic gate
  • Learning happens over months, not one sitting
  • Cost, latency, and staying on-curriculum
RUN IT YOURSELF

The mastery rule that only beats a streak once learners are careless

3000 simulated learners, each with a hidden skill state no tutor can see, answer 20 questions — where a right answer can be a lucky guess and a wrong one a careless slip. A streak rule and a Bayesian estimate with explicit guess and slip rates read the same answers, and 151 BKT thresholds are swept to find the one that advances no more unskilled learners than the streak rule does. It prints how many learners each rule then strands on a skill they already have — on this cohort and on three fresh ones. Change SLIP at the top, hit Run, and watch that gap go from exactly zero to +600, through negative on the way.

HOW TO READ THE CODE — 5 IDEAS
  1. The tutor never sees the hidden state, only right or wrong — which is why step 2 rejects deciding from the most recent answer alone.
  2. Read both columns: a premature advance pushes a learner into material built on a prerequisite they lack; held back spends a whole sitting on a skill they already had (step 1).
  3. The streak rule's flaw is the reset: one wrong answer erases every correct answer before it. BKT discounts that answer by the slip rate instead, which is what step 4 means by every graded attempt feeding the estimate.
  4. The advantage is bought entirely with SLIP, and the printed number goes where that buys it: 0.00 → +0, +0, +0; 0.10 → -30, -12, +36 (a streak of 3 is already on the frontier, and BKT loses); 0.20 → +20, +95, +225; 0.35 → +147, +380, +600.
  5. The headline is the four-cohort average, not the table: the same comparison reruns on three fresh cohorts inside the same run and prints them in brackets, because one cohort of 3000 puts the streak-of-3 gap anywhere from +10 to +32.
CPython · WebAssembly
built to teach the next-right thing, not the next thing in a fixed list — make the calls, cut grounding, run the gauntlet.
Finished this one? 0 / 65 AI System Designs done
NextDesign a Conversational AI Closest AI system design to this one

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More AI System Designs