The MDL runtime is the engine that turns your instruction files, schema, assets, and saved universe state into a playable game.
Every player action follows the same five-step cycle:
The AI doesn't return raw text. It returns a JSON object with specific fields that the renderer understands. This is what makes visual presentation possible.
| Field | Type | Purpose |
|---|---|---|
| narration | string | Prose description of what happens. Always present. |
| speaker | string | null | Who is speaking, or null for narration-only beats. |
| text | string | null | The spoken dialogue, or null. |
| background | string | null | Configured stock background/location id for ordinary beats, or null. The engine resolves morning/afternoon/evening/night stock art from `universeTime`. |
| foreground | string[] | Up to 2 visible non-MC foreground sprite IDs. Use an empty array to clear visible foreground sprites. |
| specialScene | object | null | Premium event illustration request or cached reuse. A non-empty `specialScene.description` requests image generation; null reuses the cached uid. |
| specialBackground | object | null | Reusable generated background request or cached reuse. A non-empty description requests a new background plate; null reuses the cached uid. |
| specialCharacter | object | null | Generated transparent character sprite request or cached reuse. It visually occupies one foreground slot while `foreground` remains configured sprite IDs. |
| specialChoices | object[] | null | Rare 2-4 option decision set for moments where each choice leads the next turn in a genuinely different direction. |
| music | string | null | Background track ID to play or keep playing; null means no active music. |
| sfx | string[] | Effect IDs: most are one-shot audio or brief visual pulses; particle preset ids stay visible for the full beat when a generated scene illustration is showing. |
| universeTime | string | In-world time; drives stock background variants when `background` is a known stock location id. |
The AI only sees a block-aligned slice of the stored conversation (assistant state turns on the current branch). The MGPT backend applies that window using the same rules as lib/prompt-block-window.ts:
Continuity beyond the visible window must live in presentation state (background, foreground, dialogue, time, etc.) and in the beats that remain in context.
Each player's save is called a universe. It contains:
Universes auto-save after every turn. Players can close the browser and return later — their story picks up from the last state. Players can also have multiple save slots.
Each universe carries a frozen generation contract derived from the hosted game workspace. That contract keeps gameplay stable for an existing save while still allowing package pushes to refresh affected universes through the explicit hosted sync path.
You author the hosted instructions, schema, and assets. MDL does not accept a client-supplied instruction string for text generation, and provider details stay inside the backend.
When a player loads your game, the client fetches /api/runtime-config, which returns:
gameId / gameSlug for hosted games (checkout and telemetry).Generation is server-owned: the client posts universe, statePointer, userInput, and optional requestId to /api/generate. The pointer is a client cursor, not a persisted universe field. MDL loads the stored timeline, truncates any future branch from the supplied pointer, ensures the frozen generation contract exists, forwards identifiers plus output/instruction flags to MGPT, then applies and persists the returned assistant output.
The AI only knows what's in the current context — your instructions, frozen contract, runtime context, and recent history. It doesn't have hidden memory or magic access to your asset library. If you want the AI to use a scene or sprite, describe it in your instruction files and keep the IDs visible in the schema/assets.