Essay 4 of 5 · June 2026

Building a Socratic AI tutor for Singapore secondary math, across three streams

Why each design choice is what it is, and what running it has been like.

In April I started a third project. The first two had taught me what I needed the third to be: Riverside Sec Oral Conversation, the AI oral grader for the language teachers at my school, had given me confidence that a teacher-in-the-loop AI grading flow could run at school scale; and a math grader I had tested but chose not to launch, which I wrote about in the last piece, had made clear that grading and tutoring are not the same product. The third would do tutoring.

Specifically, instead of marking the last line, it would ask about the next one.

That product is called RSS Feedback. I built it in April and May, deployed it in early May, and have been running it with my Sec 3 and Sec 4 Mathematics and Additional Mathematics classes for about six weeks. This piece is what it is, why each design choice is what it is, and what running it has been like so far.

In one sentence: a Socratic AI tutor for Singapore secondary math, built around SEAB syllabuses, that watches students work and asks them probing questions instead of giving them answers. Teachers assign worksheets; students draw their working on an iPad with an Apple Pencil; the AI returns short hints, up to twenty per question. Marks land in SEAB's M / A / B notation. Teachers always have the last word.

Why a Socratic tutor

The argument for the Socratic tutor is one I built up to across the earlier essays. In short: in math, the cognitive moment lives in the working; and the cognitively useful shape of feedback is a question, not a verdict.

Those two arguments are really one. A question keeps the cognitive moment open; a verdict closes it. A tool that asks instead of tells can be submitted to at any point of friction in the working, because what comes back continues the thinking instead of ending it. A tool that tells can only be submitted to once the working is done, because the verdict is the working's end. The principle collapses into a single instruction: ask rather than tell.

Ask rather than tell rules out anything that hands the student a judgement. A correct answer is a judgement. A red cross is a judgement. A written explanation of where the working went wrong is, structurally, also a judgement. The student receives, absorbs, internalises. That is not the cognitive activity that produces a better mathematician. The activity that does is articulating what you were trying to do, reconstructing your own reasoning, noticing your own missteps without being told. The feedback literature calls this the line between outcome feedback (the verdict, the mark) and process feedback (the question, the strategy nudge). The Socratic register is the strict end of process feedback: only ask, never tell.

A teacher in a one-on-one setting can do this. They watch the student work, ask "what are you trying to do here?", listen, redirect with another question, let the student own the breakthrough. A teacher in front of forty students cannot do it for forty students simultaneously. Most of the value the human Socratic tutor produces is locked behind a labour cost that does not scale to a real classroom.

An AI Socratic tutor unlocks that scaling. Each student gets the next question for them, in the moment, addressed to their specific working. The teacher's attention is freed from the work that does not strictly need them, and can land on the work that does. That premise, that the AI does the patient questioning and the teacher does the strategic intervention, is what RSS Feedback rests on.

Snorkl gave the base; where it fell short

I did not invent the AI Socratic tutor pattern. The clearest existing version of it I had seen was Snorkl, an edtech tool. Snorkl's premise is essentially the same as mine: the student works through a problem; the AI asks instead of tells; the teacher reviews. The shape was right. I genuinely considered using Snorkl rather than building anything new, and the early sketches I made for what I wanted owe a real debt to it.

It turned out to be insufficient for my context for three reasons.

First, customisation. Snorkl's question structure, marking shape, and hint language were largely fixed. A teacher could not change the structure of a question, the rubric inside it, or the language the AI used in its hints. For a tool that needed to align to specific SEAB syllabuses and specific stream-level language norms, that was the wrong end of the customisation spectrum.

Second, the marking taxonomy. Snorkl gave each question a single mark from zero to four. SEAB marks differently: it uses an M / A / B taxonomy, where M is the method mark, A is the accuracy mark, and B is independent. Each step in a worked solution can earn one of these; the total for a question is built up step by step from a marking scheme. A 0-4 scale collapses all that detail into a single number and removes the per-step structure that makes formative feedback usable inside the Singapore system.

Third, single questions. Snorkl treated each question as a standalone assignment. That ruled out the use case I cared most about: a student sitting down with a whole past-year weighted assessment paper or prelim paper, working through the questions in order, under timed conditions. Timed paper practice is the bread and butter of preparing for Singapore math exams, and the single-question shape simply could not host it. RSS Feedback runs multi-question assignments end to end, with optional timing at the assignment level.

These three kept Snorkl from being the answer for my context. They are also three specific reasons RSS Feedback exists as its own thing rather than a wrapper around Snorkl.

What I built instead

RSS Feedback is the version of the Socratic tutor I built around those three constraints, plus the broader constraints of running a real classroom tool at my school.

A teacher uploads a worksheet, usually a PDF or a phone photo. The system uses Mathpix to extract text and Claude to partition the page into individual questions. Each question gets cropped to its own image, given a draft per-step marking scheme in SEAB's M / A / B notation, and a total mark allocation. The teacher reviews the AI's draft: editing the question text, regenerating the worked solution, adjusting per-step marks, reordering questions. When the teacher is satisfied, they publish the assignment to a class.

The student opens that assignment on an iPad. Each question has its own page with the question image at the top and a drawing canvas below. The student writes their working with an Apple Pencil. The canvas is tuned to defer to the Pencil's pressure curve and ignore stray finger touches, because forty students writing under classroom conditions will find every input bug there is. If a student prefers pen and paper, they can upload a photo of their physical working as the canvas background and annotate on top of it.

Then they press Submit Answer.

That press fires the Socratic engine, which is the heart of the product. The system takes the student's drawing, the AI-generated worked solution, the per-step marking scheme, the SEAB syllabus context for the subject and stream, and Claude. It returns either a celebration (if the answer is correct) or a short hint of one to three sentences nudging the student in a direction. The student reads, returns to the canvas, writes more, presses Submit again. Up to twenty hints per question. After that the button changes to Save Work and the student carries on, with the teacher reviewing later.

The hints are short, conversational, and never reveal the correct value. They may name the relevant concept or theorem, but they never write out the formula itself. They ask. The system prompt that drives them is a multi-page document of "do not give the answer" rules with worked examples of how to redirect a stuck student with a question instead of a statement. I will quote the load-bearing rule in the next section.

The SEAB alignment is the deepest piece of the substrate. The product carries 89 separate syllabus blocks compiled from the publicly available 2026 SEAB syllabus PDFs, indexed by subject and stream. For math specifically, the substrate supports Mathematics and Additional Mathematics across all three streams: G1, G2 and G3. Each block carries the subject's assessment objectives, paper structure, content domains, and the marking conventions SEAB sets out in the same documents. The hint engine reads the relevant block before generating a hint, and the AI's tone shifts by stream. For G1 the rule in the prompt is simple, clear language and very small steps; for G3 it is standard exam-paper language, concise and precise. A G1 student writing a working misstep sees a different hint than a G3 student writing the same misstep.

The operational shell is the smaller surface but, in some ways, the most useful piece of the build. Authentication is domain-locked to two school-issued email domains: one for teaching staff, one for students. The system maps the domain to a role on sign-in. Any other domain is rejected. That single rule is the entire authentication policy. It removed a whole class of identity headaches I had been bracing for and let me focus the build elsewhere.

Class progress is surfaced on a dashboard: one icon per student per assignment. Done, in progress, needs review, dormant. A teacher of forty students can walk into the room on Monday and know who to talk to first.

The substrate also supports the broader SEAB subject taxonomy, more than thirty subjects across the same three streams. I have not scaled beyond math yet. The wider rollout is not the work this piece is about. The work this piece is about is the version that runs today, on math, with my four Sec 3 and Sec 4 Mathematics and Additional Mathematics classes.

The Socratic rule that does not relax

The system prompt driving the hint engine is the longest piece of design I have written for any of my products. It is a few thousand tokens of "do not give the answer" rules, with six labelled WRONG / RIGHT exemplars, per-stream language guidance, math notation conventions, and worked examples of how to redirect a stuck student without revealing what they are stuck on.

The most emphatic section of the prompt is a single rule, written in the strongest terms I could give it. Paraphrased:

Do not quote the marking scheme's expected value for any step the student has not yet earned. This applies even when the student is on attempt five or six and seems stuck. The rule does not relax with nudge count.

I insist on that rule for a reason. The natural pressure on an AI tutor, when a student has tried five times and is still wrong, is to soften: to give them a partial answer, to drop a hint that is really a tell, to write out the formula and let them substitute the values. Every model I have tested defaults toward this softening eventually if left to its own judgement.

I do not let it. The hint engine is built to keep refusing the give-away even when refusing feels unkind. If the student has tried five times and is still wrong, the hint is still a question. It might be a more pointed question, a smaller question, a question that breaks the next step into two. But it does not become an answer.

The reason is the second pedagogical claim from the earlier piece: a student who answers a question has done work that a student who reads an answer has not. The first walks away with a process; the second with a recall. At attempt five, the temptation to deliver a recall is enormous. Resisting that temptation is what makes the tutor a tutor and not a marker with a delay.

This is the product's whole bet, encoded in one rule.

Running this at school, defensively

I have not had a production incident yet. I have built as if I will.

The reason is that I know what running an AI-graded tool at school scale costs when it goes wrong. The oral grader has taught me that backups need to be backups, not promises; that a bug in a marking pipeline can reach a class in a single push; that the cheapest thing about an AI grading system is the API call and the most expensive is the trust the school places in it.

So RSS Feedback runs with: a daily error digest summarising what failed; a weekly usage digest covering the platform snapshot, per-class activity, and AI spend broken down by route; cost reconciliation against the AI provider's billed total, so I know if the in-app aggregate is drifting; point-in-time recovery on the Firestore project plus scheduled daily backups with fourteen-day retention; Storage object versioning on every uploaded file; a Durable Object rate limiter capping the request flow well within the model's tier ceiling, so a sudden class burst does not start 429-ing students; a per-student daily spend cap, beyond which the student gets a polite "try again tomorrow" and the teacher gets a note; and a 24/7 cron error monitor that pages me if any of the above starts misbehaving.

None of this code was load-bearing in the first six weeks. It was all written in anticipation of weeks that have not arrived yet.

The per-nudge cost is the other place I have spent disproportionate engineering energy. The original feedback prompt was expensive per call. In mid-June I restructured it into three blocks: a static core, a per-(subject, stream) syllabus block, and a per-question suffix. The static core and the syllabus blocks are heavily cached across calls; only the per-question suffix changes per call. That restructure dropped the per-nudge cost dramatically. Across a class working through a full assignment, the savings on a single worksheet are real money.

A second optimisation, shipped the day before, was a solution-reuse cache: when two questions across two assignments share text, the AI-generated worked solution is computed once and reused. A sizeable share of recent questions turned out to be duplicates of earlier ones; the cache turns each duplicate from a real cost into a near-zero one.

These are not the kinds of optimisations I love writing. I write them anyway because the alternative is hundreds of dollars a month in waste, and a tool whose unit economics get worse as it grows is a tool that cannot scale.

Six weeks in

The product has been live with my Sec 3 and Sec 4 Mathematics and Additional Mathematics classes since early May. That is one hundred and forty-three students across four classes, six weeks of use, more than a hundred questions live on the platform, and many hundreds of hints sent.

What I cannot tell from six weeks is whether it is actually making my students better at math. I can tell that they are working through more questions than they were before. They reach for the AI hint readily, sometimes before reaching for a friend or a teacher, and I am still figuring out how to feel about that. The friction of starting an extra question is much lower than it used to be, when starting meant a new sheet of paper and an attention rotated away from the homework already on the desk. None of that necessarily produces a better mathematician. It might. I do not know yet.

The next piece in this series will be about what I have actually seen from inside my own classroom in the six weeks of running this with students across four classes who did not ask to be the first ones on a new tool. The piece after that, if the data still tells a coherent story by then, will be the one about whether they are learning more.

For now, what I can tell you is that the tool is running; the substrate is built for the scale it has not yet reached; the cost stack is held together by aggressive prompt caching and per-student daily caps; and the Socratic rule has not been relaxed in any hint, at any attempt count, for any student.