> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mesh.texturehq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Layers

# Layers

A review lens for separation of concerns, and the anatomy every pluggable seam
in Mesh is expected to grow.

This document is reasoning, like [`philosophy.md`](/philosophy). The normative
rules it implies live in exactly one place —
[`roadmap.md` §Design guardrails (repository)](https://github.com/TextureHQ/mesh/blob/main/docs/roadmap.md#design-guardrails) — and the
contract for any specific seam lives in that seam's own doc. What this document
adds is the map: which layer a concern belongs to, what question tells you it
has leaked into the wrong one, and what a seam must have before its second
implementation lands.

## Why a layer model at all

Mesh's failure-mode analysis is identity-shaped ([`philosophy.md`](/philosophy)),
but its *code-review* failures are layer-shaped: a vendor client synthesizing
prompt text, a payload decoder making an engagement decision, a settings page
speaking one backend's vocabulary. None of those are caught by the identity
principles, because each one is locally reasonable. They are caught by asking a
different question: **which layer does this concern belong to, and is this code
in that layer?**

The layers are a review construct, not a package layout. A package may
implement contracts from more than one layer (a connector carries both a
transport contract and a presentation contract); the boundary lives in the
contracts, not in the directory tree.

## The five layers

```
REACH        what an agent can touch
  ↓
CONTEXT      what an agent knows this turn
  ↓
JUDGMENT     what the model proposes  ─┐  one layer, two owners:
GOVERNANCE   what the runtime permits ─┘  models propose, the runtime governs
  ↓
SURFACE      how output reaches the world
  ↓
EXPLANATION  how an operator reconstructs all of the above
```

**Identity and perspective are not a layer.** They are the vertical that cuts
through all five: reach is credentialed per agent and install, context is
perspective-scoped in SQL, governance keys admission on `(agent, conversation)`,
surface attributes every delivery, explanation scopes every read. A layer that
handles an unattributed value has already failed before the layer question is
asked. See [`perspective.md`](/perspective).

### 1 · Reach — what an agent can touch

Tools, providers, execution and browser backends, model connectors, transport
connectors, and the credentials that scope all of them. The layer's rule is the
cloud-first principle: nothing about reach derives from the host; every
capability crosses a declared, granted, auditable boundary.

* Packages: `internal/tool`, `internal/execution`, `internal/model`,
  `internal/connector` (the transport half), `internal/agent`,
  `internal/secrets`, `internal/settings`.
* Contracts: [`runtime/tools.md`](/runtime/tools),
  [`runtime/sandboxed-execution.md`](/runtime/sandboxed-execution),
  [`connectors/slack.md`](/connectors/slack),
  [`connectors/model.md`](/connectors/model).
* Leak test: *does anything above an adapter know a vendor's name, or does any
  adapter do work another layer owns?* A model connector that writes prompt
  text, a backend name in a settings type, a tool that infers its own class —
  all reach leaks.

### 2 · Context — what an agent knows this turn

The bounded projection of the conversation graph, memory, persona, and identity
into one model request. The layer's rule is the anti-blob principle: context is
structured and attributed until the last possible moment, and the assembled
prompt is a *view* of durable state, never the state itself.

* Packages: `internal/prompt`, `internal/graph` (read side), `internal/memory`,
  `internal/state`.
* Contracts: [`runtime/context-resolution.md`](/runtime/context-resolution),
  [`runtime/memory-retrieval.md`](/runtime/memory-retrieval),
  [`versioned-state.md`](/versioned-state).
* Leak test: *can a context source be added, or a rendering changed, without
  touching data access or the loop?* Rendering that lives outside
  `internal/prompt`, context that arrives pre-flattened, or a surface name in
  prompt text are context leaks.

### 3 · Judgment and governance — what happens, and what is allowed to

One layer with two owners, and the split is Mesh's central move
([`philosophy.md` §runtime-governance](/philosophy#the-runtime-governance-principle)):
the model owns judgment (interpret, choose, propose); the runtime owns
invariants (addressing, admission, budgets, schema validation, effect policy,
the commit boundary). Everything deterministic here must be explainable,
including the decision to do nothing.

* Packages: `internal/addressing`, `internal/turn`, `internal/run`,
  `internal/claim`, `internal/app` (governor, ingress, runtime orchestration).
* Contracts: [`runtime/addressing.md`](/runtime/addressing),
  [`runtime/turn-pipeline.md`](/runtime/turn-pipeline),
  [`runtime/agent-harness.md`](/runtime/agent-harness),
  [`runtime/interrupt-model.md`](/runtime/interrupt-model),
  [`runtime/work-graph.md`](/runtime/work-graph).
* Leak test: *is any decision made where its inputs don't live?* Engagement
  policy in a payload decoder, a bound defined independently in two packages,
  or a runtime decision smuggled through reply text ("empty string means
  declined") are governance leaks.

### 4 · Surface — how output reaches the world

Canonical output, per-connector rendering, delivery, receipts, and lifecycle
signals (acks, reactions). The layer's rule is render-at-send: the graph stores
canonical Markdown; a wire format exists only inside the connector that *is*
that format ([`runtime/turn-pipeline.md`](/runtime/turn-pipeline)
§Render at send).

* Packages: `internal/render`, `internal/connector` (the presentation half),
  `internal/turn` (the send boundary).
* Leak test: *does any layer above a connector know how a surface formats,
  addresses, or acknowledges?* Surface names in persisted vocabularies, wire
  formats in stored bodies, and inbound wire markup reaching the model
  unconverted are surface leaks — the last one is the inbound mirror of
  the compounding bug and is just as real as the outbound case.

### 5 · Explanation — how an operator reconstructs the rest

Capture, inspection, measurement, and the improvement loop. The layer's rule is
capture-before-behavior with its stated asymmetry: capture may never lag
behavior; display may lag capture — but a capture no read path ever serves is
only half-delivered, and a behavior nothing scores cannot be improved.

* Packages: `internal/admin`, `internal/telemetry`, `internal/errtrack`,
  `internal/run` (the read side), `web/`.
* Contracts: [`runtime/observability.md`](/runtime/observability),
  [`telemetry.md`](/telemetry), [`error-tracking.md`](/error-tracking).
* Leak test: *can the operator reconstruct, from durable data through the read
  API, what the agent observed, why it acted or stayed silent, what authority
  it used, and what it cost?* Anything answerable only via `psql`, a log line,
  or a trace backend is an explanation gap. So is any layer that produces
  behavior capture cannot see — a synthesized instruction, an unrecorded shed.

## The seam anatomy

[`runtime/tools.md` §The tool package format](/runtime/tools#the-tool-package-format)
settled more than tool packaging. It is the template for what *any* pluggable
seam in Mesh must eventually have, because every part of it answers a failure
the other seams have already exhibited. A seam has three parts:

1. **Contract** — a small Go interface plus value types, vendor-free,
   capability-declared. Code above the seam branches on a declared capability,
   never on an implementation's name. Every seam in Mesh has this part, and it
   is the part Mesh is consistently good at.

2. **Descriptor** — the implementation's declarative self-description, readable
   without executing its code: identity, capabilities, and its **config
   surface** — each field with the closed `secret | config | public`
   disposition vocabulary from the tool manifest. The descriptor is what the
   settings UI, the enablement flow, and the audit view render from. For tools
   the descriptor is `manifest.toml` because operators and (eventually) third
   parties read it; for compiled-in adapters a Go value serves — the format is
   incidental, the property is not: **when the descriptor is missing, the
   layer above the adapter hand-codes what the descriptor should have declared,
   in the vendor's vocabulary.** That is precisely how a backend's name ends up
   in settings types, admin routes, and page code.

3. **Catalog** — exactly one registration point mapping a stable name to an
   implementation. Generated (the tool handler catalog) or hand-maintained in
   one place (the error-tracker `ProviderLookup`); either way, unknown names
   fail loud and the *N+1th* implementation edits its own package plus one
   catalog entry, nothing else. A seam whose selection logic is written more
   than once does not have a catalog, it has switches — and each switch is a
   place the next implementation gets forgotten.

The test is blunt, and it is the test to apply in review before a seam's second
implementation merges: **adding the next implementation may touch its own
package and one catalog line.** Every additional file it must touch is a leak —
name it, and either fix the seam or record the acceptance where the seam's doc
lives. "Two adapters do not earn a registry" remains true for the *catalog*
(one switch, written once, is a fine catalog at N=2); it was never a license
for five switches in five files.

## Where each seam stands

Status detail belongs to [`roadmap/current-state.md` (repository)](https://github.com/TextureHQ/mesh/blob/main/docs/roadmap/current-state.md);
this table records only which anatomy parts each seam has. Most rows are a
historical snapshot at migration `0026`; the Tools row is updated on 2026-09-18.
See the [tool strategy](https://github.com/TextureHQ/mesh/blob/main/docs/runtime/tool-integration-strategy.md) for the current
baseline and planned common catalog.

| Seam | Contract | Descriptor | Catalog |
| - | - | - | - |
| Tools | ✅ `tool.Definition`/`Registry` and executor shared by native and remote MCP tools | ✅ native manifests in production; separate MCP/web descriptors | 🟨 native and MCP discovery exist; unified integration catalog, durable MCP snapshots, and progressive activation are planned |
| Conversation connectors | ✅ proven at N=2 — one outbound contract, shared engagement/turn dispatch (`internal/app/ingress_dispatch.go`), per-connector ingress adapters | ⬜ none — route shape, secret kinds, and admin/web flows are hand-coded per connector; spread measured in [`connectors/telegram.md`](/connectors/telegram) | ✅ one switch in `rebuildServing`, written once (fine at N=2) |
| Model providers | ✅ `model.Connector`/`Preparer` | ✅ `model.Provider` | ✅ `internal/model/providers` |
| Execution backends | ✅ `execution.Backend` + capabilities | ✅ `execution.Provider` (config fields, secret kind, env var, test hook) | ✅ `internal/execution/backends` |
| Browser backends | specified only | ⬜ | ⬜ |
| Error trackers | ✅ neutral core, vendor leaf | ⬜ (config surface hand-coded, acceptable at N=1) | ✅ one explicit switch, written once |
| Context sources | ⬜ no contract — assembly is inlined in `internal/turn` | ⬜ | ⬜ |

Model providers were this table's control experiment — the only seam with two
live implementations, whose five-switch spread measured the cost of a missing
descriptor and catalog — and execution backends were one implementation old and
already exhibiting the same spread. Both were retrofitted to the full anatomy
(the execution retrofit also un-flattened the stored settings document, `0026`,
before a second backend could collide with it). The remaining 🟨 and ⬜ cells
above are the ones to close before — not after — their next implementation lands.
Native tool packages and remote MCP bindings now run in production. The next
step is the [shared integration layer](https://github.com/TextureHQ/mesh/blob/main/docs/runtime/tool-integration-strategy.md), with
Linear retirement gated on MCP parity. Browser interaction has a separate
multi-provider implementation tracked by that strategy's baseline.

Conversation connectors took their second implementation (Telegram) without a
descriptor and paid the predicted spread — the per-file bill is recorded in
[`connectors/telegram.md`](/connectors/telegram), and closing it comes before
a third connector. Context sources close before the next prompt ingredient.

## What this model does not claim

It does not claim packages map one-to-one onto layers, that every seam needs a
TOML file, or that the layers replace the identity, perspective, or governance
principles — those remain prior. It claims only that "which layer owns this
concern?" and "does this seam have its three parts?" are questions cheap enough
to ask in every review, and that the recorded cost of not asking them is
already visible in the seams above.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.