Author a full course with an LLM
This is the canonical end-to-end flow: from an empty tenant to a playable course.
Each step uses the parent id returned by the previous one. An LLM connected to
itera-mcp can run this from natural language — the tool
sequence below is what it emits.
-
Find your tenant + confirm you can author.
whoami→ read an id fromauthor_tenant_ids. (Orlist_tenants→ pick theidfor your slug.)whoami → result { "memberships": [ { "tenant_id": "8f3c…", "role": "author" } ], "author_tenant_ids": ["8f3c…"] } -
Create the program.
create_program → args { "tenant_id": "8f3c…", "slug": "intro-kafka", "title_i18n": { "en": "Intro to Kafka" } }→
{ "success": true, "program": { "id": "P1", … } } -
Add a unit (parent = the program id
P1).create_unit → args { "program_id": "P1", "ordinal": 0, "title_i18n": { "en": "Fundamentals" } }→
{ "success": true, "unit": { "id": "U1", … } } -
Add a lesson (parent = the unit id
U1).create_lesson → args { "unit_id": "U1", "ordinal": 0, "title_i18n": { "en": "Topics & partitions" } }→
{ "success": true, "lesson": { "id": "L1", … } } -
Add activities (parent = the lesson id
L1). Mix kinds — aconceptexplainer, then asingle_choicecheck, then a judgeddocumenttask.create_activity → args (concept) { "lesson_id": "L1", "kind": "concept", "ordinal": 0,"spec": { "body": "A topic is split into partitions; each partition is an ordered log." } }create_activity → args (single_choice) { "lesson_id": "L1", "kind": "single_choice", "ordinal": 1,"spec": { "prompt": "What guarantees ordering in Kafka?","options": [ { "id": "a", "label": "The topic" }, { "id": "b", "label": "The partition" } ],"answer": "b" } }create_activity → args (document, judged) { "lesson_id": "L1", "kind": "document", "ordinal": 2,"spec": { "prompt": "Explain when you'd increase a topic's partition count." },"rubric": { "criteria": [ { "criterion": "Mentions consumer parallelism", "weight": 1 } ], "pass_score": 70 } } -
Verify the graph with a single read:
get_programwith{ "program_id": "P1" }→ returns the program withunits → lessons → activitiesnested and ordered. Confirm it matches what you built.
Reordering & edits
Section titled “Reordering & edits”- Change order with
update_unit/update_lesson/update_activity(ordinal). - Fix a title with
update_*(title_i18n). - Remember:
update_activityreplacesspec/rubricwholesale — read, edit, write back the full object.
Clone it for the next cohort
Section titled “Clone it for the next cohort”Once a program is a good template, instantiate_program deep-copies the entire
graph into a new program in one call:
{ "source_program_id": "P1", "new_slug": "intro-kafka-2026-q3", "new_title_i18n": { "en": "Intro to Kafka — 2026 Q3" } }→ { "success": true, "new_program_id": "P2" }