# OpenMAIC DSL Contract: The 8 Core Primitives Explained

> Discover the 8 core primitives in the OpenMAIC DSL contract: Stage, SceneCore, Action, Slide, QuizContent, AssetMeta, and RuntimeSession. Understand the stage-first data model.

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

---

**The OpenMAIC DSL contract defines eight core primitives—Stage, SceneCore, Action, Slide, SlideContent, QuizContent, AssetMeta/BinaryBlob, and RuntimeSession—that form the stage-first data model used by the entire platform.**

The **OpenMAIC DSL contract** is the foundational TypeScript-based specification that powers the OpenMAIC learning platform. Exported from the `@openmaic/dsl` package, this contract serves as the single source of truth for the editor, runtime, storage layer, and all APIs. Every component in the system builds upon a small set of carefully designed primitives.

## Understanding the Stage-First Architecture

OpenMAIC adopts a **stage-first** design philosophy. A `Stage` represents the complete learning unit—the root container that holds everything else. This approach ensures that serialization, versioning, and cross-platform compatibility remain straightforward regardless of how complex the interactive content becomes.

The primitives follow a clear containment hierarchy:

- **Stage** → contains **SceneCore** instances
- **SceneCore** → bundles **Action** objects and binds to a **Slide**
- **Slide** → renders **SlideContent** elements
- **RuntimeSession** → tracks mutable state during user interaction

## The 8 Core Primitives in OpenMAIC

### Stage

The **Stage** primitive is the root container defined in [`src/schema-roots.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/schema-roots.ts). It stores metadata (title, description, tags), an array of scenes, and optional runtime configuration including voice settings, agent definitions, and video manifests.

```typescript
// From src/schema-roots.ts
interface Stage {
  id: string;
  title: string;
  description?: string;
  tags?: string[];
  scenes: SceneCore[];
  voice?: VoiceConfig;
  agents?: AgentConfig[];
  videoManifest?: VideoManifest;
  version: number;
}

```

### SceneCore<TAction = Action>

**SceneCore** is the basic unit of a stage, also defined in [`src/schema-roots.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/schema-roots.ts). It uses a generic parameter to carry the exact action type, enabling type-safe extensions of the DSL. Each scene groups actions that apply to a single slide.

```typescript
// From src/schema-roots.ts
interface SceneCore<TAction = Action> {
  id: string;
  slide: Slide;
  actions: TAction[];
  duration?: number;
  transition?: TransitionConfig;
}

```

### Action and Concrete Sub-types

**Action** primitives represent the atomic operations driving interactivity. Defined in [`src/action.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/action.ts), the DSL provides a rich hierarchy including:

- `SpotlightAction` — highlight specific elements
- `LaserAction` — pointer annotations
- `SpeechAction` — voice narration
- `WbDrawShapeAction` — whiteboard drawing
- `PlayVideoAction` — media playback
- `DiscussionAction` — collaborative prompts
- `WidgetSetStateAction` — interactive component updates

Each action carries the precise data needed for client-side rendering and execution.

```typescript
// From src/action.ts
interface SpotlightAction {
  type: 'spotlight';
  target: ElementTarget;
  duration: number;
  intensity?: number;
}

```

### Slide

The **Slide** primitive in [`src/slide.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/slide.ts) defines the visual representation of a scene. It contains background properties, drawable elements, and optional theming data.

```typescript
// From src/slide.ts
interface Slide {
  background: BackgroundConfig;
  elements: SlideContent[];
  theme?: ThemeConfig;
  layout?: LayoutConfig;
}

```

### SlideContent

**SlideContent** is the union type of all drawable elements, defined in [`src/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/stage.ts). The DSL enumerates every possible visual component:

- `PPTImageElement` — raster images
- `PPTShapeElement` — vector shapes
- `PPTCodeElement` — syntax-highlighted code blocks
- `PPTVideoElement` — embedded video
- `PPTAudioElement` — audio embeds
- `PPTTextElement` — rich text
- `PPTIframeElement` — external web content

### QuizContent

**QuizContent** is a specialized slide type for assessments, also defined in [`src/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/stage.ts). It extends the base slide structure with question arrays, scoring logic, and feedback mechanisms.

```typescript
// From src/stage.ts
interface QuizContent extends Slide {
  type: 'quiz';
  questions: Question[];
  shuffleOptions?: boolean;
  allowRetry?: boolean;
  feedbackMode: 'immediate' | 'deferred';
}

```

### AssetMeta and BinaryBlob

The **AssetMeta** and **BinaryBlob** primitives in [`src/storage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/storage.ts) define the minimal storage contract for external resources. The DSL specifies only three required operations—`put`, `resolve`, and `remove`—leaving concrete implementations to the storage package.

```typescript
// From src/storage.ts
interface AssetMeta {
  id: string;
  mimeType: string;
  size: number;
  checksum: string;
}

interface BinaryBlob {
  data: ArrayBuffer;
  meta: AssetMeta;
}

interface StorageContract {
  put(blob: BinaryBlob): Promise<AssetMeta>;
  resolve(id: string): Promise<BinaryBlob>;
  remove(id: string): Promise<void>;
}

```

### RuntimeSession

**RuntimeSession** in [`src/runtime.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/runtime.ts) is the mutable runtime counterpart to the immutable `Stage`. It adds version tracking and maintains the client's working state including current position, playback status, and user interactions.

```typescript
// From src/runtime.ts
interface RuntimeSession extends RuntimeVersioned {
  runtimeDslVersion: string;
  stage: Stage;
  state: RuntimeState;
}

interface RuntimeState {
  currentScene: string;
  playback: {
    paused: boolean;
    speed: number;
    position?: number;
  };
  userState?: Record<string, unknown>;
}

```

## Working with the Primitives: Practical Example

The following example demonstrates how the core primitives compose to create a complete learning unit:

```typescript
import { Stage, SceneCore, Action, Slide, RuntimeSession } from '@openmaic/dsl';

// Define a slide with visual content
const slide: Slide = {
  background: { color: '#f5f5f5' },
  elements: [
    {
      type: 'shape',
      id: 'shape-1',
      shape: 'circle',
      x: 0.5,
      y: 0.5,
      width: 0.2,
      height: 0.2,
      style: { fill: '#e74c3c', stroke: '#c0392b' },
    },
  ],
};

// Create an action that spotlights the element
const spotlightAction: Action = {
  type: 'spotlight',
  target: { kind: 'element', id: 'shape-1' },
  duration: 3.5,
  intensity: 0.8,
};

// Bundle into a scene
const scene: SceneCore = {
  id: 'intro-scene',
  slide,
  actions: [spotlightAction],
  duration: 10,
};

// Assemble the complete stage
const demoStage: Stage = {
  id: 'circles-intro',
  title: 'Introduction to Geometric Shapes',
  description: 'Interactive exploration of basic shapes',
  scenes: [scene],
  version: 1,
};

// Runtime representation for active session
const activeSession: RuntimeSession = {
  runtimeDslVersion: '1.0.0',
  stage: demoStage,
  state: {
    currentScene: 'intro-scene',
    playback: { paused: false, speed: 1 },
  },
};

```

## Key Source Files in the OpenMAIC DSL Contract

| File | Purpose | Location |
|:---|:---|:---|
| [`src/schema-roots.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/schema-roots.ts) | Central definitions of Stage, SceneCore, and related root types | `packages/@openmaic/dsl/src/schema-roots.ts` |
| [`src/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/stage.ts) | Detailed Stage interfaces, slide types, and quiz structures | `packages/@openmaic/dsl/src/stage.ts` |
| [`src/slides.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/slides.ts) | All slide element definitions | `packages/@openmaic/dsl/src/slides.ts` |
| [`src/action.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/action.ts) | Action hierarchy and concrete implementations | `packages/@openmaic/dsl/src/action.ts` |
| [`src/runtime.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/runtime.ts) | RuntimeSession and mutable state contracts | `packages/@openmaic/dsl/src/runtime.ts` |
| [`src/storage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/storage.ts) | AssetMeta, BinaryBlob, and storage contracts | `packages/@openmaic/dsl/src/storage.ts` |

## Summary

The **OpenMAIC DSL contract** establishes a rigorous, type-safe foundation for interactive learning content through eight core primitives:

- **Stage** — the root learning unit container
- **SceneCore** — the generic scene bundling actions and slides
- **Action** — atomic interactivity operations with rich sub-types
- **Slide** — visual presentation layer
- **SlideContent** — union of all drawable element types
- **QuizContent** — assessment-specialized slide variant
- **AssetMeta/BinaryBlob** — minimal external resource contracts
- **RuntimeSession** — mutable runtime state tracking

All higher-level features—including voice design, multi-agent configurations, video manifests, and problem-based learning data—extend these primitives rather than introducing parallel structures. This design ensures consistency across the OpenMAIC editor, runtime engine, storage backends, and API surfaces.

## Frequently Asked Questions

### What is the OpenMAIC DSL contract used for?

The **OpenMAIC DSL contract** defines the canonical data model that all platform components use to represent interactive learning content. It enables seamless serialization, version migration, and cross-platform compatibility by providing a single, type-safe specification in TypeScript.

### How does SceneCore use generics in the OpenMAIC DSL?

`SceneCore<TAction = Action>` uses a generic parameter with a default value to allow type-safe extensions. Custom DSL variants can substitute constrained action types while maintaining full IntelliSense and compile-time verification without breaking existing code.

### Where are actions defined in the OpenMAIC source code?

All action types reside in [`src/action.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/action.ts) within the `@openmaic/dsl` package. The file exports both the base `Action` type and concrete implementations like `SpotlightAction`, `LaserAction`, and `WbDrawShapeAction`, each with specific payload schemas.

### What distinguishes RuntimeSession from Stage in OpenMAIC?

**Stage** captures the immutable, authored content of a learning unit, while **RuntimeSession** tracks the mutable state during active user interaction—including current position, playback settings, and accumulated user responses. The runtime version adds `runtimeDslVersion` for compatibility checking.