The lesson model
Everything you author in Itera hangs off a four-level graph. Understand these four rows and their shapes and the 21 tools become obvious — each is just create/read/update/delete on one level.
The graph
Section titled “The graph”flowchart TD tenant["Tenant<br/><small>your org / batch</small>"] program["Program<br/><small>a course template · unique slug per tenant</small>"] unit["Unit<br/><small>a section · ordinal</small>"] lesson["Lesson<br/><small>a single class · ordinal</small>"] activity["Activity<br/><small>kind · spec · rubric · ordinal</small>"] tenant --> program --> unit --> lesson --> activity
| Level | Lives in | Key fields | Parent |
|---|---|---|---|
| Program | itera.programs | slug (unique per tenant), title_i18n | tenant_id |
| Unit | itera.units | ordinal, title_i18n | program_id |
| Lesson | itera.lessons | ordinal, title_i18n | unit_id |
| Activity | itera.activities | kind, spec (jsonb), rubric (jsonb), ordinal | lesson_id |
- Each level is created with the parent id returned by the previous
create_*call. ordinalis the sort position within its parent (default0).- Deleting a parent cascades to its children (deleting a program removes its units, lessons, and activities).
- Everything is tenant-scoped by RLS. You only see and touch tenants your identity belongs to.
title_i18n — internationalised titles
Section titled “title_i18n — internationalised titles”Titles are an i18n map (jsonb), e.g. { "en": "Intro", "pt": "Introdução" }.
- You may pass a bare string — it is coerced to
{ "en": "<string>" }. - Omitting it defaults to
{}.
// both are valid title_i18n inputs"Introduction to Kafka"{ "en": "Introduction to Kafka", "pt": "Introdução ao Kafka" }Activity kinds
Section titled “Activity kinds”activity.kind is one of ten values. The first four are the original
dev/coding kinds; the rest are the general learning-activity taxonomy.
| Kind | Group | What it is |
|---|---|---|
diagram | judged | Build/annotate a diagram; graded against spec + rubric. |
document | judged | Write a document/answer; AI-judged against the rubric. |
quiz | judged | A quiz (question set) evaluated against the rubric. |
code | judged | A coding task; the artifact is judged. |
concept | no-judge | A concept / reading / explainer screen (no grading). |
single_choice | no-judge | Pick exactly one option. |
multi_choice | no-judge | Pick one or more options. |
match | no-judge | Match pairs across two columns. |
order | no-judge | Put items in the correct order. |
video | no-judge | Watch a video (optionally gated on completion). |
spec and rubric — free-form JSON
Section titled “spec and rubric — free-form JSON”Both are jsonb and both default to {}. They are kind-specific:
spec— the activity’s configuration/content. For asingle_choice, the prompt + options; for adocument, the task statement; for avideo, the video reference; etc.rubric— the grading criteria (for judged kinds). For adocumentorcodeactivity, the rubric drives the AI judge’s verdict.
The authoring tools do not enforce a per-kind spec schema — they store what
you give them. Keep the shape consistent per kind so the player and the judge can
read it. Illustrative shapes:
{ "prompt": "Which delivery guarantee does a Kafka consumer group provide by default?", "options": [ { "id": "a", "label": "Exactly-once" }, { "id": "b", "label": "At-least-once" }, { "id": "c", "label": "At-most-once" } ], "answer": "b"}// spec{ "prompt": "Explain how consumer-group rebalancing works and one way to minimise its impact." }// rubric{ "criteria": [ { "criterion": "Describes partition reassignment on membership change", "weight": 0.5 }, { "criterion": "Names a mitigation (e.g. static membership / cooperative rebalance)", "weight": 0.5 } ], "pass_score": 70}How reads mirror the graph
Section titled “How reads mirror the graph”Two reads return the graph pre-joined so you don’t have to walk it level by level:
get_programreturns a program with its full nested graph (units → lessons → activities, ordered byordinal).instantiate_programdeep-copies that whole graph into a new program.
Next: the authoring reference All 21 itera-mcp tools, grouped by level, with their real inputs and outputs.