# How the Blueprint-Sessions System Creates and Applies Session Templates in OpenWork

> Learn how OpenWorks blueprint-sessions system creates and applies session templates. Discover how it normalizes JSON to typed objects and injects materialized sessions.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: internals
- Published: 2026-08-22

---

**The blueprint-sessions system in OpenWork creates session templates by normalizing raw JSON configuration into typed objects via `normalizeBlueprintSessionTemplates`, and applies them by sanitizing stale data and injecting fresh materialized sessions through `applyMaterializedBlueprintSessions`.**

The blueprint-sessions subsystem powers template-based session management in the [different-ai/openwork](https://github.com/different-ai/openwork) repository. Located in [`apps/server/src/blueprint-sessions.ts`](https://github.com/different-ai/openwork/blob/main/apps/server/src/blueprint-sessions.ts), this system bridges raw configuration files and the UI by converting blueprint definitions into concrete, interactive sessions. Understanding this flow is essential for extending OpenWork's templating capabilities or debugging session initialization issues.

## Creating Session Templates from Raw Configuration

The creation process transforms untyped JSON into validated `BlueprintSessionTemplate` objects through defensive normalization.

### Extracting the Blueprint Block

The entry point `normalizeBlueprintSessionTemplates` first extracts the `blueprint` object from the overall OpenWork configuration using `readRecord(openwork?.blueprint)`. It then iterates over the `sessions` array, safely converting each raw entry into a plain object with `readRecord(value)` and discarding malformed items that fail validation.

### Normalizing Template Fields

Each session undergoes strict field normalization:
- **`title`** – Trimmed to a string, defaulting to "Template session N" when missing or empty.
- **`messages`** – Processed through `normalizeMessage`, which guarantees a valid `role` ("assistant" or "user") and ensures non-empty `text` content.
- **`id`** – Uses the supplied identifier or auto-generates `template-session-N` based on array index.
- **`openOnFirstLoad`** – Boolean flag copied verbatim when true.

The function filters out any null results, returning a clean array of typed templates ready for the frontend.

## Reading Materialized Sessions

Once templates are instantiated into actual sessions, `readMaterializedBlueprintSessions` retrieves the concrete mappings. This function mirrors the creation pattern but operates on `blueprint.materialized.sessions.items`, returning plain objects containing `{templateId, sessionId}` pairs. It discards entries lacking required fields, ensuring the UI only receives valid session references.

## Applying Materialized Sessions to Configuration

When persisting concrete sessions back to the configuration, the system follows a sanitization-first approach through `applyMaterializedBlueprintSessions`.

### Sanitizing Stale Data

The function first calls `sanitizeOpenworkTemplateConfig` to clone the configuration object and delete any existing `materialized.sessions` data. This prevents stale template references from accumulating and ensures a clean slate for new materializations.

### Injecting New Session Data

After sanitization, the system reads or creates the `blueprint.materialized` block and injects a new `sessions` object containing:
- A `hydratedAt` timestamp marking the materialization time
- A shallow copy of the supplied `items` array containing the template-to-session mappings

The modified `openwork` object now carries the freshly materialized sessions, ready for persistence or client transmission.

## Code Examples

### Creating Session Templates from Raw Config

```typescript
import { normalizeBlueprintSessionTemplates } from "@/blueprint-sessions";

const rawOpenwork = {
  blueprint: {
    sessions: [
      { id: "welcome", title: "Welcome", messages: [{ role: "assistant", text: "Hi!" }] },
      { title: "Untitled", messages: [{ role: "user", text: "Hello" }] }
    ],
  },
};

const templates = normalizeBlueprintSessionTemplates(rawOpenwork);
// → [
//   { id: "welcome", title: "Welcome", messages: [{ role: "assistant", text: "Hi!" }], openOnFirstLoad: false },
//   { id: "template-session-1", title: "Untitled", messages: [{ role: "user", text: "Hello" }], openOnFirstLoad: false }
// ]

```

### Applying Materialized Sessions

```typescript
import { applyMaterializedBlueprintSessions } from "@/blueprint-sessions";

const materialised = [
  { templateId: "welcome", sessionId: "session-abc123" },
  { templateId: "template-session-1", sessionId: "session-def456" }
];

const updatedOpenwork = applyMaterializedBlueprintSessions(rawOpenwork, materialised, Date.now());
// updatedOpenwork.blueprint.materialized.sessions.hydratedAt contains the timestamp
// updatedOpenwork.blueprint.materialized.sessions.items contains the mappings

```

### Reading Materialized Sessions Later

```typescript
import { readMaterializedBlueprintSessions } from "@/blueprint-sessions";

const sessions = readMaterializedBlueprintSessions(updatedOpenwork);
// → [{ templateId: "welcome", sessionId: "session-abc123" }, …]

```

## Summary

- **Normalization happens in `normalizeBlueprintSessionTemplates`** located in [`apps/server/src/blueprint-sessions.ts`](https://github.com/different-ai/openwork/blob/main/apps/server/src/blueprint-sessions.ts), which validates and types raw JSON configuration.
- **Default values protect against malformed input**, including auto-generated IDs and fallback titles for incomplete templates.
- **Materialization separates templates from instances**, tracking concrete sessions through `{templateId, sessionId}` mappings in the `materialized` configuration block.
- **Sanitization prevents data corruption** by cloning the config and removing stale session data before injecting new materializations.

## Frequently Asked Questions

### What happens when a session template lacks a title?

The normalization process assigns a default title formatted as "Template session N" where N represents the item's index in the sessions array. This ensures every template has a displayable identifier even when the raw configuration omits the title field.

### How does the system handle invalid or malformed session entries?

During the `normalizeBlueprintSessionTemplates` execution, each raw entry passes through `readRecord(value)` for safe conversion. Entries that fail validation or return null are filtered out of the final array, preventing corrupt data from reaching the UI.

### What is the difference between blueprint session templates and materialized sessions?

Blueprint session templates define the structure and initial content of reusable sessions, while materialized sessions represent concrete instances created from those templates. The system stores materialized sessions in `blueprint.materialized.sessions.items` as pairs of template IDs and generated session IDs, tracking when they were hydrated via the `hydratedAt` timestamp.

### Where is the blueprint-sessions logic implemented in the OpenWork codebase?

The core implementation resides in [`apps/server/src/blueprint-sessions.ts`](https://github.com/different-ai/openwork/blob/main/apps/server/src/blueprint-sessions.ts), which exports the normalization, reading, and application functions. The server entry point in [`apps/server/src/server.ts`](https://github.com/different-ai/openwork/blob/main/apps/server/src/server.ts) consumes these utilities when serving workspace data, while [`apps/server/src/blueprint-sessions.test.ts`](https://github.com/different-ai/openwork/blob/main/apps/server/src/blueprint-sessions.test.ts) contains the test suite guarding against regressions.