pleach
Architecture

Concept clusters

Seven cluster triplets organize the runtime — session/turn/row on top, then execution-graph, routing, audit-ledger, lifecycle, and persistence one click in.

This page is the concept map. Every other doc page is the deep dive on one of the concepts named here.

The substrate organizes around clusters of three. One triplet covers the whole runtime — session, turn, row — and reduces to the same primitive used everywhere else: an append-only typed audit row keyed by turnId. Six more cluster triplets sit one click in. Each one is what the substrate uses to do something specific: run a turn, route a call, record a call, compose work across spawns, advance over time, or survive a restart.

If you read the glossary entry on the name: each cluster triplet is a way the lattice carries one weight a single streamText call cannot. Routing, audit, lifecycle, persistence — different forces, same hedge.

The substrate-wide triplet

Everything else reduces to these. The homepage opens with this triplet; the docs index repeats it; every cluster below is built out of one of them.

  • Session. Long-lived state for one user × one product surface. Channels, storage, family-lock, and the event log all hang off it. Mint with runtime.sessions.create(); resume by id across processes and clients via version-vector sync. See SessionRuntime.
  • Turn. One user-message-in / one-answer-out cycle. Walks the four-stage lattice — anchor-plantool-loopsynthesizepost-turn — under singleton-synthesize discipline so exactly one final answer fires per turn. See Turn lifecycle.
  • AuditableCall row. One append-only typed row per LLM call, keyed by turnId. Carries tenantId, toolName, subagentDepth, modelId, and tokenUsage. The grain every cost rollup, compliance query, and replay reads from. See The AuditableCall row.

The six cluster triplets

Each cluster lives on a host page that walks the three concepts as parallel bullets. Sibling concept pages open with a one- paragraph pointer to the cluster framing. The clusters are ordered roughly by where they fire in a turn — graph schedules work, the routing cluster picks a model, the audit cluster records the call, the composing-agents cluster spawns child work, the runtime-lifecycle cluster advances and persists, and the state cluster carries everything across restarts.

Execution-graph cluster

The per-turn execution substrate. Lives inside the lattice. Full walk in Architecture.

  • Graph. Declarative topology — nodes wired to channels, edges constrained to the four-stage lattice. See Graph.
  • Node. An async function plus typed StateGraphNodeMetadata declaring stageId, acceptsSeam, subscribes, and writes. See Nodes.
  • Channel. Typed reactive state slot. Six kinds with defined concurrent-write semantics and a checkpoint() / restore() pair. See Channels.
  • Engine. The engine/ superstep scheduler (SuperstepRunner) that runs the compiled graph — fires triggered nodes in parallel, accumulates their writes, and commits channel updates atomically per step. Deterministic and race-free by construction; also owns retry, abort composition, and graph↔session state sync. See Architecture → execution-graph cluster.

Routing cluster

Decides which model fires for which kind of call, and pins what stays locked across the session. Lives between the execution graph and the LLM transport. Full walk in Family-locked routing.

  • CallClass. Four-bucket taxonomy every LLM call declares — utility, reasoning, converse, synthesize. See Call classes.
  • Seam. Per-call-class factory that builds a ProviderSeam<C>. Four factories live in src/graph/seams/. See Seams.
  • Family-lock. Session-start lock on one ProviderFamily and one Transport. See Family-locked routing.

Audit-ledger cluster

The write side. The row is the grain; the ledger is the write path; the chain is the after-the-fact-tamper detector. Full walk in Audit ledger.

  • AuditableCall row. Typed row shape with five typed payload slots. See The AuditableCall row.
  • ProviderDecisionLedger. Append-only write interface, one method, idempotent on (sessionId, turnId, stageId, seqWithinTurn). See Audit ledger.
  • Tamper-evident hash chain. prev_hash + row_hash columns detect silent backfill, reorder, and removal. See Hash chain.

Composing-agents cluster

How composable work nests inside a session. Names the unit of work, spawns the child runtime that executes it, records the rolling signal that decides whether to spawn it again. Full walk in Agents.

  • Skill. Markdown file with YAML frontmatter; SkillLoader walks three sources. See Skills.
  • Subagent. Child runtime spawned from a tool call against a resolved skill spec. SUBAGENT_LIMITS.maxDepth = 3 caps the nesting. See Subagents.
  • Agent profile. Persistent registry record keyed by specName. See Agents.

Runtime-lifecycle cluster

What happens over time and what gets persisted. Sessions outlive turns; turns outlive their stream frames; the event log outlives both. Full walk in Session lifecycle.

  • Session lifecycle. createSession / resumeSession / deleteSession — the arc above the turn. See Session lifecycle.
  • Turn lifecycle. The per-message arc between executeMessage and the final SSE frame. See Turn lifecycle.
  • Event log. Append-only typed stream both lifecycles write into. See Event log.

State-and-persistence cluster

What makes a session survive a process restart, a fork or rewind, and a multi-client edit. Lives below the execution graph and above the schema bundle. Full walk in Storage.

  • Storage adapter. Pluggable surface reading and writing SessionState. Memory / IndexedDB / Supabase adapters all implement the same interface. See Storage.
  • Checkpoint. Per-channel snapshot at every stage boundary. runtime.checkpoints.rollback restores in place; TimeTravelAPI.fork branches into a new session. See Checkpointing.
  • Sync (version vector). Record<clientId, number> per session. compareVectors flags concurrent writes; SyncCoordinator surfaces conflicts through sync.conflict. See Sync.

What lives outside the cluster pattern

Eight sidebar groups don't carve cleanly into three-concept triplets. They aren't deficient — they're shapes the pattern doesn't fit. Three are surfaces (facets, plugins, tools); five are heterogeneous concept sets or pairs (safety, observability, frontend, prompts, cross-session state).

  • Facets. Typed accessors on runtime.<name>runtime.sessions, runtime.events, runtime.checkpoints, runtime.tenant, runtime.spans, and the rest. A surface pattern that groups related methods by domain so the runtime reads as a short list of named accessors instead of a flat method dump. Not a three-concept cluster. See Facets.
  • Plugins. The HarnessPlugin extension contract — ~40 optional hooks plus four structural invariants the substrate enforces against them. A bounded contract, not a triplet. See Plugin contract.
  • Tools. The defineTool contract, Zod-validated input / output, per-invocation context, and batching. One surface end to end — contract, dispatch, result-handling — not a three-concept cluster. See Tools.
  • Prompts. Composition of system prompts from typed contributions plus the budgeted composer. A pair (prompts + prompt builder), not a triplet.
  • Cross-session state. Plans span multiple turns; memory spans multiple sessions. Two variable surfaces that outlive a single session, each with a distinct mechanism (revision history vs decay curve). Not a three-concept cluster.
  • Safety & determinism. safety, scrubbers, fabrication-detection, determinism, fingerprint. Five concepts, each with a distinct mechanism; no natural triplet. safety.mdx orients the reader directly.
  • Observability. lineage, observability, otel-observability, runtime-inspector. Distinct surfaces a reader usually arrives at already knowing which one they need.
  • Frontend integration. react, server, api-routes, query, devtools. Wiring surfaces, not concepts.

Where to go next

On this page