AI Engineering  ·  Curriculum Generation  ·  EdTech

Why We Don't Let AI Design Your Curriculum Alone

How we built the AI-powered course generation engine behind our Full-Stack EdTech Platform, and why the real engineering work started after the model finished writing.

July 2026 9 min read Applied AI  ·  Graph Algorithms  ·  EdTech
Start Reading Back to Blogs

See It in Production

This generate-then-validate architecture powers the AI course generator inside our Full-Stack EdTech Platform, alongside pgvector recommendations and a full DDD microservices backend.

View the Case Study
The Problem

The Trap: Trusting AI's First Draft

"Let AI generate the courses" sounds simple. Feed a topic to a model, get back a structured curriculum, lessons, modules, sequencing, the works. It wasn't simple.

Every demo of this kind looks impressive in the first five minutes. Type a prompt, watch a full course outline appear. Then someone opens the curriculum in detail and finds this:

  • LESSON 4 Build AI Agents
  • LESSON 5 Advanced Memory Management
  • LESSON 9 What is an LLM?

Every individual lesson is well written. The problem is the order, you can't teach agent-building before you've taught what a language model even is. Technically valid content, pedagogically broken structure. That gap is exactly where a good AI demo stops and a production education product has to begin.

Why longer prompts don't fix it

The instinctive fix is to keep adding rules to the prompt: respect prerequisites, avoid duplicate concepts, keep difficulty progressive, avoid circular dependencies. It helps, for a while. But it rests on a false assumption, that a large language model, given enough instructions, will reliably obey structural rules every single time.

It won't, not because the model is bad, but because it's fundamentally probabilistic. It generates what's likely to be a good curriculum; it doesn't verify that it is one. No amount of prompt length changes that math. Somewhere around lesson 30 of a 60-lesson course, a dependency gets duplicated or a prerequisite gets skipped, and nobody notices until a learner hits a wall mid-course.

A prompt is a request. It has never been a guarantee. Treating one as the other is how structural bugs ship straight to learners.

For a consumer chatbot, an occasional ordering slip is a shrug. For an education platform whose entire value proposition is a coherent learning path, it's a broken product, and it doesn't show up in a demo, it shows up three weeks later in a support ticket from a paying learner who's stuck.

The Fix

What We Built Instead

The architecture decision that solved this was simple to state and non-trivial to build: stop treating the AI's first output as the final output.

We split the system into two distinct responsibilities: the model generates, deterministic software validates every relationship it creates before anything reaches a learner. It's the same discipline enterprise software has always applied to user input and API payloads, we simply stopped treating AI output as an exception to that rule.

The generation side is genuinely probabilistic and stays that way, that's what makes it useful. The validation side is intentionally boring: no model calls, no sampling, no "mostly correct." A curriculum either satisfies the graph constraints or it doesn't, and that's a question ordinary code can answer in milliseconds.

System Architecture

User Request topic + level AI Generation lessons · order prerequisites Deterministic Validation graph checks cycle · order · duplicates issues found? no Approved ready to publish yes Targeted AI Repair fix only flagged items everything else untouched re-validate

The AI proposes; deterministic checks decide. Only flagged issues get sent back for repair, never a full regeneration.

This is the same "optimistic concurrency" instinct distributed systems use: let the fast, hopeful path run, then check its result against hard invariants before committing it. The model isn't asked to be perfect. It's asked to produce a candidate that a separate, deterministic gate can verify.

In Practice

What Validation Actually Catches

A curriculum isn't really a list of lessons, it's a directed graph. Lessons depend on other lessons, concepts build on prior concepts, modules connect (or should connect) into a coherent path. Treat it as a graph, and most structural problems stop being things you hope an AI notices, and become things you can check mathematically.

01

Broken prerequisite order

"Build AI Agents" placed at lesson 30, but its stated prerequisite, "LangChain Basics," at lesson 45. Model every lesson as a node and every prerequisite as a directed edge, then run a topological sort (Kahn's algorithm) over the graph: if a lesson's prerequisite can't be scheduled before it in any valid linear order, the sort fails outright and names the exact offending pair. No model call required.

Topological sort · O(V+E)
02

Circular dependencies

"Vector Search" required "Embeddings." "Embeddings" required "Vector Search." A → B and B → A. A depth-first traversal that tracks the current recursion stack flags any back-edge the moment it's created, which is exactly how a topological sort fails in the first place, so in our implementation the two checks share one pass over the graph.

DFS back-edge detection
03

Silent duplication

"Prompt Engineering" taught twice, at the same depth, at lessons 2 and 9, the course quietly repeating itself instead of moving the learner forward. Each lesson's core concept gets embedded, and any pair with cosine similarity above a fixed threshold (~0.92) is flagged for review rather than silently allowed through. Deterministic threshold, probabilistic embedding, used only for comparison, never for the pass/fail decision itself.

Embedding similarity, fixed threshold
04

Disconnected learning tracks

A clean Python → LangChain → Agents track generated alongside an unrelated Marketing Strategy → Customer Personas track, with no bridge between them. A connected-components pass over the prerequisite graph surfaces any lesson cluster that isn't reachable from the course's stated entry point, for human review, rather than letting it ship silently.

Connected components

Why not just ask another LLM to check the first one?

It's the obvious-sounding alternative, and it's the one we deliberately avoided. An "LLM-as-judge" pass over the same curriculum is still a probabilistic process, it can miss the exact same class of error the generator missed, for the exact same underlying reason. You haven't added verification, you've added a second opinion with the same blind spots, at roughly the same latency and cost as the first call.

Graph checks don't have that failure mode because they're not making a judgment call, they're evaluating a well-defined property. A topological sort either succeeds or it doesn't; there's no confidence score to argue with. And the performance difference isn't cosmetic: a full graph validation pass over a 60-lesson course runs in single-digit milliseconds, versus the multi-second round trip of even one additional LLM call, which matters when validation has to run after every repair iteration, not just once.

Closing the Loop

The Repair Loop: Fix What's Broken

When validation finds a problem, the instinct is to regenerate the whole curriculum and hope it comes out better. We don't.

Full regeneration is slow, expensive, and just as likely to introduce a new structural problem while fixing the old one, you're re-rolling the dice on every lesson to fix three of them. Instead, the validator emits a precise, scoped report, and only that report goes back to the model:

// validation_report.json
{
  "status": "failed",
  "issues": [
    { "type": "order_violation", "detail": "Lesson 40 depends on Lesson 60" },
    { "type": "duplicate_concept", "detail": "Prompt Engineering (lessons 2, 9)" },
    { "type": "circular_dependency", "detail": "Embeddings ↔ Vector Search" }
  ],
  "instruction": "Fix only these. Leave everything else untouched."
}

That constraint changes the nature of the AI call entirely, from "generate a good curriculum" (hard to verify) to "resolve three specific, well-defined issues" (easy to verify). The result converges on a correct output in one or two repair passes, rather than an open-ended cycle of regeneration and hope.

Guardrails around the loop itself

  • A repair-iteration cap. If a curriculum isn't clean after a fixed number of repair passes, it's escalated to a human reviewer instead of looping indefinitely.
  • Untouched-content diffing. Every repair pass is diffed against the prior version; if the model changes anything outside the flagged issues, that pass is rejected and retried.
  • An immutable audit trail. Every generation, validation report, and repair pass is logged, so a curriculum's structural history can be reconstructed later if a learner reports something that slipped through.
Where This Shipped

This generate-then-validate pipeline is the course-authoring engine behind our Full-Stack EdTech Platform, sitting alongside the pgvector-based recommendation service and the Razorpay payment flow in the same DDD microservices architecture.

Beyond Curriculum

Why This Matters Beyond Curriculum Generation

We built this for an education platform, but the underlying pattern isn't education-specific, it's the pattern every serious enterprise AI system eventually needs. Anywhere AI generates something with internal structure, a compliance document, a software architecture, a training roadmap, a set of business rules, the same choice applies: trust the model's first pass, or build a system that verifies it.

Enterprise software has never trusted user input, API payloads, or database writes without validation. There's no reason AI-generated output should be the exception. The teams getting real production value out of AI right now aren't the ones with the cleverest prompts, they're the ones who stopped asking the model to be right, and started building systems that make sure it is.


Talk to Our Team    View the EdTech Platform Case Study

Topics

Applied AI Graph Algorithms Content Generation EdTech LLM Validation

Related Articles

Full-Stack EdTech Platform

The full case study: microservices, DDD, Razorpay payments, and pgvector recommendations behind the platform.

Engineering Trust Into RAG

The same "don't trust the first pass" discipline, applied to a production RAG assistant.

Building a Production-Ready RAG System

Hybrid retrieval, reciprocal rank fusion, and cross-encoder reranking, from the ground up.