Intrinsic Labs

OpenLoom

A protocol for loom interfaces

Current Version: 2.0 (draft)

← Aspen Grove

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 rootNodeIds entry and currentNodeId resolves to a key in nodes.
  • Every edge's targetNodeId and every sources[].nodeId resolve in nodes.
  • No node is the target of more than one continuation edge 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. (rootNodeIds is 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.