# OpenMAIC Runtime DSL vs Document DSL: Understanding the Two DSL Line Types

> Understand the difference between OpenMAIC's runtime DSL and document DSL. Learn how separate versioning ensures safe, phased migrations for session state and document content.

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

---

**OpenMAIC uses two distinct DSL lines—`runtimeDslVersion` for session state and `dslVersion` for document content—to enable independent versioning and safe, phased migrations.**

The OpenMAIC platform (THU-MAIC/OpenMAIC) separates versioning concerns between runtime infrastructure and content documents through two dedicated DSL version fields. This design allows the storage layer, frontend, and migration systems to evolve without forced lockstep updates.

## What Is the Runtime DSL Line?

The **runtime DSL line** tracks the schema version for session-level data structures. It appears as `runtimeDslVersion` in runtime session objects.

Key characteristics:

- **Field name:** `runtimeDslVersion`
- **Constant:** `RUNTIME_DSL_VERSION` (defined in `packages/@openmaic/dsl/src/version.ts`)
- **Managed by:** Storage layer automatically stamps it on session creation and updates
- **Validates:** Session fetching, migration checks, and runtime-level field compatibility

As implemented in `packages/@openmaic/storage/src/runtime/types.ts`, the runtime session type embeds this field to ensure the server can parse session state correctly.

```typescript
// Runtime DSL line automatically added by createSession()
import { RUNTIME_DSL_VERSION } from '@openmaic/dsl';
import { createSession } from '@openmaic/storage';

const session = await createSession({
  id: 'session-1',
  // Storage layer injects: runtimeDslVersion: RUNTIME_DSL_VERSION
});

console.log(session.runtimeDslVersion); // '0.1.0'

```

## What Is the Document DSL Line?

The **document DSL line** tracks the schema version for content documents including scenes, slides, and courses. It appears as `dslVersion` within the document payload itself.

Key characteristics:

- **Field name:** `dslVersion`
- **Constant:** `DSL_VERSION` (also from `packages/@openmaic/dsl/src/version.ts`)
- **Managed by:** Document authors and editors; part of the JSON payload
- **Validates:** Document loading, content editing, and document-level migrations

This line appears in migration tests at [`tests/document-store/migration.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/document-store/migration.test.ts), demonstrating how documents carry their own schema version independent of runtime sessions.

```typescript
// Document DSL line embedded in content payload
import { DSL_VERSION } from '@openmaic/dsl';

const slide = {
  id: 'slide-42',
  dslVersion: DSL_VERSION,  // Document-level DSL line
  title: 'Introduction',
  content: []
};

console.log(slide.dslVersion); // '0.1.0'

```

## Why OpenMAIC Maintains Two DSL Lines

The separation serves three architectural purposes:

1. **Independent evolution** — Runtime session fields can change (new authentication, session metadata) without rewriting stored documents. Document structures can change (new slide element types) without affecting session handling.

2. **Targeted migrations** — Migration code checks `runtimeDslVersion` for session upgrades and `dslVersion` for document upgrades independently. This prevents unnecessary full-data rewrites.

3. **Phased deployment safety** — Backend and frontend teams can ship changes at different cadences. A new runtime version rolls out without forcing immediate document migrations, and vice versa.

## Migration Behavior and Version Checking

The migration system in OpenMAIC compares stored versions against current constants defined in `packages/@openmaic/dsl/src/version.ts`:

| Check | Trigger | Example source |
|-------|---------|---------------|
| `runtimeDslVersion < RUNTIME_DSL_VERSION` | Session migration runs first | [`tests/runtime/chat-storage.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/runtime/chat-storage.test.ts) shows `FUTURE_VERSION` errors |
| `dslVersion < DSL_VERSION` | Document migration applied separately | [`tests/document-store/migration.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/document-store/migration.test.ts) |
| Both outdated | Sequential migration: runtime first, then document | Server-side validation in [`tests/agent-runtime/stage-detail-route.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/agent-runtime/stage-detail-route.test.ts) |

This sequential approach prevents accidental data loss when both layers need updates.

## Key Source Files for DSL Line Implementation

| File | Purpose |
|------|---------|
| `packages/@openmaic/dsl/src/version.ts` | Defines `DSL_VERSION`, `RUNTIME_DSL_VERSION`, and their key constants |
| `packages/@openmaic/storage/src/runtime/types.ts` | Runtime session type with `runtimeDslVersion` field |
| [`tests/document-store/migration.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/document-store/migration.test.ts) | Document DSL versioning in migration scenarios |
| [`tests/runtime/chat-storage.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/runtime/chat-storage.test.ts) | Runtime DSL version validation errors |
| [`tests/agent-runtime/stage-detail-route.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/agent-runtime/stage-detail-route.test.ts) | Server-side document DSL validation on POST requests |

## Summary

- OpenMAIC distinguishes **runtime DSL line** (`runtimeDslVersion`) for session state and **document DSL line** (`dslVersion`) for content documents
- The runtime line is storage-managed; the document line is payload-embedded
- Both versions derive from constants in `packages/@openmaic/dsl/src/version.ts`
- Independent versioning enables safer, granular migrations without forced data rewrites
- Migration checks evaluate runtime version first, then document version, maintaining data integrity

## Frequently Asked Questions

### Can the runtime DSL version and document DSL version differ?

Yes, by design. A session may use `runtimeDslVersion: '0.2.0'` while containing documents with `dslVersion: '0.1.0'`. The migration system handles each separately, upgrading documents only when explicitly needed. This flexibility is tested in [`tests/document-store/migration.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/document-store/migration.test.ts).

### What happens if a future DSL version is detected?

Runtime throws a `FUTURE_VERSION` error, as shown in [`tests/runtime/chat-storage.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/runtime/chat-storage.test.ts). This protects against data corruption when a newer client connects to an older server or when incorrect version stamps appear in persisted data.

### Who is responsible for updating each DSL line?

The **storage layer** automatically manages `runtimeDslVersion` through `createSession()` and related APIs. The **document author or editor** manages `dslVersion` as part of the content payload. Backend validation enforces correctness on write operations, per [`tests/agent-runtime/stage-detail-route.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/agent-runtime/stage-detail-route.test.ts).

### Why not use a single global version number?

A unified version would force unnecessary migrations. If runtime session handling adds a new field, every stored document would require rewriting even when unchanged. The dual-line approach minimizes migration scope and supports independent team ownership of runtime versus document features.