# How to Use the OpenMAIC DSL SDK for Type-Safe Lesson Documents

> Discover the OpenMAIC DSL SDK a zero-dependency TypeScript library. Master type-safe lesson documents with validation, normalization, migration, and asset enumeration APIs.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: how-to-guide
- Published: 2026-09-09

---

**The OpenMAIC DSL SDK is a zero-dependency TypeScript library that provides the complete contract for MAIC ecosystem object models, including validation, normalization, migration, and asset enumeration APIs for lesson stage documents.**

The OpenMAIC DSL SDK (`@openmaic/dsl`) defines the universal object model that powers the entire MAIC ecosystem—from renderers to importers to storage systems. As a pure, runtime-dependency-free TypeScript package, it ensures type safety and structural integrity across all lesson documents without requiring external libraries.

## Installing the OpenMAIC DSL SDK

Install the package via npm or pnpm to begin working with the DSL contracts:

```bash
npm install @openmaic/dsl

# or

pnpm add @openmaic/dsl

```

After installation, import types and utilities directly from the package root:

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

import {
  validateStage,
  normalizeStage,
  DSL_VERSION,
  migrate,
  enumerateAssetManifest,
} from '@openmaic/dsl';

```

## Core Module Architecture

The OpenMAIC DSL SDK is organized into focused modules under `packages/@openmaic/dsl/src/`, each handling specific aspects of the lesson document contract.

### slides.ts: Slide Object Models

The [`slides.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/slides.ts) module defines the complete slide element hierarchy, including shapes, text, images, charts, tables, and animations. Key exports include `Slide`, `PPTElement`, `ElementTypes`, and `ShapePathFormulasKeys`. These types describe every visual element that can appear within a slide scene.

### stage.ts: Lesson Skeletons

In [`stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/stage.ts), the SDK defines the `Stage` type and generic `Scene<TAction, TContent>` structures. This module exports `SceneType`, `SlideContent`, and `QuizContent`, establishing the lesson skeleton that connects scenes, whiteboards, video manifests, and interactive content.

### action.ts: Playback Verbs

The [`action.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/action.ts) module contains the `Action` union type and `ActionType` enum, defining playback verbs such as speech, spotlight, laser pointer, discussion triggers, and widget interactions. The `SYNC_ACTIONS` constant categorizes actions requiring synchronous execution.

### guards.ts: Type Discrimination

For runtime type safety, [`guards.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/guards.ts) provides type guards like `isTextElement` and `isSlideContent`, along with the `PPT_ELEMENT_TYPES` array. These utilities safely discriminate between element and content variants without external validation libraries.

## Working with Stage Documents

The OpenMAIC DSL SDK provides three critical workflows for managing stage documents: validation, normalization, and version migration.

### Validating Stage Documents

When ingesting user-generated content or importer output, use `validateStage` from [`validate.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/validate.ts) to perform zero-dependency structural validation. This function walks the object graph and collects all schema violations without modifying the input.

```typescript
import { validateStage } from '@openmaic/dsl';

const result = validateStage(stageDoc);

if (!result.valid) {
  // result.errors contains { path, message } objects
  throw new Error(
    result.errors.map(e => `${e.path}: ${e.message}`).join('; ')
  );
}

```

The [`validate.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/validate.ts) module also exports `validateScene` and `validateAction` for granular validation of document subtrees.

### Normalizing Incomplete Documents

Use `normalizeStage` from [`normalize.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/normalize.ts) to automatically fill missing required fields, derive geometry calculations, and apply `ELEMENT_DEFAULTS`. This pure function fails loudly on malformed fields while standardizing document structure.

```typescript
import { normalizeStage } from '@openmaic/dsl';

const normalized = normalizeStage(rawStage);
// Returns a Stage with all required fields populated

```

The normalization process handles element positioning, default styling, and content structure without side effects or external dependencies.

### Migrating Legacy Versions

The DSL contract evolves independently of the npm package version. Use the migration ladder in [`version.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/version.ts) to upgrade legacy documents to the current `DSL_VERSION`.

```typescript
import { DSL_VERSION, migrate } from '@openmaic/dsl';

const upgraded = migrate(oldStage);
console.log('Upgraded to DSL version', DSL_VERSION);

```

The [`version.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/version.ts) module also exports `dslVersionOf` and `needsMigration` for inspecting document metadata before attempting migration.

## Enumerating Assets

The [`asset-manifest.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/asset-manifest.ts) module provides zero-I/O asset enumeration. The `enumerateAssetManifest` function walks a stage document and collects all media references—including image sources, audio URLs, video manifests, and speech audio IDs—returning an `AssetManifest` with complete metadata.

```typescript
import { enumerateAssetManifest } from '@openmaic/dsl';

const manifest = enumerateAssetManifest(stageDoc, {
  metadata(ref, kind) {
    // Optionally enrich with size, mime type, duration, etc.
    return { size: ref.length, mime: 'image/png' };
  },
});

console.log(manifest.entries);
// Array of all asset references with paths and kinds

```

This utility enables pre-flight checks, dependency validation, and bulk upload preparation without loading actual media files.

## Integrating with AI Agents

The OpenMAIC DSL SDK extends beyond static types to provide runtime tools for AI agents. Located in [`lib/server/agent-runtime/dsl-tools.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/dsl-tools.ts), the `buildDslCourseTools()` function constructs three high-level tools that expose the DSL to AI runtimes.

### Available Agent Tools

The SDK automatically registers these tools for agent consumption:

**`read_stage`** – Returns subtrees of a stage document in `tree`, `source`, or `text` views. Defined by `READ_COURSE_SCHEMA` at line 33 of [`dsl-tools.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/dsl-tools.ts).

**`patch_stage`** – Atomically patches single scenes using JSON-Pointer operations (set, remove, add/delete elements, string replacement). Schema defined at line 94 of [`dsl-tools.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/dsl-tools.ts) as `PATCH_COURSE_SCHEMA`.

**`grep_stage`** – Performs case-insensitive literal search (NFKC-normalized) across the entire stage, returning hit snippets and continuation cursors. Schema defined at line 111 as `GREP_COURSE_SCHEMA`.

These tools rely on the same pure SDK types and validators used throughout the platform, ensuring consistency between AI-generated modifications and persisted documents.

## Summary

- **The OpenMAIC DSL SDK** (`@openmaic/dsl`) provides zero-dependency TypeScript contracts for the entire MAIC ecosystem.
- **Core modules** in `src/` define slides ([`slides.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/slides.ts)), stage structures ([`stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/stage.ts)), actions ([`action.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/action.ts)), and type guards ([`guards.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/guards.ts)).
- **Validation and normalization** via `validateStage` and `normalizeStage` ensure document integrity without external libraries.
- **Version migration** using `migrate` and `DSL_VERSION` handles evolving schemas across document lifetimes.
- **Asset enumeration** with `enumerateAssetManifest` collects all media references without I/O operations.
- **AI integration** through `buildDslCourseTools()` exposes `read_stage`, `patch_stage`, and `grep_stage` to agent runtimes.

## Frequently Asked Questions

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

The OpenMAIC DSL SDK defines the complete object model for lesson documents in the MAIC ecosystem. It provides TypeScript types, structural validators, normalizers, and migration utilities that ensure consistency across renderers, importers, storage systems, and AI agents. The SDK contains zero runtime dependencies, making it suitable for both frontend and backend consumption.

### How do I validate a stage document against the schema?

Import `validateStage` from `@openmaic/dsl` and pass your document to receive a validation result. The function returns an object with a `valid` boolean and an `errors` array containing path and message details for each violation. This validation occurs in pure TypeScript without requiring JSON Schema validators or external dependencies.

### Can the OpenMAIC DSL SDK handle document versioning?

Yes. The SDK includes a comprehensive migration system in [`version.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/version.ts) that manages the `DSL_VERSION` lifecycle. Use `needsMigration()` to check if a document requires updating, then call `migrate()` to transform legacy documents to the current schema version. This migration ladder ensures backward compatibility as the DSL contract evolves independently of the npm package version.

### How do AI agents interact with documents through the SDK?

AI agents interact with documents through three specialized tools built by `buildDslCourseTools()` in [`lib/server/agent-runtime/dsl-tools.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/dsl-tools.ts). These include `read_stage` for document inspection, `patch_stage` for atomic modifications using JSON-Pointer operations, and `grep_stage` for content searching. All tools use the same pure SDK validators and types, maintaining consistency between AI operations and persisted data.