Overview
The conceptual map — what Pleach is, what a turn looks like, what gets recorded, and which door to open next.
Pleach is a TypeScript agent runtime. Sessions hold state; turns
drive change; every LLM call lands as one append-only audit row
keyed by turnId. The runtime, the four-stage lattice, and the
audit ledger form a triangle — the rest of the docs are detail.
The name is horticultural. A streamText call is one branch
upright in a pot. Pleach is the lattice — every addressable
event the agent produces (each LLM call, tool dispatch,
subagent spawn) lands as a branch, woven into one structure you
can query, prune, and replay six months later. The four stages
are the trellis; the audit row is the weave.
This page gives you the shape in 90 seconds. Install steps live on Getting started; framework comparison lives on Comparison.
The mental model
One request in, one streamed answer out. The SessionRuntime owns
the turn; the ledger hangs off it as an append-only sink so every
addressable decision is queryable after the fact.
Session vs turn
A session is the unit of identity that outlives any one message. A turn is one message-in, one answer-out. They have different shapes:
| Property | Session | Turn |
|---|---|---|
| Scope | Per-conversation; locks (provider, model) for its lifetime | Per-message; runs the four-stage lattice once |
| Persistence | Durable row + checkpoint chain in storage | Derived from the event log; no separate row |
| Abort behavior | Idempotent delete; checkpoints drop, audit rows stay | AbortSignal cancels in-flight provider calls; partial spend still lands a row |
Session lifecycle (mint, resume, fork, delete) is documented at Session lifecycle. The dynamic per-message arc lives at Turn lifecycle.
A turn, in four stages
The lattice is structural. Every node in the compiled graph belongs
to exactly one stage; audit:graph-stages fails the build on an
out-of-lattice edge. post-turn is terminal — no edge out.
anchor-plan
Bootstraps the turn: intent classification, plan generation, and
anchoring of references the tool loop will need. Fires step.start
on the stream and writes one ledger row per call with
payload.kind: "planGeneration".
tool-loop
The iterative core. One reasoning call per iteration may emit
tool calls; the runtime dispatches them and re-enters the loop.
Fires tool.started / tool.completed per dispatch and writes
cacheBreakpoint, toolSelection, and (on retry) fallbackStep
rows.
synthesize
Exactly one synthesize call per turn — capped by a per-runtime
singleton seam plus an idempotent counter so the rendered string
and the audited string are the same string. Fires message.delta
and message.complete; writes one synthesisQuality row.
post-turn
Terminal stage. Durable writes flush, enrichment plugins run,
checkpoints land. No LLM calls fire here. Fires
checkpoint.created and then done.
For the full per-stage stream-event and ledger-payload tables, see Turn lifecycle → the four-stage execution path.
What gets recorded
Every addressable decision — every seam-bound provider call, every
in-family retry, every tool-cascade rung — lands one row. The
ledger is append-only by contract: ProviderDecisionLedger exposes
no update and no delete. A per-turn cost rollup is one
GROUP BY turn_id; a per-stage budget is one GROUP BY stage_id.
The four-field identity tuple is what makes joins cheap. turnId
joins to your billing row; stageId slices the spend; sessionId
joins to the session record; seqWithinTurn gives a stable order
inside the turn. See The AuditableCall row
for the full field shape and the typed-payload discriminants.
Concretely, a per-turn cost rollup looks like:
SELECT turn_id, SUM(input_tokens + output_tokens) AS total_tokens
FROM harness_auditable_calls
WHERE session_id = $1
GROUP BY turn_id;That query works against a row shape that exists by construction —
every row carries a non-null turn_id because a call that fires
outside the lattice fails CI before it ever reaches a provider.
The axis is yours to pick. tenantId carries customer-acme if
you're invoicing end customers in a SaaS; it carries
cost-center-eng-platform if you're attributing employee or team
spend under one Anthropic Workspace or OpenAI Project on an
Enterprise contract. The rollup is the same GROUP BY either
way — no second vendor contract, no second admin key. See
Migrating from Anthropic Enterprise
and Migrating from OpenAI Enterprise
for the composition walk-through.
Three doors
Pick the closest. The rest of the index is reference.
Try it in 5 lines
Install @pleach/core, call createPleachRuntime(), stream your first turn. No database, no provider key, ~30 seconds.
Decide if Pleach fits
Where Pleach overlaps with AI SDK, LangChain, LlamaIndex, Mastra, and the dev harnesses — and where the audit ledger and four-stage lattice change the shape.
Adopt for audit and cost rollup
The AuditableCall row, per-turn cost attribution, scrubbers, the hash chain, and the CI gates that hold it.
Where the rest of the docs live
The sidebar is grouped by what you reach for, not by package boundary. Core primitives (SessionRuntime, Facets, Providers, Tools, Prompts) is the day-one surface. Compose agents (Agents, Subagents, Skills, Plans, Memory) is the multi-step shape. Runtime lifecycle (Channels, Event log, Projections, Stream events, Interrupts, Async tasks) is what the runtime is doing between your calls. State & persistence (Storage, Cache, Checkpointing, Sync) is how state survives a process restart. Safety & determinism (Safety policies, Scrubbers, Fabrication detection, Determinism, Fingerprint) is the property set replay and eval depend on. Audit & observability (Audit ledger, Hash chain, AuditableCall row, Lineage, OTEL spans) is the read side. Frontend (React, Server, API routes, Query, DevTools) and Integration (MCP, LangChain adapter, Host adapter, Plugin contract) wire the runtime into a real application. Operations (Deployment, Multi-tenant, Performance, Security, Compliance, Error codes) is what production needs.
What this site is not
Not where the package source lives. @pleach/core is published
from the upstream repository at github.com/pleachhq/core and
consumed here as a documentation target — the version of
@pleach/core rendered against this site is whatever the package
manifest pins.
Not the canonical reference for any individual package — each package's README on npm is. If this site disagrees with a published README (a row in the model resolution matrix, a field name in the AuditableCall row, a verdict in the stream-observer ladder), the README wins.
Where to go next
Getting started
Install, construct a runtime, stream a turn.
Architecture
Six pieces, one substrate — SessionRuntime, CompiledGraph, Channels, Seams, the AuditableCall ledger, and the event log.
Turn lifecycle
The four-stage execution path, stream events per stage, audit rows per stage.
Session lifecycle
The arc above the turn — minting, resume, abort, time-travel, delete.