Contents
4. Tree
{
"id": "01J8ZC3YV3N9K5T2W7QF4XH2MB",
"title": "Marie Character Study",
"description": "Exploring Marie's voice across models",
"mode": "dialogue",
"systemContext": "You are…",
"rootNodeIds": ["n-root"],
"currentNodeId": "n-b3k9",
"createdAt": "2026-06-30T10:00:00Z",
"updatedAt": "2026-07-08T21:10:00Z",
"nodes": { "n-root": { }, "n-a7x2": { } },
"edges": [ ],
"tags": [ { "name": "research", "color": "#7A9E7E" } ],
"extensions": {}
}
| Field | Type | Req | Notes |
|---|---|---|---|
id |
string | MUST | |
title |
string | MUST | May be empty. |
description |
string | MAY | |
mode |
string | SHOULD | "dialogue" | "buffer"; unknown values allowed, importers map to their nearest mode. Default "dialogue". |
systemContext |
string | MAY | Tree-level system prompt. Exporters SHOULD offer excluding it (it often carries private material). |
rootNodeIds |
string[] | MUST | ≥ 1 entry. Multi-root trees list every root. |
currentNodeId |
string | MAY | The selected/active node at export time. |
createdAt / updatedAt |
timestamp | SHOULD | |
nodes |
map<id, Node> | MUST | Flat map; topology lives in edges. |
edges |
Edge[] | MUST | May be empty only for single-node trees. |
tags |
TagDef[] | MAY | Tree-level tag definitions (name MUST, color MAY). Nodes reference tags by name. |
agents |
map | MAY | Tree-scoped agent registry; overrides document-level on ID conflict. |
extensions |
object | MAY |
4.1 Structural invariants
A valid tree satisfies (importers SHOULD validate and repair, not crash):
- Every
rootNodeIdsentry andcurrentNodeIdresolves to a key innodes. - Every edge's
targetNodeIdand everysources[].nodeIdresolve innodes. - No node is the target of more than one
continuationedge unless the format consumer supports DAGs; strict-tree importers MUST keep the first continuation edge (in array order) and MAY drop or demote the rest. - The continuation-edge graph is acyclic.
- Roots are exactly the nodes that are not the target of any continuation edge.
(
rootNodeIdsis asserted redundantly so damaged files are repairable.)
4.2 Sibling order
Sibling order is meaningful in every surveyed loom. The order of edges in the
edges array defines sibling order among continuations that share a source.
Exporters MUST emit edges in intended sibling order; importers MUST preserve it.
4.3 Node
{
"id": "n-a7x2",
"content": [ { "type": "text", "text": "The rain had a grammar of its own…" } ],
"author": { "role": "model", "agentId": "agent-claude-creative" },
"createdAt": "2026-07-01T12:30:05Z",
"editedFrom": "n-a7x1",
"meta": {
"bookmarked": true,
"bookmarkLabel": "tone shift",
"pruned": false,
"excluded": false,
"tags": ["research"],
"rating": 1,
"note": "this is where it gets good"
},
"generation": { },
"extensions": {}
}
| Field | Type | Req | Notes |
|---|---|---|---|
id |
string | MUST | |
content |
ContentBlock[] | MUST | Ordered blocks; a plain-text node is a one-element array. |
author |
Author | MUST | § below. |
createdAt |
timestamp | SHOULD | |
editedFrom |
string | MAY | Node ID this node was created by editing. Edit lineage, not topology. |
meta |
object | MAY | All subfields optional; absent = defaults below. |
generation |
Generation | MAY | § 5. Only meaningful when author.role is model or mixed. |
extensions |
object | MAY |
Author — { "role": "human" | "model" | "system" | "mixed", "agentId"?: string, "name"?: string }.
mixed means human-edited model output (socketteer's source: "mixed").
agentId references an agent registry entry (§ 4.5); name is a fallback
display label when no registry entry exists.
ContentBlock — discriminated union on type:
{ "type": "text", "text": string }{ "type": "image", "ref": string, "mimeType": string, "width"?: number, "height"?: number, "altText"?: string }{ "type": "audio", "ref": string, "mimeType": string, "durationMs"?: number, "transcript"?: string }
ref is either a data: URI (self-contained documents) or a relative path
inside an OpenLoom bundle — a ZIP whose root contains tree.openloom plus
referenced media files. Exporters SHOULD prefer bundles above ~1 MB of media.
Unknown block types MUST be preserved on re-export and rendered as a
placeholder. Text-only importers MAY substitute altText/transcript.
meta defaults: bookmarked false, pruned false (soft-hidden branch),
excluded false (omitted from model context), tags empty, rating absent
(integer, negative = bad, positive = good — carries MiniLoom-style preference
signal), note absent (free-text annotation; richer annotations should use
annotation edges instead).
4.4 Edge
Topology is an explicit list of directed hyperedges — the superset that
children arrays, parent pointers, and Aspen Grove's multi-source edges all
project into:
{
"id": "e-1",
"type": "continuation",
"sources": [ { "nodeId": "n-root", "role": "primary" } ],
"targetNodeId": "n-a7x2",
"createdAt": "2026-07-01T12:30:05Z",
"extensions": {}
}
| Field | Type | Req | Notes |
|---|---|---|---|
id |
string | SHOULD | Importers mint one if absent. |
type |
string | MUST | "continuation" (context-bearing traversal) or "annotation" (attached note, excluded from context by default). Unknown types are preserved but treated as annotations for traversal. |
sources |
Source[] | MUST | ≥ 1. role ∈ "primary" | "context" | "instruction"; default "primary". Multi-source = hyperedge. |
targetNodeId |
string | MUST | |
createdAt |
timestamp | MAY |
Simple parent→child links are single-source primary continuation edges.
Strict-tree importers MUST use the primary source as the parent and MAY
surface other sources as annotations.
4.5 Agent registry
Attribution beyond a role enum, without forcing every file to carry it:
"agents": {
"agent-claude-creative": {
"name": "Claude Creative",
"type": "model",
"modelRef": "openrouter:anthropic/claude-sonnet-4.5",
"configuration": { "temperature": 1.0, "systemPrompt": "…" }
},
"agent-asher": { "name": "Asher", "type": "human" }
}
name and type ("human" | "model") are required per entry; modelRef
({provider}:{identifier}) and configuration (free-form; recognized keys:
systemPrompt, temperature, maxTokens, stopSequences) are optional.
Exporters SHOULD offer excluding configuration.systemPrompt (private
material). Importers map unknown agents to local agents or plain labels.
