# OpenMAIC JSON Schema Artifacts for Non-TypeScript Consumers: Complete Guide

> Explore OpenMAIC JSON Schema artifacts stage.schema.json, scene.schema.json, and action.schema.json. Validate MAIC documents without TypeScript dependencies for any runtime.

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

---

**The @openmaic/dsl package provides three canonical JSON Schema files—[`stage.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/stage.schema.json), [`scene.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/scene.schema.json), and [`action.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/action.schema.json)—that enable any runtime to validate MAIC documents without TypeScript dependencies.**

The **OpenMAIC DSL** (Domain-Specific Language) is designed as a cross-platform slide-contract format for interactive educational content. While the source of truth lives in TypeScript, the project ships **language-neutral JSON Schema artifacts** that let Python, Go, JavaScript, or any other runtime validate MAIC documents against the exact same contract. This article examines the three schema files, their generation pipeline, and practical validation patterns for non-TS consumers.

## The Three Core JSON Schema Artifacts

The **@openmaic/dsl** package exports three interrelated schemas under the `schema/` directory. Each maps to a foundational type in the MAIC data model.

### stage.schema.json: Top-Level Lesson Container

**[`stage.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/stage.schema.json)** describes the root **Stage** object—the lesson skeleton that aggregates all content.

- **Contains**: Lesson metadata, whiteboard list, video manifest, scene references, and global settings
- **Generated from**: The `Stage` TypeScript interface via `gen-schema.mjs` (`Stage: 'stage.schema.json'`)
- **Source**: `/packages/@openmaic/dsl/scripts/gen-schema.mjs` lines 16–18

Non-TS consumers import it directly:

```javascript
import stageSchema from '@openmaic/dsl/schema/stage.schema.json' with { type: 'json' };

```

This pattern appears in `/packages/@openmaic/dsl/README.md` lines 95–97, which documents the standard import syntax for JSON modules.

### scene.schema.json: Canvas and Action Container

**[`scene.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/scene.schema.json)** defines the **Scene** object—a temporal canvas that groups slides with synchronized whiteboard actions.

- **Contains**: Slide array, background configuration, whiteboard action timeline, and the generic `Action` union reference
- **Generated from**: The `SerializedScene` interface via the same build script (`SerializedScene: 'scene.schema.json'`)

The schema captures the complete serialized form of a scene, including all playback-relevant state.

### action.schema.json: Playback Verb Taxonomy

**[`action.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/action.schema.json)** enumerates the **Action** union—every interactive verb the MAIC runtime understands.

- **Contains**: Discriminated union of all actions (spotlight, laser pointer, speech synthesis, widget interactions, pen strokes, etc.) with their required fields and `@default` annotations
- **Generated from**: The `Action` type definition (`Action: 'action.schema.json'`)

This schema uses JSON Schema's `oneOf` or `discriminator` patterns to enforce that each action object contains the correct discriminator field (`type`) and shape.

## Schema Generation Pipeline

The schemas are **not hand-authored**—they are generated at build time from the authoritative TypeScript sources. This guarantees zero drift between the TS types and the JSON Schema contract.

### Build-Time Generation with ts-json-schema-generator

In `/packages/@openmaic/dsl/scripts/gen-schema.mjs`, the generation logic maps type names to output filenames:

```javascript
// From gen-schema.mjs lines 16-18
const SCHEMA_MAP = {
  Stage: 'stage.schema.json',
  SerializedScene: 'scene.schema.json',
  Action: 'action.schema.json'
};

```

The script uses **ts-json-schema-generator** to:
1. Parse the TypeScript AST in `src/*.ts`
2. Extract JSDoc annotations (including `@default` values)
3. Emit strict JSON Schema v7+ files with `required` arrays, `additionalProperties` constraints, and discriminant mappings

### Package Export Configuration

The [`package.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/package.json) in `/packages/@openmaic/dsl/` declares explicit export maps for the schema files:

```json
{
  "exports": {
    "./schema/*": "./dist/schema/*"
  }
}

```

This allows consumers to use the clean import paths shown above rather than deep-linking into `node_modules`.

## Zero-Runtime-Dependency Validation

The schemas contain **no runtime dependencies**—they are pure JSON data files. Any standards-compliant validator can consume them.

### JavaScript/Node.js Validation with Ajv

```javascript
import Ajv from 'ajv';
import stageSchema from '@openmaic/dsl/schema/stage.schema.json' with { type: 'json' };
import sceneSchema from '@openmaic/dsl/schema/scene.schema.json' with { type: 'json' };
import actionSchema from '@openmaic/dsl/schema/action.schema.json' with { type: 'json' };

const ajv = new Ajv({ allErrors: true, strict: false });

const validateStage = ajv.compile(stageSchema);
const validateScene = ajv.compile(sceneSchema);
const validateAction = ajv.compile(actionSchema);

function validateMAIC(doc) {
  if (!validateStage(doc)) {
    console.error('Stage validation failed:', validateStage.errors);
    return false;
  }
  
  if (!validateScene(doc.scene)) {
    console.error('Scene validation failed:', validateScene.errors);
    return false;
  }
  
  for (const action of doc.scene.actions ?? []) {
    if (!validateAction(action)) {
      console.error('Action validation failed:', validateAction.errors);
      return false;
    }
  }
  
  return true;
}

```

### Python Validation with jsonschema

```python
import json
import jsonschema

# Load schemas from package or copy them into your project

with open('stage.schema.json') as f:
    stage_schema = json.load(f)
with open('scene.schema.json') as f:
    scene_schema = json.load(f)
with open('action.schema.json') as f:
    action_schema = json.load(f)

def validate_maic_document(doc: dict) -> None:
    """
    Validates a MAIC document against all three layers.
    Raises jsonschema.ValidationError on first failure.
    """
    # Validate root structure

    jsonschema.validate(instance=doc, schema=stage_schema)
    
    # Validate nested scene

    jsonschema.validate(instance=doc.get('scene', {}), schema=scene_schema)
    
    # Validate each action in the timeline

    for action in doc.get('scene', {}).get('actions', []):
        jsonschema.validate(instance=action, schema=action_schema)
    
    print("Document is valid MAIC")

```

## Cross-Language Contract Guarantees

The JSON Schema artifacts serve critical functions for polyglot MAIC implementations.

### Exact Shape Preservation

The schemas capture:
- **Required fields** via `required` arrays
- **Discriminated unions** via `oneOf` with `propertyName` discriminators
- **Default values** from JSDoc `@default` annotations
- **String literal unions** from TypeScript literal types
- **Nested object constraints** with `additionalProperties: false` where appropriate

### Version Stability

Each schema release corresponds to the `DSL_VERSION` constant defined in the source. When the TypeScript model changes, the build pipeline regenerates all three files atomically. This ensures that:

- Schema versions never lag behind the runtime implementation
- Non-TS consumers can pin to exact schema versions via npm semver
- Breaking changes in the contract trigger major version bumps in the package

### Alternative: In-Process Validators

For Node.js consumers who prefer direct function calls over schema compilation, `/packages/@openmaic/dsl/src/validate.ts` exports pre-compiled validators that mirror the schema logic. These use the same underlying types but skip the JSON Schema indirection—useful when bundle size matters less than validation speed.

## Summary

- **Three canonical schemas**: [`stage.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/stage.schema.json), [`scene.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/scene.schema.json), and [`action.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/action.schema.json) provide complete coverage of the MAIC data model
- **Build-time generation**: `gen-schema.mjs` in the dsl package produces these files from TypeScript sources using `ts-json-schema-generator`
- **Zero-dependency consumption**: Pure JSON files work with any validator—Ajv, Python's `jsonschema`, Go's `gojsonschema`, etc.
- **Version-locked contracts**: Schemas regenerate automatically with each build, maintaining parity with the `DSL_VERSION`
- **Flexible import paths**: Package exports in [`package.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/package.json) enable clean imports via `@openmaic/dsl/schema/*.schema.json`

## Frequently Asked Questions

### How do I import OpenMAIC schemas in a CommonJS project?

Use dynamic import or copy the schema files to your project. The package only ships ESM exports. For CommonJS, install the package and reference the files directly from `node_modules/@openmaic/dsl/dist/schema/`, or use `fs.readFileSync` to load the JSON. The schemas themselves are valid JSON and impose no module system requirements.

### Can I use these schemas with OpenAPI or AsyncAPI specifications?

Yes. The JSON Schema dialect (draft-07 or later) is compatible with OpenAPI 3.x schema objects. You can reference the schema files via `$ref` in OpenAPI components, or extract sub-schemas for specific action types. The [`action.schema.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/action.schema.json) in particular provides a complete union definition suitable for API request/response validation.

### What happens if I validate with an outdated schema version?

Validation will reject documents that use newer fields or action types introduced in later DSL versions. The schemas enforce `additionalProperties: false` on key objects, so unrecognized properties trigger validation errors. Always match your schema version to the `DSL_VERSION` declared in the documents you are validating—this field is available in the Stage header.

### Are the schemas sufficient for runtime type coercion?

No. JSON Schema validates *structure*, not *semantics*. The schemas ensure that a `spotlight` action has the required `targetId` string, but they do not verify that the ID points to an existing element in the scene graph. For full semantic validation, use the TypeScript runtime in `/packages/@openmaic/dsl/src/validate.ts` or implement equivalent logic in your target language.