SuperAPI AI Directory

iblai-api-studio

Writing & research

View repository

Updated 10-15 22:16

About this skill

iblai-api-studio — author a course on Open edX Studio

Studio is the Open edX CMS behind the ibl.ai LMS. The /iblai-api-studio-* skills drive it over its own session-authenticated HTTP endpoints (no UI, no Api-Token) and check the result on the LMS the way lms.ibl.ai does. Each skill is one capability with verified endpoints; this page is the map. A full build needs most of them — read the ones in the build order now, in one pass, before the first call.

Where Production Test server
Studio (authoring) https://studio.learn.iblai.app https://studio.learn.iblai.org
LMS API (verification) https://learn.iblai.app https://learn.iblai.org
LMS app (what users open) https://lms.ibl.ai https://lms.iblai.org

Preflight (30 seconds, always)

node .claude/skills/iblai-api-studio-auth/scripts/studio-login.mjs --check \
  && grep -q '^STUDIO_ORG=.\+' studio.env && echo "STUDIO_ORG set" || echo "STOP: run /iblai-api-studio-auth (and set STUDIO_ORG)"

No studio.env, an expired session, or an empty STUDIO_ORG → /iblai-api-studio-auth first. Do not start creating anything until this prints two oks and the org key.

Build order

0. /iblai-api-studio-auth            preflight above; sign in once → studio.env
1. plan the outline (below)          sections → subsections → units → components, on paper first
2. /iblai-api-studio-course-create   POST /api/ibl/manage/course/ → course_key (+ delete)
3. /iblai-api-studio-settings        dates, pacing, about page, images, catalog fields — BEFORE any publish
   /iblai-api-studio-grading         assignment types + weights — subsections reference these
4. /iblai-api-studio-outline         ONE call builds every section/subsection/unit (+ html/problem) and publishes
   then, always: rename the html blocks (the builder names them all "Text"),
   set graderType per graded subsection (the spec has no such key), republish
   — or block by block —
   /iblai-api-studio-section · -subsection · -unit    POST /xblock/ {parent_locator, category}
5. /iblai-api-studio-html            text blocks: data = HTML fragment
   /iblai-api-studio-problem         one problem block per unit holding all its questions (OLX)
   /iblai-api-studio-pdf             pdf blocks (advanced module + asset + save_pdf handler)
6. /iblai-api-studio-team            staff / instructor by email (any time)
7. /iblai-api-studio-publish         {publish:"make_public"} on the course root; verify states
8. /iblai-api-studio-lms             enroll, read the published outline as a user, catalog check

Settings before content, content before the first publish. Pacing (self_paced) cannot change once the course has started, enrollment must open before the start date, and a published-but-empty course is what users see in the catalog. Configure, build, review the outline, then publish once.

Bulk or one block at a time?

Both are first-class; pick by situation, not by convenience:

Situation Use
New course, outline known up front, text + questions /iblai-api-studio-outline — POST /api/v1/ibl/course/create_full_course builds and publishes the whole tree in one request (a 5-section course is 1 call instead of ~120)
Existing course, one change: add one section or lesson, insert a unit, fix one component's text, replace a quiz, reorder, rename, hide, delete a single block, work in an unpublished draft the individual skills (-section, -subsection, -unit, -html, -problem, -pdf) — they act on exactly one block by locator and never touch the rest
Existing course, many changes: rewrite all readings, add units across lessons, restructure sections /iblai-api-studio-outline "Bulk edits — reconcile": scripts/reconcile.py diffs a spec against the live outline and creates/updates/reorders (and, only on request, deletes) idempotently, then publishes what changed
Both build the skeleton + text with the bulk call, then add PDFs and later edits block by block or by reconcile, then republish what changed — the reconcile driver adopts the builder's "Text" html blocks on its first run, provided the spec keeps the built component order

The same block is named three ways across endpoints — locator/id + display_name + category (stock), xblock_locator/id + display_name + type (v1), block_id + name + block_type (container children). The table in /iblai-api-studio-outline maps them.

Never run the bulk builder against a course that already has content to "add a section": it appends and publishes everything, including drafts.

Deleting a course (/iblai-api-studio-course-create) is permanent and destroys user enrollments and progress. It is guarded by explicit checks in that skill; hiding a course (/iblai-api-studio-settings) is almost always what is meant.

Budget for block-by-block: 1 call per section/subsection/unit, 2 per html or problem block, 4 per pdf block, plus 1 publish. Keep every returned locator in a local JSON (build.json) keyed by the outline path so a re-run resumes instead of duplicating.

Planning a production-grade outline

Enterprise courses are judged on structure before content. Plan the tree before the first request and keep it consistent:

  • Start from outcomes. 3–6 measurable learning objectives for the course (verbs from Bloom's taxonomy: describe, apply, analyse, evaluate); every section maps to at least one, every graded subsection assesses one.
  • Sections = modules or weeks (4–8 for a short course), each with a one-line goal in its name: Week 2 · Reading data critically.
  • Subsections = lessons (2–4 per section, 20–40 minutes each). Name them by topic, not by type. Mark graded ones with graderType and a due date.
  • Units = one idea per page (3–6 per subsection, 5–10 minutes each), in a repeatable rhythm: context/overview → content (html, video, pdf) → practice (one problem block with several questions) → summary/next steps.
  • Assessment alignment. Formative checks (unlimited attempts, hints, showanswer: finished) inside lessons; summative work (limited attempts, weighted) in dedicated subsections whose grader type exists in the policy.
  • Consistency. Same naming pattern at every level, same unit rhythm, same HTML component styles (see /iblai-api-studio-html), a course-level intro section (welcome, objectives, how grading works, syllabus PDF) and a closing section (summary, further reading, feedback).
  • Accessibility and scope. Alt text on every image, headings in order, readings under ~1,500 words per unit, video under 10 minutes.

Write the plan as the JSON spec that /iblai-api-studio-outline accepts; it doubles as the review artefact for the user before anything is created.

Content quality — and how to keep sub-agents on the rails

Course content is the product. Every page a user opens must be well written, presentable and beautiful, informative without being distracting, well structured and organized, carefully planned and reviewed. That bar is easy to state and easy to lose when writing is split up.

Sub-agents drift. When sections or units are delegated to parallel agents, the pieces come back with different voices, different heading levels, different callout styles, uneven depth (one unit a rich reading, the next three sentences), invented terminology, or questions that do not match the objectives. Nothing in Studio stops that. Regulate it explicitly:

  1. One content brief, given to every agent verbatim — course objectives, audience and reading level, tone (second person, plain, no filler), the unit rhythm (overview → content → one practice block → summary), the naming pattern, the HTML patterns allowed (/iblai-api-studio-html), the question rules (/iblai-api-studio-problem), target length per unit (300–1,200 words of reading, 3–5 questions), and the glossary of terms already defined in earlier units.
  2. Produce the spec, not the calls. Sub-agents return JSON fragments for /iblai-api-studio-outline (or data strings for single blocks); only the coordinating agent posts to Studio, after review. No sub-agent gets studio.env.
  3. Review every fragment against the brief before it is posted: objective coverage, depth (no unit under ~150 words of real content, no placeholder text, no "in this section we will…" padding), consistent headings and callouts, valid HTML fragment and valid OLX, a title on every block, hints and solutions on every question, terminology consistent with earlier units, nothing that repeats a neighbouring unit. Send thin or divergent pieces back with the specific gap; do not "fix in post" by posting and patching.
  4. Read the whole course once, in order, as a user would (the published outline from /iblai-api-studio-lms, or the spec end to end) before the first publish. Transitions between sections, an intro that sets expectations, an outro that closes them.

Beautiful means calm: consistent components, generous spacing, one accent colour, no decoration that competes with the reading.

Keys you will pass around

Thing Shape Where it comes from
course key course-v1:<org>+<number>+<run> course create response course_key
course root block block-v1:<org>+<number>+<run>+type@course+block@course derived from the course key; parent_locator for sections and the bulk builder
any block (usage key) block-v1:<org>+<number>+<run>+type@<category>+block@<hex> locator from POST /xblock/ / xblock_locator from the v1 routes
category chapter · sequential · vertical · html · problem · pdf fixed

URL-encode course keys in query strings (course_key=course-v1%3Aorg%2Bnum%2Brun); path segments accept them raw.

The snippet every skill starts with

set -a; . ./studio.env; set +a
S=(-s -b "studio_session_id=$STUDIO_SESSION; csrftoken=$STUDIO_CSRF" -H "X-CSRFToken: $STUDIO_CSRF" \
   -H "Origin: $STUDIO_URL" -H "Referer: $STUDIO_URL/" -H "Accept: application/json" -H "Content-Type: application/json")

Accept: application/json makes Studio answer JSON; X-CSRFToken + Origin make writes pass CSRF. 302 to /login = expired session; a 500 HTML "Studio Server Error" on a documented call = a malformed cookie (see /iblai-api-studio-auth "Reading failures") or a parameter the skill marks as broken.

Which skill when

The user wants… Skill
"connect", "log in to Studio", a call returned 302/403/500 /iblai-api-studio-auth
a new course, list my courses, the course key, delete a course /iblai-api-studio-course-create
the whole outline (and text/questions) in one go /iblai-api-studio-outline
weeks/modules/sections; rename, reorder, release dates, hide from users /iblai-api-studio-section
lessons/subsections; due dates, graded as Homework/Exam, timed /iblai-api-studio-subsection
units/pages inside a lesson; order components; duplicate; delete /iblai-api-studio-unit
text, reading, rich content, callouts, tables, images, embeds /iblai-api-studio-html
a PDF reader block /iblai-api-studio-pdf
quiz, questions, multiple choice, checkbox, numeric, text, dropdown /iblai-api-studio-problem
dates, pacing, description, about page, images, intro video, catalog tags, advanced settings, uploads /iblai-api-studio-settings
who can edit the course; add/remove staff or instructors /iblai-api-studio-team
grading policy, assignment types, weights, pass mark, grace period /iblai-api-studio-grading
make it live, publish, discard draft, "why can't users see it" /iblai-api-studio-publish
enroll a user, what the user sees, is it in the catalog /iblai-api-studio-lms

Outside this family: AI-generated course drafts through the ibl.ai pipeline → /iblai-vibe-course-create; org roles (course-creator, org-instructor) and user admin → /iblai-api-management; catalog programs/pathways/enrollment with an Api-Token → /iblai-api-catalog; Canvas → /iblai-api-canvas-course-builder.

Reporting back

End with the course key, the LMS app URL $LMS_APP_URL/platform/<org>/courses/<course_key>, counts (sections / subsections / units / components), publish state, and anything that failed. An unpublished build is invisible to users — say so explicitly.