How we designed Continuum — an AI tutor that remembers students, adapts its teaching strategy, and improves over time
Most AI tutors are good at answering questions. Very few are good at remembering the student.
That gap became the core idea behind Continuum, the project we built for a hackathon. We didn’t want another tutor that starts from zero every session and treats every conversation like it has never seen the learner before. We wanted something closer to a real teacher: a system that could remember past mistakes, notice patterns, adapt explanations, and eventually stop treating old misconceptions as active once the student had clearly improved.
In short, we wanted to build an AI tutor with a memory lifecycle.
The challenge, of course, was that we had to do it in hackathon conditions limited time, limited scope, and no room for building features that looked cool but didn’t actually strengthen the core idea. So instead of trying to build a massive platform, we focused on the smallest version of the product that could still prove one thing convincingly:
Continuum is not just an AI tutor. It is an AI tutor that remembers, recalls, improves, and forgets.
This post is a breakdown of how we structured that build across four days using Cognee as the memory layer, FastAPI for the backend, and an LLM-driven tutoring loop on top.
The core idea behind Continuum
Before getting into the build process, it helps to define the product in one sentence.
Continuum is a memory-driven AI tutor designed to learn how a specific student learns over time.
Instead of treating every tutoring session as a blank slate, the system is built around four memory operations:
Remember: store student interactions, answers, misconceptions, and strategy outcomes
Recall: retrieve relevant past context before teaching the next concept
Improve: periodically synthesize memory into better teaching preferences and mastery insights
Forget: remove outdated misconceptions once the student has clearly overcome them
That lifecycle became the backbone of the entire architecture. Everything else curriculum, tutoring, grading, dashboards was built around making those four operations meaningful and visible.
Why we planned the build day by day
Hackathons punish vague architecture.
If you try to build “an AI tutor with memory” as one giant fuzzy idea, you end up with half-working services, no clear demo story, and no time to debug the one thing that actually matters. So we broke Continuum into four days where each day unlocked the next:
Day 1: prove memory works and centralize the lifecycle logic
Day 2: build the curriculum layer and the first tutoring loop
Day 3: let the tutor learn from student answers and adapt its strategy
Day 4: make the system’s learning visible through a dashboard and timeline
That order mattered a lot. We didn’t want to build tutoring logic on top of an unverified memory system. We didn’t want to build a dashboard before there was meaningful memory data to show. And we definitely didn’t want to spend hours polishing UI if the tutor itself couldn’t demonstrate continuity.
Day 1 — Build the foundation before building the tutor
The first day was dedicated to one thing above all else: making sure Cognee actually worked before we built on top of it.
It sounds obvious, but it’s one of the easiest mistakes to make in a hackathon. You install a tool, assume the integration is fine, start writing business logic, and then discover two days later that your memory pipeline isn’t behaving the way you thought it was. We wanted to avoid that entirely.
So before writing any real tutoring features, the first task was to run a real local memory test. We created a fake student interaction, stored it through a “remember” call, and then issued a “recall” query against it to confirm that the returned context actually made sense. Not just “it didn’t crash,” but “the memory is being stored and retrieved in a way that would be useful to a tutor.”
That one-hour verification step was probably one of the highest-leverage decisions in the whole project. It meant the rest of the architecture could be built with confidence instead of guesswork.
Creating the Memory Lifecycle Service
Once Cognee was verified, the next move was to build what became the heart of Continuum: the Memory Lifecycle Service.
Rather than letting every part of the backend talk to Cognee directly, we created a single centralized Python module that owned all memory interactions. This module exposed a clean set of functions:
remember()
recall()
improve()
forget()
We also added a logging utility that recorded every lifecycle event with a timestamp and a trigger reason.
This ended up being one of the best architectural decisions in the project. It gave us:
A single place to debug memory behavior
If recall returned bad context or forget wasn’t firing correctly, we knew exactly where to inspect.
A single place to instrument for the demo
Since every memory operation passed through one module, it became easy to surface lifecycle events in the UI later.
A clean boundary for the rest of the backend
Other services didn’t need to know anything about Cognee internals. They just imported the lifecycle module.
Even in a hackathon setting, centralizing memory logic paid off immediately. It kept the architecture understandable and gave us a strong “Best Use of Cognee” story right from the start.
Setting up the FastAPI skeleton
With memory in place, we created the FastAPI project structure so the other services had a home. This wasn’t the day for building lots of endpoints; it was about creating the skeleton — folders, routers, and a simple health-check route — so the backend was ready to grow cleanly over the next three days.
By the end of Day 1, the flashy parts of Continuum still didn’t exist. But the most important part did: we had a working memory layer and a backend structure built around it.
Day 2 — Teach the tutor what to teach
With the memory infrastructure ready, Day 2 shifted from “can the system remember?” to “can the system actually tutor?”
To make that happen, we built two pieces: a Curriculum Service and the first version of the Tutoring Engine.
Keeping the curriculum intentionally small
For the hackathon, we made a deliberate scope decision: the curriculum would be small, fixed, and carefully chosen.
Instead of trying to support multiple subjects or ingest a giant knowledge base, we created a compact syllabus — roughly 10 to 15 concepts in a single domain, such as high-school algebra or basic Python programming. Each concept included its prerequisite relationships in natural language.
That dataset was ingested into Cognee as a shared curriculum graph. Unlike student memory, which evolves constantly, the curriculum itself stays stable. It doesn’t belong to one student; it belongs to the tutoring system as a whole.
Once ingested, we tested it by asking recall-style questions such as:
Which concepts depend on loops?
What should a student know before solving linear equations?
What comes after variables and expressions?
As soon as those queries worked, the curriculum side was effectively complete. We didn’t need it to be huge; we just needed it to be structurally meaningful enough to support tutoring decisions.
Building the first tutoring loop
The more important part of Day 2 was the Tutoring Engine Service, which acted as the orchestrator of the learning loop.
Its job was simple in concept but powerful in practice:
Accept a student ID and a current concept
Call recall on that student’s memory to surface weak areas, past struggles, or relevant misconceptions
Consult the curriculum graph to understand where the concept sits in the learning path
Use both of those inputs to decide what to focus on
Ask the LLM to generate a tutoring question
At this stage, the teaching strategy itself was still hardcoded. That was intentional. We didn’t need adaptive strategy selection yet; we just needed the tutor to generate a reasonable question using student memory and curriculum context.
The output of the tutoring engine was a payload containing:
the generated question
the concept being covered
the teaching style used
Most importantly, we wired it to a real API endpoint by the end of the day. That gave the frontend something concrete to call and turned the tutoring loop into a real, testable part of the system.
By the end of Day 2, Continuum could do something meaningful: it could look at a student’s past context, look at the concept graph, and generate a targeted tutoring prompt instead of a generic one.
Day 3 — Make the tutor learn from the student
By Day 3, Continuum could ask questions. What it still couldn’t do was learn from the answers.
That changed once we built the grading, misconception, and strategy-selection pipeline.
Grading answers and storing real learning signals
The first service we added was an endpoint that accepted a student answer and sent it to the LLM for evaluation.
The LLM’s job wasn’t just to mark the answer correct or incorrect. If the student was wrong, it also had to classify the type of misconception in plain language.
That distinction mattered a lot. “Wrong answer” is not useful memory by itself. But “confused variable assignment with comparison” or “used the right formula with the wrong sign convention” is the kind of information that actually helps a future tutoring session.
Once the grading result came back, the backend called the Memory Lifecycle Service’s remember function and stored the full interaction:
concept
student answer
correctness
misconception type, if any
teaching strategy used
At that point, memory was no longer storing abstract test data. It was storing real tutoring interactions.
Strategy selection: moving from static tutoring to adaptive tutoring
Once we had a few interactions in memory, we could build the Strategy Selection Service.
This service looked at a student and a concept type, queried memory for past strategy performance, and then selected the next teaching style based on what had actually worked.
For example, if a student consistently responded better to analogy-based explanations than direct conceptual prompts, the tutor could start favoring that style. If step-by-step decomposition worked better for one topic than another, that could influence the next question generation call.
This is where Continuum started to feel less like “LLM + memory” and more like a real adaptive tutoring system. The tutoring engine was updated so it no longer used a hardcoded teaching strategy; instead, it requested the current best-fit strategy from the strategy service before generating the next question.
Adding improve and forget triggers
The last major piece of Day 3 was implementing the improve and forget lifecycle triggers.
Improve
We configured improve to fire automatically after every five student interactions. The idea was that the system should periodically step back and synthesize what it had learned so far:
Which misconceptions keep recurring?
Which teaching strategies are working best?
Which concepts appear stable and which still look shaky?
We also exposed improve as a manual endpoint for demo purposes. That meant we could trigger it live during the pitch and visibly show the system “updating” its understanding of the student.
Forget
The forget trigger represented something equally important: recognizing when a student has genuinely moved past a misconception.
We defined a simple rule for the hackathon version: if a concept that previously had a misconception attached to it was answered correctly three times in a row, the system would mark that misconception as resolved and trigger a forget event.
This mattered because a good tutor shouldn’t just remember failures forever. It should also know when to stop treating an old weakness as current truth.
By the end of Day 3, Continuum had crossed a major threshold. It wasn’t just storing student history anymore — it was using that history to adapt teaching behavior and update its internal model of the learner.
Day 4 — Turn the memory system into something visible
A memory-driven system is only compelling if you can actually show the memory doing something.
That made Day 4 all about visibility, polish, and demo readiness.
Building the dashboard aggregation endpoint
The first feature we added was a Dashboard Aggregation endpoint. This endpoint called the memory layer to assemble a student-facing snapshot of learning state, including:
mastery levels per concept
currently active weak areas
preferred teaching strategies by concept
recent tutoring outcomes
The goal wasn’t just to return raw memory entries. It was to convert memory into something interpretable — a structured summary that the frontend could turn into a meaningful dashboard.
Building the session timeline
Next, we added a Session Timeline endpoint that returned a chronological list of lifecycle events, especially every time remember, improve, or forget was triggered.
This became one of the most important pieces of the demo.
Why? Because it made Continuum’s “self-improving tutor” claim visible. Instead of saying “trust us, memory is happening behind the scenes,” we could show a real timeline of events:
a misconception being remembered
a strategy pattern being improved
an outdated weakness being forgotten after repeated correct answers
That timeline turned the memory lifecycle from an invisible implementation detail into a product feature the judges could actually see.
Running full end-to-end sessions
The rest of Day 4 was spent doing something that often gets neglected in hackathons: running the full flow with real interaction data instead of mock payloads.
We simulated multiple student sessions, intentionally answered some questions incorrectly, corrected them later, triggered improvement cycles, and watched whether the dashboard and timeline changed in the way we expected.
This is where a lot of hidden issues tend to surface:
recall not returning enough useful context
misconception labels being inconsistent
strategy selection not changing when it should
frontend views failing to reflect lifecycle events correctly
By the time demo prep started, the goal was not “every feature exists.” It was “the core story works end to end.”
And the story was simple: the tutor remembers what happened, changes how it teaches, and updates its view of the student over time.
What made this approach work
Looking back, the four-day structure worked because it respected dependency order.
We didn’t try to make the tutor adaptive before memory was reliable.
We didn’t try to build dashboards before we had lifecycle data worth showing.
We didn’t try to support a giant curriculum when a small concept graph was enough to prove the idea.
Each day ended with a meaningful checkpoint:
Day 1: memory works and lifecycle operations are centralized
Day 2: the tutor can generate questions using memory + curriculum context
Day 3: student answers change future teaching behavior
Day 4: the learning process becomes visible and demo-ready
That progression kept the project grounded. Instead of trying to build everything at once, we kept asking a more useful question:
What is the smallest next layer that makes the core idea more real?
Lessons learned from building Continuum
Building Continuum in a hackathon taught us a few things that go beyond this specific project.
- Verify your critical dependency on Day 1
If your entire product depends on memory, don’t “assume the memory layer is probably fine.” Test it immediately with a real workflow.
- Centralize the part of the system you’ll need to explain
The Memory Lifecycle Service wasn’t just useful for code organization. It also made the product easier to reason about, easier to debug, and easier to explain to judges.
- Small datasets are fine if they prove the concept well
We didn’t need a giant educational corpus to demonstrate adaptive tutoring. A compact curriculum graph was enough because the real focus was on the memory lifecycle, not on content scale.
- A good demo needs visible system behavior
“AI with memory” is not compelling if memory stays hidden in logs. The dashboard and timeline mattered because they turned architecture into something a human could understand at a glance.
- The best hackathon architecture is the one that supports the story
In the end, Continuum wasn’t trying to prove that we could build every tutoring feature imaginable. It was trying to prove one thing well:
an AI tutor becomes far more interesting when it can remember the student, adapt its teaching, and stop treating learning as a series of disconnected sessions.
That’s the story we optimized for, and that’s what shaped the build.
Closing thoughts
Continuum started as a simple frustration with the current generation of AI tutors: they are often smart, but they are rarely continuous.
They can explain a concept. They can generate a quiz. They can answer follow-up questions. But most of them still forget who the student is the moment the session ends.
We wanted to explore what happens when that changes.
What happens when a tutor remembers the patterns behind a student’s mistakes?
What happens when it adjusts its teaching strategy based on what has worked before?
What happens when it knows not only what the student got wrong, but also when they’ve finally moved past that weakness?
That’s the direction Continuum is built around.
And while the hackathon version is only the first step, it already made one thing clear to us:
the future of AI tutoring isn’t just better answers — it’s better memory.
Top comments (0)