PATHWAY-FORGE Generative AI · Learning Authoring 2024 — 2026

Generating Courses Without Letting the Model Invent the Curriculum

An authoring system that turns a one-line brief into a standards-grounded programme, validates the structure, then generates each session as editable content.

PART OF // Education platform · 2020—2026

ROLE // Architect and core engineer — platform architecture, learner-runtime integration and delivery, with product, data-science and engineering teammates

brief → programme Structured authoring flow
grounded Standards chosen before generation
per session Isolated, recoverable jobs
STACK // ReactNode.jsPythonLLM OrchestrationVector SearchQueuesStructured Content

⬢ Client-anonymised by design. No employer, product or customer is named, and no proprietary code appears here — only the system shape and the reasoning behind it.

Generation is the last step, not the first. Everything before it narrows what the model is allowed to say. INTAKE GROUNDING SKELETON FAN-OUT PUBLISH Author Brief one sentence, usually Guided Form fills the gaps Normalise resolve required constraints Standards Retrieval vector search over the model Constraint Filter age · duration · format Outline Generator typed module / unit / session Validator codes · hierarchy · coverage Session Jobs one per session, durable Progress State visible, resumable Structured Content slides · activities · quizzes Preview & Edit author keeps authority Learner Runtime same path as hand-authored
interface service state async external Generation is the last step, not the first. Everything before it narrows what the model is allowed to say.

A fluent answer is not a curriculum

Someone can describe what they want to teach in one sentence. A programme that an institution will actually run needs rather more than that: an audience, a duration, a subject context, a cognitive or behavioural focus, a delivery format, the technology available in the room, and the cultural setting it will be taught in.

A language model will supply all of those, immediately and plausibly, whether or not it has been told any of them. That is the entire problem. The failure mode isn’t a model that refuses — it’s a model that invents a standards identifier that reads exactly like a real one.

So the product treats generation as the last stage of a compilation pipeline rather than the first. Resolve the brief, choose the allowed standards deterministically, build a validated skeleton, and only then spend money on session content.

Constraints that shaped it

Briefs are incomplete by nature. Nobody arrives with a fully specified programme; if they had one they wouldn’t need the tool. The intake has to make missing constraints visible rather than quietly defaulting them.

Curriculum coverage has to be citable. A generated programme that claims to cover a competency has to be pointing at a real entry in a versioned standards model. This is the property the whole thing is sold on.

Generation is slow and partially fails. A full programme is dozens of expensive calls. Treating that as one atomic operation means a single timeout throws away everything.

The output has to be editable. Generated material that can’t be opened, corrected and published through the same path as hand-authored material is a demo, not a feature.

Decisions, and what each one cost

Retrieve and filter before generating

Vector search maps the author’s intent into the standards model; deterministic filters then narrow that to the competencies, age bands, durations, subjects, formats and contexts actually permitted. The model composes within that set — it never chooses it.

What it cost: the apparent freedom of the tool drops sharply, and that is visible to users. Someone who asks for something outside the permitted range gets told so rather than getting a confident answer. We chose to make that refusal explicit, which reads as a limitation right up until the first time someone checks a code and finds it real.

Approve the skeleton before paying for the detail

The first output is a typed module/unit/session outline carrying identifiers, durations, objectives and coverage rollups. It is validated — codes exist, hierarchy is well-formed, durations sum correctly, coverage is what was asked for — before a single session is generated.

What it cost: two round trips where users expected one, and a screen they have to look at before the thing they wanted. It also means an outline change after generation has to reconcile against work already done, which is the fiddliest code in the system.

Fan out one durable job per session

Each session generates independently with its own progress state. A failure is retried in place; completed sessions stay completed.

What it cost: ordered assembly and version handling. Sessions finish out of order, and if the outline moves underneath them you need to know which generated content belongs to which revision. A single sequential pass would have been a tenth of the code.

Publish into the existing content schema

Slides, prompts, polls, quizzes, discussions and activities share one renderable structure, so generated material enters the same preview, edit, publish and delivery path as anything authored by hand.

What it cost: the generator is constrained by a schema it doesn’t own, and extending the schema means touching the learner runtime. The alternative — a parallel format for generated content — would have been faster and would have produced two systems to maintain forever.

What changed

Authoring moved from a blank page to a governed workflow. A brief becomes a reviewable outline; standards coverage stays visible while it’s being assembled; progress is observable rather than a spinner; and the output is operational content rather than a wall of text somebody has to transcribe.

What I’d do differently

I’d make the prompt, the model version, the retrieval corpus and the standards version first-class provenance on every generated artefact, and I’d run a regression evaluation before changing any of them. Generative components drift, and without a held-out set with expected properties you learn about it from a user rather than from CI.

I’d also put explicit cost and latency budgets on each stage and surface them in the product. They were understood by the team and invisible to everyone else, which is precisely the kind of thing that becomes a surprise at renewal.

Image, narration and video generation existed alongside this. I’d keep them labelled experimental until their output quality has been measured the same way the text path is.