# How the OpenMAIC Lesson Generation Pipeline Is Structured: A Deep Dive into the Agent-Runtime Architecture

> Explore the OpenMAIC lesson generation pipeline's five-layer server-side orchestration. Learn how it turns prompts into skills and builds lessons with crash resilience.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: deep-dive
- Published: 2026-09-11

---

**The OpenMAIC lesson generation pipeline is structured as a five-layer server-side orchestration system that parses user prompts into skill requests, dispatches them through specialized generation tools, persists incremental progress in Dexie-based stores, and synchronizes completion states with the React frontend for crash-resilient lesson construction.**

The THU-MAIC/OpenMAIC repository implements a robust **lesson generation pipeline** within its `agent-runtime` architecture. This system transforms natural language prompts into structured educational content by chaining together stateless orchestration logic and persistent client-side state stores. Understanding this architecture reveals how the application maintains data integrity and UI responsiveness during long-running AI generation tasks.

## Layer 1: Skill Parsing and Dispatch

The pipeline initiates in [`lib/server/agent-runtime/skill-handle-inference.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/skill-handle-inference.ts), where the system parses incoming user prompts to extract the leading **skill name**.

When a user submits a prompt like "build a lesson about photosynthesis using slide-craft", the skill resolver identifies the tool identifier (e.g., `slide-craft` or `stage-design`) and forwards the request to the appropriate generation handler. This separation of concerns ensures that the orchestration layer remains agnostic to the specific content generation logic, treating each skill as a modular plugin.

## Layer 2: Generation Tool Orchestration

The central registry in [`lib/server/agent-runtime/generation-tools.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/generation-tools.ts) manages all generation implementations through the `runGenerationTool` entry point.

This orchestrator performs three critical operations:
- It creates a **generation job** with a unique `generationId`.
- It assigns the `producer` field as `"server-job"` to track ownership.
- It records the job in the **media-generation store** before execution begins.

The registry maintains a `generationToolMap` that maps tool names (like `slide-design` or `image-generation`) to their respective execution handlers. This pattern allows developers to register new lesson-generation capabilities by extending the tool map without modifying the core dispatch logic.

```typescript
// lib/server/agent-runtime/generation-tools.ts
export async function runGenerationTool(
  toolName: GenerationToolName,
  payload: GenerationPayload,
) {
  const job = await createGenerationJob(toolName, payload); // creates DB record
  const tool = generationToolMap[toolName];
  await tool.execute(job.id, payload);
  return job.id;
}

```

## Layer 3: Persistent State Management

The pipeline delegates state persistence to two specialized Dexie-based stores that serve as the **single source of truth** for generation progress.

### Media-Generation Store

Located in [`lib/store/media-generation.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/store/media-generation.ts), this IndexedDB store tracks the granular state of every active generation job. It stores the outline, intermediate scene data, media URLs, and completion flags. The store provides methods like `addChunk` to stream incremental updates from the server, enabling real-time progress visualization even during lengthy AI inference.

```typescript
// lib/store/media-generation.ts
export const useMediaGenerationStore = create<DexieStore<MediaGenerationRecord>>({
  // Dexie schema …
  async addChunk(jobId, chunk) {
    await db.mediaGeneration.where('jobId').equals(jobId).modify({ ...chunk });
  },
});

```

### Stage Store

The [`lib/store/stage-store.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/store/stage-store.ts) maintains the current lesson's high-level metadata, including the scene list and the `generationComplete` boolean flag. When the orchestrator finishes processing, it writes the final outline into this store, triggering the UI to transition from loading states to content rendering. This store also handles **crash-recovery** by rehydrating the lesson state from IndexedDB when the application reloads.

## Layer 4: Frontend Synchronization

React components consume the pipeline state through custom hooks (`useMediaGenerationStore`, `useStageStore`). The [`components/generation/interactive-mode-button.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/components/generation/interactive-mode-button.tsx) file demonstrates this pattern by conditionally rendering UI elements based on the `generationOpen` and `generationComplete` flags.

```tsx
// components/generation/interactive-mode-button.tsx
const generationOpen = useMediaGenerationStore(state => state.generationOpen);
const generationComplete = useStageStore(state => state.generationComplete);

return (
  <>
    {generationOpen && !generationComplete && <LoadingSpinner />}
    {generationComplete && <LessonViewer />}
  </>
);

```

This subscription model ensures that the interface remains responsive while the server-side pipeline processes complex generation tasks, providing immediate visual feedback when intermediate artifacts arrive.

## End-to-End Data Flow

The complete **lesson generation pipeline** follows a deterministic sequence from prompt to rendered content:

1. **Prompt → Skill resolver** – The user input undergoes parsing in [`skill-handle-inference.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/skill-handle-inference.ts) to extract the target skill (e.g., `slide-craft`).
2. **Skill → Generation tool** – `runGenerationTool` instantiates a job record with a unique `generationId` and persists it to the media-generation store.
3. **Tool → Media-generation store** – The active tool streams incremental artifacts (outline chunks, generated media URLs) into the Dexie database via `addChunk`.
4. **Store → Stage store** – Upon receiving the final `generationComplete: true` signal, the orchestrator copies the finalized outline into the stage store.
5. **Stage store → UI** – React hooks detect the state change and render the completed lesson slides.

## Summary

- The **skill parsing layer** in [`skill-handle-inference.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/skill-handle-inference.ts) extracts tool identifiers from natural language prompts.
- The **orchestration layer** in [`generation-tools.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/generation-tools.ts) manages job lifecycle through `runGenerationTool` and unique `generationId` tracking.
- **Persistent storage** relies on Dexie-based [`media-generation.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/media-generation.ts) for granular progress and [`stage-store.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/stage-store.ts) for completion flags.
- The **frontend** synchronizes via React hooks that subscribe to store changes, enabling real-time progress indicators.
- This architecture provides **crash-resilience** through IndexedDB persistence and **extensibility** through the modular tool registry.

## Frequently Asked Questions

### What triggers the lesson generation pipeline in OpenMAIC?

The pipeline triggers when the skill resolver in [`lib/server/agent-runtime/skill-handle-inference.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/skill-handle-inference.ts) detects a generation-related command in the user prompt (such as `slide-craft` or `stage-design`). This resolver extracts the skill name and invokes `runGenerationTool` with the appropriate payload, initiating the five-layer orchestration process.

### How does OpenMAIC handle crashes during lesson generation?

The system implements crash-resilience through the Dexie-based **media-generation store** in [`lib/store/media-generation.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/store/media-generation.ts). Because generation progress persists incrementally to IndexedDB, unfinished jobs retain their state across browser reloads. When the application restarts, the stage store rehydrates from disk, allowing users to resume generation exactly where the process interrupted.

### Can I add custom generation tools to the pipeline?

Yes. Developers can extend the pipeline by registering new tools in [`lib/server/agent-runtime/generation-tools.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/generation-tools.ts). This requires adding an entry to the `generationToolMap` dictionary with a unique `GenerationToolName` and an execution handler that conforms to the `runGenerationTool` interface. The orchestrator automatically routes matching skill requests to the new implementation without requiring changes to the parsing or persistence layers.

### What is the difference between the media-generation store and the stage store?

The **media-generation store** ([`lib/store/media-generation.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/store/media-generation.ts)) tracks granular, incrementally-updated job data including partial outlines and media URLs during active generation. The **stage store** ([`lib/store/stage-store.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/store/stage-store.ts)) holds the finalized lesson structure and the `generationComplete` flag that drives UI state transitions. The media store handles runtime progress while the stage store manages the authoritative lesson presentation state.