Inspiration

Every learning tool gives you a plan. A course outline. A study roadmap. A curriculum. And then it never changes again — no matter what happens to you while you follow it. You get lost, and the map stays the same.

Tools that do test you — including the best of them — report a score and stop there. The quiz measures. The plan does not move.

I teach cooking science. My students know things they cannot explain, and the textbook explains things they cannot recognise. I wanted an agent that could sit between those two vocabularies and keep rebuilding the route as it learned who it was talking to.

What it does

Wayfinder takes whatever material you actually have — a PDF chapter, a photo of handwritten notes, a voice memo you never played back — mixed and unsorted. It reads across all of it at once and finds where your words and the book's words describe the same thing:

"judge doneness by how it pushes back"  ⇄  Contraction ranges of myosin and actin
"if it splits, add another yolk"        ⇄  Lecithin as a surfactant

Then it builds a directed graph — not a list — where each step knows what it depends on and why it sits where it sits.

And then the plan keeps moving. Three different signals rewrite it:

Signal What it reads Example
What you say your own words "this part is too hard"
What you reveal quiz answers, forgotten cards you missed 3 specific points
Where you head pace vs deadline, mastery across the path you are 40% over your time budget

The second row is the point. Grading runs on Gemma 4 and does not return a score — it returns which ideas you missed. That alone is enough to split a step into an easier entry point and the harder part behind it.

Because saying "this is too hard" requires knowing that it is. Most people don't know yet. Their answers know first.

The same loop runs on time itself: forget two spaced-repetition cards and the step you already finished is promoted back to the front of the path. Not because you asked. Because forgetting is evidence too.

When the structure changes, the screen names the evidence:

STRUCTURE CHANGED
from your answers — before you said a word
Split into smaller steps
9 steps → 10 steps

How I built it

Four layers, one mutation engine.

  • L1 Dialogueingest_multimodal reads every format at once, then asks back only what the materials cannot answer.
  • L2 Logicmutate_graph() is the single mutation engine. All three signals feed it. Every mutation is a schema-validated patch, checked for broken references and cycles on the merged graph before it is written. A failing patch is repaired, never written.
  • L3 Knowledge — a vocabulary book built from the learner's own material, plus Firestore-native KNN retrieval. Every generated step is anchored back to a real quote — matched in code, not merely requested in a prompt.
  • L4 Output — the agent decides the medium per step. Not by unit price: a relationship is a diagram; a change over time is a clip. To choose video it must state what a still cannot convey. If it cannot, it does not get video.

Google ADK on Cloud Run, stateless. All state lives in Firestore, including the 1536-dimension vector index — I rejected Vertex AI Vector Search on cost, because an idle endpoint bills whether or not anyone is learning.

The browser subscribes to Firestore through SSE, so the screen only redraws when Firestore actually changes. The agent cannot claim a change it did not make.

Grading falls back across three backends — local Gemma 4 → Vertex MaaS → Gemini — and the screen shows which one actually answered, not the one I hoped would.

Every paid call reserves budget before it runs, per learner and overall, in a Firestore transaction. A cost ledger, not an afterthought.

Challenges I ran into

The agent lied in its own history. When I let the model pick the mutation trigger, it wrote "the learner said it was hard" for mutations nobody had spoken about. Speech and observed evidence now live in separate prompt sections, and the trigger is set from the caller's fact, not the model's choice.

Two gates disagreed. The media-planning layer decided a hands-on step needed video; a much older type-based rule inside the generator rejected it and returned 500. I had built the deciding layer and left the old rule in place. Judgment now lives in exactly one module.

Generated media evaporated. Diagrams and illustrations were written to the container's local disk. With min-instances=0, a few idle minutes wiped them — and because generation is metered, the learner would be charged again for the same diagram. Media now persists to Cloud Storage with local disk as a cache in front.

The product's key moment was invisible. The mutation — the whole thesis — showed up as a step counter ticking from 9 to 10 and one line of 12px text. I found this by looking at recorded frames, not by reading code. The map now dims, the changed steps glow, and the panel names the evidence.

Accomplishments that I'm proud of

The loop is genuinely closed. The learner does not have to diagnose themselves. Answering a comprehension check badly — and saying nothing else — is enough to change the plan, and the change is explained rather than silently applied.

And the honesty constraints held: the screen is driven only by database writes, the trigger recorded in history is a fact rather than a guess, and every paid call is metered before it runs.

What I learned

Inspecting rendered frames — not trusting "it completed" reports — is what found five real defects. Every one of them passed its tests.

And a design rule I now believe: a condition that assumes it will be resolved will run away when it isn't. My checkpoint layer kept trimming the curriculum because trimming did not fix the deadline overrun. It needed a cooldown, not a better threshold.

What's next for Wayfinder

Per-learner cost caps are in place; the next step is charging generation to the learner (in-app credits or bring-your-own-key) so the system can be handed to someone other than its author without the author paying for their study.https://github.com/studioso-tech/curricushift-ai

Built With

Share this project:

Updates