# Overview (/docs/overview)



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](/docs/getting-started); framework
comparison lives on [Comparison](/docs/comparison).

## The mental model [#the-mental-model]

<Mermaid
  chart="flowchart LR
    U[User] --> B[Browser]
    B -->|POST /execute| R[SSE route]
    R -->|executeMessage| SR[SessionRuntime]
    SR -->|seam calls| P[Provider]
    P -.->|streaming deltas| SR
    SR -->|StreamEvent| R
    R -->|SSE frame| B
    SR -.->|one row per call| A[(AuditableCall ledger)]"
/>

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 [#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](/docs/session-lifecycle). The dynamic per-message
arc lives at [Turn lifecycle](/docs/turn-lifecycle).

## A turn, in four stages [#a-turn-in-four-stages]

<Mermaid
  chart="flowchart LR
    AP[anchor-plan] --> TL[tool-loop]
    TL --> TL
    TL --> SY[synthesize]
    SY --> SY
    SY --> PT[post-turn]"
/>

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` [#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` [#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` [#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` [#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](/docs/turn-lifecycle#the-four-stage-execution-path).

## What gets recorded [#what-gets-recorded]

<Mermaid
  chart="flowchart LR
    SR[SessionRuntime] -->|per LLM call| Row[AuditableCall row]
    Row --> ID[&#x22;identity:<br/>sessionId<br/>turnId<br/>stageId<br/>seqWithinTurn&#x22;]
    Row --> Pay[typed payload]
    Row --> Out[outcome + tokens]
    Row --> L[(harness_auditable_calls)]"
/>

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](/docs/auditable-call-row)
for the full field shape and the typed-payload discriminants.

Concretely, a per-turn cost rollup looks like:

```sql
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](/docs/migrating-from-anthropic-enterprise)
and [Migrating from OpenAI Enterprise](/docs/migrating-from-openai-enterprise)
for the composition walk-through.

## Three doors [#three-doors]

Pick the closest. The rest of the index is reference.

<Cards>
  <Card title="Try it in 5 lines" href="/docs/getting-started" description="Install @pleach/core, call createPleachRuntime(), stream your first turn. No database, no provider key, ~30 seconds." />

  <Card title="Decide if Pleach fits" href="/docs/comparison" description="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." />

  <Card title="Adopt for audit and cost rollup" href="/docs/audit-ledger" description="The AuditableCall row, per-turn cost attribution, scrubbers, the hash chain, and the CI gates that hold it." />
</Cards>

## Where the rest of the docs live [#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 [#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](/docs/model-resolution-matrix),
a field name in the [AuditableCall row](/docs/auditable-call-row),
a verdict in the [stream-observer ladder](/docs/architecture#3-seams)),
the README wins.

## Where to go next [#where-to-go-next]

<Cards>
  <Card title="Getting started" href="/docs/getting-started" description="Install, construct a runtime, stream a turn." />

  <Card title="Architecture" href="/docs/architecture" description="Six pieces, one substrate — SessionRuntime, CompiledGraph, Channels, Seams, the AuditableCall ledger, and the event log." />

  <Card title="Turn lifecycle" href="/docs/turn-lifecycle" description="The four-stage execution path, stream events per stage, audit rows per stage." />

  <Card title="Session lifecycle" href="/docs/session-lifecycle" description="The arc above the turn — minting, resume, abort, time-travel, delete." />
</Cards>
