Engram: The AI Tutor That Finally Solves Self-Grading With Architectural Isolation
Hook
Every AI tutor fails the same way: the model grades its own explanations, you feel like you've learned, and two weeks later you remember nothing. Engram fixes this with a architecture trick borrowed from judicial systems—separation of powers.
Context
Conversational AI promised to revolutionize learning. Ask GPT-4 to explain Rust lifetimes, and you'll get a Socratic dialogue that feels like understanding is crystallizing in real-time. The problem? That feeling is a lie. Learning science has known since the 1970s that fluency—how smoothly information flows during study—is a terrible predictor of retention. You close the chat window feeling enlightened, and a week later you can barely reconstruct the core concept.
The failure mode is structural: AI tutors use the same model to teach and assess. When GPT evaluates whether you understood its explanation of monads, it's essentially grading its own teaching performance. The model sees your confused half-answer, recognizes its own phrasing, and generously decides you've 'got it.' You move on, the concept never enters long-term memory, and the cycle repeats. Meanwhile, Anki users with hand-written flashcards are still recalling obscure facts years later because spaced repetition works—but only if someone honest is checking your answers. Engram is the first tool that brings together conversational AI teaching and algorithmic spaced repetition while solving the assessment catastrophe through architectural isolation.
Technical Insight
Engram's core innovation is splitting the learning pipeline into four components that never share context. The curriculum architect (a separate Claude agent) decomposes topics into directed acyclic graphs of prerequisite concepts. The tutor (constrained Claude chat) conducts Socratic dialogue but never evaluates answers—it just saves them to disk. The assessor (a blind third agent) receives only rubrics and learner responses, producing grade receipts with zero visibility into the teaching session. The scheduler (pure Python running FSRS-4.5) consumes those receipts to maintain a local learner model and compute review timing.
Here's what a learning session looks like at the code level. When you request a review, the scheduler queries your learning state and selects due concepts:
# engram.py - FSRS scheduler (simplified)
def get_due_reviews(learner_state: dict) -> list[Concept]:
now = datetime.now()
due = []
for concept_id, memory in learner_state['memories'].items():
if memory['next_review'] <= now:
due.append({
'id': concept_id,
'stability': memory['stability'],
'difficulty': memory['difficulty']
})
return sorted(due, key=lambda x: x['stability']) # Review weakest first
The tutor then loads the concept from your curriculum graph and enforces generation-before-explanation patterns. It asks you to retrieve the concept from memory, waits for your answer, and crucially—saves it to a stash file before showing any feedback:
# Tutor agent flow (conceptual)
def conduct_review(concept: Concept) -> StashFile:
prompt = f"Retrieve from memory: {concept.prompt}"
learner_response = chat(prompt, show_answer=False)
# Write to disk BEFORE any feedback
stash = {
'concept_id': concept.id,
'timestamp': now(),
'response': learner_response,
'rubric': concept.rubric
}
write_stash(f'~/.claude/learning/stash/{concept.id}_{timestamp}.json', stash)
return stash
The assessor runs as a completely separate Claude invocation. It reads the stash file, sees only your response and the grading rubric, and produces a grade receipt:
# Assessor agent (blind to teaching context)
def grade_stash(stash_path: str) -> GradeReceipt:
stash = json.load(open(stash_path))
# Agent receives ONLY these two artifacts
prompt = f"""
Rubric: {stash['rubric']}
Learner answer: {stash['response']}
Grade this response. You have NO access to the teaching session.
"""
assessment = claude_api(prompt, temperature=0.3)
receipt = {
'concept_id': stash['concept_id'],
'grade': parse_grade(assessment), # Again/Hard/Good/Easy
'justification': assessment,
'graded_at': now()
}
write_receipt(receipt)
return receipt
The FSRS scheduler consumes these grade receipts to update your memory model. FSRS-4.5 is the algorithm powering modern Anki—it predicts forgetting curves per-concept using stability and difficulty parameters:
# Update memory based on grade receipt
def update_memory(concept_id: str, grade: str, memory: Memory) -> Memory:
# FSRS-4.5 update equations (simplified)
if grade == 'Again':
new_stability = memory.stability * 0.4
new_difficulty = min(10, memory.difficulty + 2)
elif grade == 'Easy':
new_stability = memory.stability * 2.5
new_difficulty = max(1, memory.difficulty - 1)
# ... other grade cases
# Calculate next review using forgetting curve
interval_days = new_stability * (0.9 ** (1/new_difficulty))
next_review = now() + timedelta(days=interval_days)
return Memory(
stability=new_stability,
difficulty=new_difficulty,
next_review=next_review
)
The architectural isolation is enforced through separate Claude API calls with no shared conversation history. The tutor can't see grades, the assessor can't see explanations, and the scheduler is pure deterministic math. This isn't prompt engineering—it's structural impossibility for the failure mode to occur.
For threshold concepts (ideas that transform understanding, like pointers or monads), the curriculum architect generates explorable explanations as self-contained HTML artifacts. These implement prediction gates: content is hidden until you commit a guess, encoding desirable difficulties directly into the UI. The HTML is portable—you can save it, revisit it offline, or share it without the learning system.
Gotcha
The blind assessor only sees what you type. If you understand something but struggle to articulate it in chat, you'll get marked wrong—and that error propagates through your entire review schedule. Verbal understanding, sketched diagrams, or the 'I know it when I see it' feeling don't count. You must write to learn, which creates friction for visual or kinesthetic learners.
The local-first architecture means your learning state lives in ~/.claude/learning/ with no sync mechanism. Lose that directory and you lose months of grade receipts, review schedules, and calibration data across all topics. The system is single-device only—studying on your laptop, then switching to a tablet for evening reviews breaks the FSRS scheduling entirely. For a tool positioning itself as production-grade spaced repetition, the lack of state synchronization is a significant operational risk. Anki solved this in 2010 with AnkiWeb; Engram asking you to manually backup JSON in 2024 feels like an unforced error. The privacy benefits of local-first are real, but opt-in sync should exist for users willing to trade that for durability.
Verdict
Use if: You're a self-directed technical learner tackling genuinely difficult concepts (category theory, distributed systems, compiler internals) and you already have the discipline for deliberate practice. The blind grading and FSRS scheduling will catch the retention gaps that conversational AI alone misses, and the local-first stance means your learning data never trains someone else's model. Use if you value algorithmic accountability over frictionless explanations. Skip if: You want passive learning without retrieval effort, need to study across multiple devices without manual state management, or learn better through discussion than solo recall. Skip if you're exploring broad topics casually rather than mastering specific technical depths—Engram optimizes for retention at the cost of initial ease, which only pays off for knowledge you'll use long-term.