OpenMAIC

Application

THU-MAIC/OpenMAIC

Multi-agent AI classroom that turns one prompt into a full interactive course.

Overview

OpenMAIC is an open-source multi-agent interactive classroom that generates immersive courses from a single prompt. Its agent workbench plans curricula, builds slides, quizzes, simulations and videos, and can be steered mid-generation. It is provider-neutral, supporting bring-your-own LLMs, media, search and storage backends.

README Preview

\n  \n -->\n\n\n  \n\n\n\n  Get an immersive, multi-agent learning experience in just one click\n\n\n\n  \n    \n  \n\n\n\n  \n  \n  \n  \n  \n  \n  \n  \n  \n   \n  \n  \n  \n  \n  \n  \n  \n\n\n\n  English | Simplified Chinese\n  \n  Live Demo · Quick Start · Lemonade · FunASR · Features · Use Cases · OpenClaw\n\n\n## 🎉 OpenMAIC v1.0.0 — Build courses with an agent\n\n**One prompt in, a whole course out — and now you can steer.** Released August 27, 2026, OpenMAIC v1.0.0 adds a **Pro workbench** alongside the classic one-click generator: chat with an agent that plans your curriculum, builds and revises every page, and works straight from your materials.\n\n- 🤖 **Agent workbench** — a chat-first workspace that plans, builds, and revises whole courses\n- 💾 **Durable sessions** — server-backed runs survive restarts; cancel, resume, and steer anytime\n- 📎 **Session materials** — upload documents, audio, and video, or pull from web search; the agent builds from them\n- 🧰 **Course tools + 20 built-in skills** — slides, quizzes, interactives, PBL, images, video, voices, `.pptx` import\n- 🔌 **Neutral by design** — bring your own models, media, search providers, and storage backend\n\nTake the full tour in [Features](#-features), then set it up with [Agent workbench and runtime](#optional-agent-workbench-and-runtime).\n\n\n## 🗞️ News\n\n- **2026-08-27** — **OpenMAIC v1.0.0:** an agent workbench, durable course-building sessions, reusable skills, session materials, provider-neutral server capabilities, and a pluggable persistence stack.\n- **2026-08-14** — [v0.3.2 released!](https://github.com/THU-MAIC/OpenMAIC/releases/tag/v0.3.2) Video export hardening (deterministic Quiz/PBL covers, fidelity polish, interactive HTML capture, CPU resource profiles); server-backed persistence completed (full document cutover, one-command Postgres stack, incremental saves) plus the asset registry; the `@openmaic/generation` package; four new locales; Amazon Bedrock, At

FAQ (5)

Troubleshooting
Why does my custom keyless TTS/ASR provider reset to Browser Native after page reload in OpenMAIC (dubbing controls disappear)?

This is a known bug in OpenMAIC v1.1.2. When you add a custom keyless provider (requiresApiKey: false, e.g. a local OpenAI-compatible TTS endpoint), addCustomTTSProvider in lib/store/settings.ts saves the endpoint only to customDefaultBaseUrl and leaves baseUrl: ''. On reload, the validation isProviderUsable in lib/store/settings-validation.ts runs if (cfg.requiresApiKey === false) return !!cfg.baseUrl;, marks the provider as unusable, and silently falls back to browser-native-tts. Since dubbing UI (per-line preview/regenerate buttons, 'regenerate all dubbing', voiced chips) is gated on ttsProviderId !== 'browser-native-tts', all dubbing controls vanish.

Fix (verified): in lib/store/settings.ts, write the URL to both fields when adding/updating a custom provider:

addCustomTTSProvider: (id, name, baseUrl, requiresApiKey, defaultModel) =>
  set((state) => ({
    ttsProvidersConfig: { ...state.ttsProvidersConfig, [id]: {
      ...,
      baseUrl,                  // was ''
      customDefaultBaseUrl: baseUrl,
      ...
    }},
    ttsProviderId: id,
  })),

Alternative fix: in isProviderUsable, accept customDefaultBaseUrl as a fallback for custom-* provider ids, e.g. return !!(cfg.baseUrl || cfg.customDefaultBaseUrl); for the keyless branch. Apply the same change to custom ASR providers, then rebuild (pnpm build && pnpm start). Temporary workaround without code changes: re-select the custom provider in Settings → Model Services → TTS after each reload (it works until the next reload), or delete and re-add the provider each session.

GitHub Issue #1769
Troubleshooting
Why does OpenMAIC PBL v3 reject valid student feedback with '请引用本轮学生对当前段的实质反馈' error?

This is a known bug in OpenMAIC 1.2.0-rc.2. The PBL v3 studentFeedback gate (lib/server/pbl-v3/guided-review.ts, lines 71-79) used a literal substring match against the latest student message, so any feedback the agent wrapped or summarized (e.g. Student reply: "...") failed the check and blocked progression via read_next_skill or complete_stage. Fix: upgrade to a build that includes PR #1963 (commit 4de9467d, merged into the integration/shared-sandbox branch). The fix accepts quoted or summarized feedback and answers spread across multiple learner messages, while still enforcing real-reply, stage, and artifact-version checks.

GitHub Issue #1960
Troubleshooting
Why is KaTeX/LaTeX math showing as raw text (not rendered) in OpenMAIC interactive scenes?

This happens because postProcessInteractiveHtml (in packages/@openmaic/generation/src/interactive-post-processor.ts) skips injecting the KaTeX auto-render script and MutationObserver whenever the generated HTML already contains the string katex. When the model-generated page ships its own katex.min.js/katex.min.css (common), auto-rendering is never installed, so \(...\) and $...$ print literally. In sandboxed about:srcdoc iframes, the page's own renderMathInElement() call also fails with Uncaught ReferenceError: renderMathInElement is not defined because external CDN scripts cannot load. Two failure modes: (1) math never renders when the page includes KaTeX core; (2) labels filled by the page's own init() stay raw on first paint because the observer is installed after the initial render pass. Fix (PR #1606): guard injection on auto-render/renderMathInElement instead of the bare katex string; when KaTeX core is already present, inject only the missing auto-render contrib script and the MutationObserver; after installing the observer, run one extra render pass after a ~300ms settle timeout and again on window load so init()-filled labels render on first paint.

GitHub Issue #1538
Troubleshooting
How to fix SANDBOX_CONFLICT (409) error when PBL v3 teaching tools fail in OpenMAIC?

This error occurs when PBL v3 background polling and a teaching tool (e.g., read_next_skill, request_skill_review, complete_stage) call touchEnvironment for the same study concurrently, so the second renewal fails to acquire the environment advisory lock and returns 409 before recording its result. **Workaround:** retry the teaching action after the other operation finishes — the retry typically succeeds. **Permanent fix:** upgrade to a build including PR #1964 (merge commit 3446978c on integration/shared-sandbox), which rereads the durable renewal timestamp and retries explicit environment-lock contention within a five-second budget without replaying teaching actions. Note this fix landed after v1.2.0-rc.2 and may not yet be merged into main.

GitHub Issue #1961
Troubleshooting
How to fix 'Parsing service unavailable' failed material error in OpenMAIC?

A material fails with 'Parsing service unavailable' when no parser is configured. An administrator must first configure a parser for the knowledge base, then open the knowledge base page and use 'Parse again' on the failed material to retry. For media that fail because they are too long, check the duration limit shown in the failure reason. Note that conversation-sourced materials have no 'Parse again' row action — manage and re-parse them directly from the knowledge base page. Clearer reason-specific failure guidance, localized business error messages (previously English-only), and corrected singular/plural wording ('1 material' instead of '1 materials') were shipped in PR #1923, merged as commit 84a88bc4.

GitHub Issue #1892