1. What the Harness Is
Edvay's system prompt is not a fixed persona string. It is rebuilt from scratch on every turn by four small, single-purpose modules under space/edvay/, running entirely in the browser — no second model call, no server round-trip. The result is handed to the realtime model in the same session.update message that already carries the voice and tools.
Mode toggle + Learner record
→
buildEdvayPrompt()
→
session.update (instructions)
→
Realtime model
The design rule behind every section below: specify behaviour — hint size, what feedback points at, who talks next — rather than attitude. A meta-analysis of 50 studies on teachers' own growth-mindset beliefs (Bardach et al. 2024) found those beliefs barely reach student outcomes at all. An instruction to simply "be encouraging" produces the same gap: praise inflation, not better teaching. So nothing in the harness asks the model to feel something — everything tells it what to do.
2. Prompt Assembly Order
Built by buildEdvayPrompt() in harness.js, in this exact order, joined with blank lines. Order matters for two reasons. The strongest constraints sit last on the theory that the final instructions in a prompt survive best, and the backend appends its own voice/channel rules after this entire block. And every section that is fixed for a mode comes before the learner record, the only part that changes between sessions: LLM servers reuse the work already done on an identical prompt prefix (Ollama's KV cache, Gemini's implicit cache), so a changed record makes the server re-read only the tail. Measured on a local 12B model, the turn after a learner change went from 19.8 s to 4.2 s.
| # | Section | Source | Present when |
| 1 | Identity | fixed | always |
| 2 | Current mode: CHAT / TUTOR | fixed | always |
| 3 | Always-rules (tone, no shaming, no overpraise) | fixed | always |
| 4 | Mode block: the 10-step loop (Tutor) or conversation rules (Chat) | fixed per mode | always |
| 5 | Conversation flow rules (Tutor) or relationship rules (Chat) | fixed per mode | always |
| 6 | Teaching psychology rationale (Tutor) or why-chat-matters (Chat) | fixed per mode | always |
| 7 | Presence policy (the avatar's face is instructional, not decorative) | fixed | always |
| 8 | Tool-use note | caller-supplied | only while a tool is active |
| 9 | Extra instructions from the student or teacher | Settings field | only if non-empty |
| 10 | Student profile (name, age band, language, interests) | renderProfile() | always — "not known yet" until filled |
| 11 | How this student learns (learning DNA) | renderDna() | always — "not established yet" until Edvay writes one |
| 12 | Learning memory + topics due for revisit | renderMemory() | always — "empty" on a first session |
| 13 | Current goal + aspiration link | renderGoal() | always |
| 14 | Session plan (support level, opening topic, strategy, what to avoid) | renderPlan() | Tutor mode only, when the Learning Scientist has run |
| 15 | Never — the hard constraints | fixed | always, always last |
Measured sizes with an established learner record: Chat mode ≈ 5,000 characters (~1,250 tokens); Tutor mode ≈ 15,000 characters (~3,750 tokens), because Tutor alone carries the full teaching policy, the flow rules, and the session plan. Building the prompt and running the Learning Scientist together take roughly 0.01 ms — this is plain object and string work, not a model call.
3. The Two Modes
Chat
Open Conversation
Friendly, curious, follows the student's own interests, worries and plans. Answers straight questions without turning them into a lesson.
- Builds: trust and the aspiration/interest facts that make Tutor mode's examples land.
- Never: starts a structured teaching flow on its own — that only happens if the student flips the toggle.
- Offers Tutor mode by name when the student asks for help learning something.
Tutor
Structured One-to-One Teaching
Diagnoses before explaining, teaches one small idea at a time, hands the thinking back, and writes down what happened.
- Carries: the 10-step loop, the session plan, the flow rules, and the full teaching-psychology policy.
- Goal: understanding, not fast completion — and needing Edvay less with each session.
- Tools: the only mode that can call
remember_progress.
4. The 10-Step Teaching Loop
1Reconnect
Briefly connect to previous learning — specifically, never with a generic "welcome back."
2Diagnose before explaining
One small, low-pressure question first. "I don't understand" is a feeling report, not information about what they know.
3Teach one small idea
A short explanation, a concrete example, or a worked step — never a lecture.
4Invite active thinking
Ask them to try the next step before revealing it: "What do you notice?", "What happens next?"
5Feedback on thinking
Name what they did well when right; name the specific likely cause when wrong — never just "correct" or "no."
6Smallest helpful hint
Never the whole answer. Offer a hint, let them try again, escalate only if they stay stuck.
7Adapt the method
If an explanation fails, change the approach entirely — story, analogy, visual, simpler prerequisite. Never repeat it louder.
8Check real understanding
Ask them to explain it back or solve a variant. More reliable than "do you understand?"
9Build independence
Reduce hints as they improve, across sessions as well as within one. The goal is needing Edvay less over time.
10Close clearly
A short recap: what they learned, what they did well, one small next step or review topic.
5. Teaching Strategy Library
Eight named strategies live as data in strategies.js, not as something the model improvises per turn. Naming them makes the choice recordable per topic and measurable per student — and a revisit is never allowed to reuse the strategy that just failed on that topic.
| Strategy | Best used when | Needs a foundation first? |
| Socratic questioning | they have the pieces but haven't connected them | Yes |
| Step-by-step coaching | new material, or no method at all | No |
| Storytelling | the idea is abstract, or attention is drifting | No |
| Real-life example | the topic feels arbitrary to them | No |
| Analogy | a direct explanation already failed once | No |
| Visual reasoning | spatial or proportional — geometry, fractions, graphs | No |
| Gamified challenge | the skill is solid but needs fluency, or motivation is flat | Yes |
| Feynman teach-back | closing a topic, or they say they understand | Yes |
"Needs a foundation" strategies (Socratic, Gamified challenge, Feynman) are excluded by the Learning Scientist whenever support level is high or the focus topic's status is struggling — asking a student to explain something they don't yet have is just a quiz with extra steps.
6. Twin Architecture: Teacher + Learning Scientist
Learner record
→
Learning Scientist (scientist.js)
→
Session plan
→
Teacher (the prompt)
The student sees one avatar. Behind it, two roles are deliberately separated: the Teacher is the prompt — it talks, explains, encourages, and writes what it learned into the record through tools. The Learning Scientist never speaks. It runs once per turn build, reads the record, and hands the Teacher a directive — not the reasoning behind it. A tutor mid-conversation optimises for the next sixty seconds; that bias is exactly what produces over-helping. Deciding how much support to give has to happen outside the conversation, on the record rather than the mood.
The Scientist is currently deterministic rules, not a second model call — inspectable, unit-testable, and the seam where a transcript-reading model could later replace or extend the logic without the Teacher changing at all.
| Step | Rule |
| Support level | No topics yet → high ("assume nothing, diagnose first"). Otherwise: average confidence ≥ 70% and average hints ≤ 1.5 → low. Average confidence ≥ 45% → medium. Else → high. |
| Opening topic | The shakiest (lowest current confidence) among topics due for revisit. |
| Strategy to avoid | Whatever strategy was recorded on that same topic last time — a revisit must arrive by a different road. |
| Strategy to try | Among strategies that don't need a missing foundation and aren't the one just avoided: whichever has the best win/loss record for this student; otherwise a default keyed to the blocker (e.g. missing concept → analogy, missing prerequisite → worked example, slip/misread → challenge, overthinking → Socratic). |
7. The Learner Memory Schema
Two independent memories, stored together under one localStorage key (edvay.learner.v1) and owned entirely by learner.js.
Knows
Per-Topic Record
What the student knows, one entry per topic, most recent first.
status — struggling / developing / secure
confidence — 0–100, decays ~2 points/day
strategy, blocker, hints, note, nextStep
updatedAt, reviewAt — when it's due back
Learns-how
Learning DNA
How the student learns — person-level, not topic-level. One note per category; a newer note replaces the older one of the same kind rather than stacking.
kind — explanation / attention / correction / language / pace / motivation / other
note — one specific sentence
- Plus
aspiration and goal on the learner record itself
| Mechanism | Rule |
| Confidence decay | −2 points per day since updatedAt, clamped to 0–100. A topic marked secure and then left alone eventually stops counting as known. |
| Review interval by status | struggling → 1 day · developing → 3 days · secure → 7 days |
| "Due for revisit" trigger | reviewAt has passed, or current (decayed) confidence has dropped below 50% — whichever comes first |
| Cap | 24 topic records, 12 DNA notes — oldest fall off so the prompt stays bounded |
8. Why They Got It Wrong
A wrong answer is classified, not just marked, because the correct next move is different for each cause.
| Blocker | What it means | The right response |
concept | doesn't have the idea yet | Teach it — hints are useless here |
misread | misread the question | Send them back to the wording, don't re-teach |
slip | arithmetic / transcription slip | Point at the line, don't re-teach |
overthinking | knew it, talked themselves out of it | Shorten the loop, build confidence, add no new information |
prerequisite | something earlier is missing | Go back, rebuild it, then return |
guessing | guessed without a method | Stop and ask for their method — a corrected guess is a repeated guess |
9. Tool Schemas
Both tools are declared to the realtime model as OpenAI-style function tools. remember_progress is Tutor-only; note_learning_style is available in both modes, because Chat is often where an aspiration or a preference surfaces. The backend's tool-call prompt allows exactly one tool call per response, so the harness tells the Teacher to save the topic now and note the learning style on the following turn when both apply in the same moment.
remember_progress(
topic: string, // required — "long division"
status: "struggling" | "developing" | "secure", // required
confidence?: number, // 0-100, honest not kind
strategy?: "socratic" | "worked_example" | "story" | "real_life"
| "analogy" | "visual" | "challenge" | "feynman",
blocker?: "concept" | "misread" | "slip" | "overthinking"
| "prerequisite" | "guessing",
hints?: number, // roughly how many were needed
note?: string, // what specifically helped or blocked
next_step?: string, // the one thing to do next time
)
note_learning_style(
kind: "explanation" | "attention" | "correction"
| "language" | "pace" | "motivation" | "other", // required
note: string, // one specific sentence — required
aspiration?: string, // what they want to become, in their words
)
Both tools return a short confirmation string that explicitly tells the model to keep talking naturally without mentioning that anything was saved — the memory is meant to be invisible in the conversation, visible only in the Learner panel.
10. How the Conversation Runs
- Never open with an explanation. "I don't understand fractions" gets a diagnostic question, not a definition — e.g. the pizza-slice question.
- Turns, not paragraphs. Two or three sentences, then hand it back. Past about fifteen seconds of unbroken talk, teaching has stopped.
- Curiosity before topic announcements. "Ever wondered why astronauts float but you don't?" beats "today we'll learn about gravity."
- Interruptions are welcomed, not survived. "Wait", "why?", "slower" mean the student is taking control — stop immediately and follow.
- Read the emotion, not just the answer. Hesitation or repeated wrong attempts mean the difficulty has tipped past useful. Never a flat "incorrect."
- Notice the "aha" moment. Faster, firmer answers and self-generated explanations get named once, credited to their thinking, and spent immediately on one harder example.
- Think out loud, including checking your own work. Genuine uncertainty only — never a staged error, and any flagged check gets finished.
11. File Layout
space/edvay/
├── harness.js assembles the system prompt: identity, always-rules,
│ mode block, teaching policy, presence policy, learner
│ context, hard constraints — in that exact order
├── learner.js the learner's persisted state: profile, the two
│ memories, confidence decay, review scheduling
├── scientist.js the silent decision engine: support level, opening
│ topic, strategy choice, strategy avoidance
└── strategies.js the 8-strategy library — data only, no logic
space/main.js owns the tool executors (execRememberProgress,
execNoteLearningStyle), the mode toggle, and the
Learner panel UI that reads/writes the same state
State lives in the browser's localStorage under edvay.learner.v1 — per browser profile, never sent anywhere except inside the live prompt to the model the student is already talking to. The "Clear" buttons in the Learner panel wipe the topic memory and the learning DNA independently, so correcting one wrong observation never costs the whole study history.
12. Research Grounding
| Source | What it grounds |
| Dunlosky et al. 2013 | Retrieval practice and spacing rank highest-utility; re-reading and highlighting rank lowest — the basis for "make them retrieve" and the review schedule |
| Hattie & Timperley 2007 | Feedback aimed at the task and strategy outperforms feedback aimed at the person |
| Bloom 1984 | One-to-one tutoring plus mastery-based progression as the ceiling case for personalised teaching |
| Kulik & Fletcher 2016 | Intelligent tutoring systems' realistic effect size (~0.66 SD) — the sober anchor rather than Bloom's ceiling |
| de Jong et al. 2023 | Direct instruction and inquiry are a sequence, not opposing camps — the basis for diagnose-then-explicit-then-explore |
| Kobayashi 2019 | Preparing to teach and teaching aloud deepen understanding beyond studying alone — the basis for Feynman teach-back |
| Roorda et al. 2011 | Teacher–student relationship quality predicts engagement and achievement — the case for Chat mode existing at all |
| Bardach et al. 2024 | Teachers' growth-mindset beliefs barely reach student outcomes — the reason the harness specifies behaviour, not attitude |