An AI tutor that will not leak the answer
Ask a general assistant to rephrase an exam question and it often rephrases it into the answer. Why tutor modes belong on the server, not in a system prompt.
لم تُترجَم هذه المقالة بعد — تُعرض النسخة الإنجليزية.
Ask a general-purpose assistant to rephrase an exam question and it will often rephrase it into the answer. Which gas do plants take in during photosynthesis? comes back as Which gas, absorbed from the air and combined with water to make sugar, do plants take in? — technically a restatement, practically a give-away. Nobody had to jailbreak anything. The learner asked for a rephrasing, then a hint, then another, and somewhere in that sequence the model said the thing it was told not to say.
The failure is helpfulness, not adversarial cleverness. The model already knows plants take in carbon dioxide, and everything it was trained on pulls towards telling someone who is stuck. "Do not reveal the answer" is an instruction competing with that pull, and instructions lose sometimes. The question is not how to word the instruction better. It is what happens when it fails.
Four modes, and only one may say the answer
A single "ask the tutor" box has no rule to enforce, because the request has no shape. One reply has to serve the learner who misread the wording and the learner who has given up. Named modes turn an intention into a parameter, and a parameter can be checked.
- Reformulate — the same question in plainer words, every term, number and option kept. No hint, no strategy, no answer. For the learner who understands the material and not the sentence.
- Hint — one small next step. Hints are numbered and monotonic: hint three is deeper than hint one, meaning more scaffolding, not more of the answer. A later hint must never be a nearer miss.
- Reveal — the only mode permitted to state the answer, and only after an attempt. A decision, not a slip.
- Explain — why the correct answer is correct and where the learner's went wrong, once the answer is on screen.
No-leak guard
A server-side check that runs after the model replies and before the learner sees it. The reply is compared against the question's stored answer key under the rule for the mode requested: a rephrasing and a hint may not contain the answer, a reveal may. Failing does not fail the request — the reply is regenerated once under a stricter instruction, and a second failure is replaced by a safe generic nudge. The guard belongs to the endpoint, not the prompt.
Can an AI tutor give a student the answer?
It can, and most general assistants will, because a request to rephrase or hint is ambiguous enough that a helpful model resolves it towards the answer. Preventing that takes two things a system prompt cannot provide: the correct answer must be absent from the model's context in the modes where it is forbidden, and the reply must be checked against the answer key on the server. Ask which of the two a vendor does.
Ask nicely and you get a request, not a rule
A system prompt is an input to a probabilistic process. It shifts the distribution of replies; it does not bound it. Fine for tone and format, where a failure is a badly worded sentence. Not fine for a rule whose violation ends an assessment, because a reply that leaks looks exactly like one that does not.
The strongest guarantee costs nothing and is usually skipped — in reformulate and hint, do not put the answer key in the prompt at all. The model cannot repeat what it was never given, and that closes the leak no checker can catch, since paraphrasing a supplied answer is likelier than independently recalling the same fact. A hint written without the key is occasionally a worse hint. The two answer-bearing modes still get it.
The check that runs afterwards is a backstop with an honest limit. It normalises both strings and looks for containment. It catches a model that names the answer. It cannot catch a paraphrase, a translation, or a definition in other words. Its value is making the residual failures a small known set.
One detail decides whether this survives a determined teenager: the mode is a parameter the client sends, and the answer key is not. The server resolves both from the block identifier, under the learner's own access rules. A client that lies about the mode gets that mode's rule. A patched browser gets nothing.
The endpoint decides. Reformulate and hint are built without the answer key, checked against it after generation, regenerated once on a failure, and downgraded to a generic nudge on a second failure.
A system prompt saying "never reveal the answer", one free-text chat box, and a filter running in the browser where the learner's developer tools are.
Request { mode: "hint", block: <id> } the client sends a mode, never a key
Server
1 is this caller actually enrolled in this programme?
2 has this learner withdrawn AI-processing consent? -> stop, send nothing
3 resolve the question and the answer key from the block
4 mode is reveal/explain and nothing was attempted? -> stop, send nothing
5 build the prompt
reformulate / hint answer key NOT included
reveal / explain answer key included
6 call the model
7 reformulate / hint: does the reply contain the answer?
yes -> regenerate once, under a pointed corrective rule
still yes -> discard it, return a safe generic nudge
8 a reveal that succeeded -> append-only audit rowQuestion type changes what the rule means
"Rephrase the question" is coherent for a multiple-choice stem and incoherent for a true/false item, because a true/false question is a claim to be judged. Rephrasing a claim collapses into paraphrasing or explaining it, and either can signal the truth value. Asked to simplify The rabbit shared the carrots with his friends, a model tends to answer "can you put this sentence in your own words?" — not the question the learner was set. That type needs a different rule in kind: restate it as an explicit decision between true and false, leaning neither way.
Multiple choice needs its own rule. A restatement may refer to the options collectively — compare the choices given — and may never quote, name or paraphrase an individual one. Singling out an option to discuss it is how a rephrasing becomes a recommendation.
Then there are families with no secret string at all. Ordering, matching, classification and drag-and-drop have relational answers: an arrangement of items the learner is already looking at. A containment check has nothing to compare against and will pass a reply that gives away the whole pairing. There, the prompt rule is the only guard.
Three failures a naive checker makes
- The multi-part answer. Sunlight, water and carbon dioxide leaks the moment a hint names water. Whole-string comparison misses it, so each answer is decomposed on list separators — commas, semicolons, and, or — and each part checked alone. Split on separators only, never on spaces, or the water cycle becomes three harmless words and the check goes quiet.
- The common word. True, false, yes, none, all. "Check whether that holds in every case" is a good hint, and a checker without a stop-list rejects it, retries, rejects it again, and serves a generic nudge. Guards that fire on good replies get switched off.
- The short number. The length threshold that stops common words tripping the guard lets 42 through. Numbers need their own rule: a hint may never state the value, however short.
Why can an AI not simply rephrase a true or false question?
Because a true/false item is a statement, not a request, and the only ways to restate a statement are to paraphrase it or explain it. Both risk signalling whether it is true: a model that softens a false claim or sharpens a true one has answered the question without stating an answer. Present it instead as an explicit choice between true and false, in plainer words, leaning neither way — and select that rule by question type on the server.
Try first, and what counts as trying
Reveal and explain should be unavailable until the learner has put down an answer — not because struggle is virtuous, but because the mark means nothing otherwise, and a learner who reveals first learns the shape of the answer rather than the route to it.
The obvious implementation is wrong. Gate on whether the learner typed something and it works for short answers and numbers and fails for everything else: ordering, matching, multi-select and essay responses do not serialise to a meaningful string, so a learner who genuinely answered is refused and told to try first. Gate on the recorded outcome of the block instead — did this learner answer it. And make the refusal real: no key resolved, nothing sent, a fixed reply in the learner's own language.
A second gate catches a different case. Inside a graded attempt the item's policy may hide results — feedback released manually, or answers never shown — and reveal is refused even after an attempt, so the tutor is not a side door around the release schedule. It cannot replace the first gate: formative practice has no grading policy at all. In Lurno the two are separate for that reason.
Should a learner be able to reveal the answer before attempting the question?
No, and the check belongs on the server next to the answer key rather than in the interface. Enforce two conditions separately: the learner has recorded an attempt at this question, and the assessment's own policy currently allows results to be seen. The first covers unmarked practice, where no policy exists; the second covers a graded attempt whose feedback has not been released. Enforcing only one leaves half the product open.
A reveal is an event, not a silence
When a learner asks for the answer and gets it, the score on that question was produced with the answer on screen. If the only trace is a chat log that ages out, the mark and the circumstance have been separated, and the first anyone hears of it is a disputed result.
Two records, deliberately different. A working log of tutor turns — modes, timings, hint depth — which is teaching data with a retention limit, because a transcript of a fourteen-year-old's confusion is not something to keep for seven years. And an append-only entry, hash-chained so a later edit is detectable, written for successful reveals only: who, which item, which attempt, when.
Reveals only, and the restriction is the design. Auditing every hint rebuilds the transcript you just decided not to keep, and buries the one event that changes how a mark should be read. The attempt itself carries a flag saying the answer was shown, so no later view presents that score as clean. The point is not to catch anybody; it is that a teacher looking at a suspicious mark gets an answer instead of a shrug. Marking is on assessments and the grading queue.
Consent has to remove the tutor, not the label
A learner-facing tutor sends a learner's question and their own wrong answer to a third-party model. In most jurisdictions that needs consent as its legal basis, held as its own record — separate from the organisation's decision to buy an AI feature, and withdrawable without withdrawing from the course.
Withdrawal is where implementations quietly cheat. The check belongs on the server, before the answer key is resolved and before a byte leaves for a provider — not in the interface that hides the button, which stops nothing that calls the endpoint directly. And say so plainly: AI help is off, here is where to turn it back on. Not a spinner that never resolves, and not a quiet downgrade to a canned tutor replying as though nothing changed.
Two details finish the job. Withdrawal must take effect on the next turn, not the next sign-in — anything cached in a session token stays live until that learner signs out, which can be days. And consent governs what is sent, not only what comes back: personal data stripped before the call, the learner's text fenced as data rather than instruction. Those gates are on security.
What happens to the AI tutor if a learner withdraws consent for AI processing?
It should stop, entirely and immediately, and say that it has. The server checks the consent record before resolving the answer key and before calling any provider, so a withdrawn learner's text never reaches a model; the panel shows that AI help is off and points at the setting that re-enables it. Withdrawal applies on the next request rather than the next session, and the rest of the course is untouched — they keep their programme, attempts and marks, and lose one feature.
Before you buy, and the short version
- Is the answer key in the prompt when a learner asks for a hint? If it is, the only thing between the learner and the answer is a sentence of English.
- Where does the containment check run? Open the network tab; if the key is in the response, it is over.
- What happens when the check fails — a retry, a fallback, or a shrug?
- Reformulate a true/false item, then an ordering item. The second is where relational answers walk past a string check.
- Try to reveal before attempting, on an essay and a matching question. That is where attempt detection breaks.
- Is a reveal recorded somewhere immutable, and does the attempt carry the fact?
- Withdraw AI consent for a test learner and ask for a hint. If a call still goes out, the consent screen is decoration.
Name the modes, so there is a rule to break. Keep the answer out of the context in the modes that must not state it — the only guarantee that does not depend on the model behaving. Check the reply against the key on the server anyway, and know which leaks that check cannot see. Change the rule with the question type. Write the reveal down where it cannot be edited. And when a learner says no to AI, send nothing.