> ## 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.

# Versioned state

# Versioned state

Mesh should not treat agent memory, tool access, or persona configuration as loose markdown files on disk.

Those files are fine as an export format, but they are the wrong source of truth for a multiplayer system that needs to be durable, auditable, recoverable, and perspective-isolated.

See [`perspective.md`](/perspective) for the RuntimeAgent perspective boundary, [`runtime/context-resolution.md`](/runtime/context-resolution) for how that boundary applies to model context, and [`runtime/memory-retrieval.md`](/runtime/memory-retrieval) for how eligible memory is selected and ranked.

## Why not markdown as the canonical store

Markdown repos are convenient for a hacker workflow, but they have structural problems:

* they are easy to mutate silently
* they do not naturally preserve provenance
* they do not give you a clean rollback story
* they make branching and forking awkward
* they spread important runtime state across files that are hard to query
* they make it too easy to accidentally share state between agents that happen to use the same filesystem

That is acceptable for notes. It is not ideal for live agent state.

## What Mesh should do instead

Mesh should store the canonical state in Postgres using append-only, versioned tables.

The important pieces are:

* *self/profile state* — persona, style, operating constraints, goals
* *tool grants* — what capabilities an agent has been given
* *memory entries* — durable remembered facts with provenance
* *prompt snapshots* — the assembled material used for a turn
* *revisions* — immutable history for every change

Every one of those belongs to a specific `RuntimeAgent`. Multi-agent hosting is operational multiplexing, not a shared state space.

A human-readable markdown export can still exist, but only as a view over the structured state.

## Perspective ownership

Memory belongs to the RuntimeAgent that learned it.

If Lyra and Daedalus both interact with Victor, Lyra's memory about Victor and Daedalus's memory about Victor are separate state. The control plane may correlate the external identities for operational reasons, but that correlation does not make either agent's memory eligible context for the other.

The same rule applies to profile state, tool grants, and prompt snapshots: there is no deployment-global fallback state that an agent silently inherits because another RuntimeAgent already has it.

A cross-connector identity link established in one perspective may organize that RuntimeAgent's memory across Slack, Telegram, or GitHub. It does not bootstrap identity or memory in another perspective.

## Provenance is part of memory

A durable memory entry must retain enough provenance for future context resolution to decide whether it is appropriate to reuse:

* which RuntimeAgent learned it
* which Actor or Actors it concerns inside that perspective
* which Conversation and MessageEvents produced it
* when it was learned
* what audience could observe the source conversation

Perspective isolation answers "whose knowledge is this?" Audience provenance answers "where may that knowledge be reused?" Losing either makes later policy enforcement impossible.

## Why append-only matters

Append-only state gives us:

* auditability
* rollback
* forking
* reproducibility
* safe experimentation
* the ability to inspect exactly what the runtime believed at a given turn

If an agent degrades over time, we can return to a known-good revision instead of trying to reconstruct intent from a pile of edited files.

## Intended behavior

When a profile or tool grant changes:

1. write a new revision owned by the RuntimeAgent
2. preserve the prior version
3. mark the new one as current for that RuntimeAgent
4. assemble the runtime prompt from that agent's current version plus context resolved entirely inside its perspective

That makes the live system predictable and the history inspectable.

## Prompt snapshots

A prompt snapshot is the audit record of what one RuntimeAgent actually knew for one turn.

It must never contain references sourced from another RuntimeAgent's perspective merely because both are hosted by the same process. The snapshot should eventually record the agent id plus the source message, memory, and state revisions used to assemble it. See [`runtime/context-resolution.md`](/runtime/context-resolution).

## Design principles

*DB is canonical. Markdown is presentation.*

*State is RuntimeAgent-owned. Co-residency is not shared cognition.*

Those are the right boundaries for a system that wants to be multiplayer from the start.

## Current state

This document is the intent. What is actually built, as of
`0019_run_ledger.sql`:

* **persona** — built (`agent_persona_revisions`): the operator-authored identity
  text rendered into every prompt. Append-only revisions with an explicit
  `active` flag (one per agent, enforced by a partial unique index), written by
  the admin API's persona endpoints and edited on the agent's profile page.
  Reverting activates an earlier revision; it never mints a copy, so history
  records what happened. The loader resolves the active revision into the
  serving agent and `turn.Engine` renders it — this one is behavior, not intent.
* **memory entries + revisions** — built and live in both directions, keyed to
  `runtime_agents(id)`, and actor-attributed as of
  `0018_actor_attributed_memory.sql`. Operators author them through the admin API;
  the runtime loads the newest eligible live entries into each prompt and exposes
  four verbs (`remember`, `recall`, `amend`, `forget`).

  Each entry now distinguishes **subject** (`subject_actor_id`, who the claim is
  about), **source** (`source_actor_id` plus `source_message_event_id`, who
  supplied it and on what basis), and **visibility** (`perspective` or
  `conversation`, the hard eligibility filter). The two actor references are
  composite foreign keys into `actors (runtime_agent_id, id)`, so cross-perspective
  attribution is rejected by the database rather than by convention. Both are
  nullable: an unresolved subject is a legitimate state, not a defect to paper over
  with a guess.

  `memory_entry_revisions` is an operation log, not merely a body history. Each row
  records its `operation` (`create`/`amend`/`forget`), the attributed state it
  produced, and who supplied the change. Every write — including `forget`, which
  soft-deletes and advances the revision counter — commits its entry and its
  revision row in one transaction, so a committed memory is never missing its
  history and a retired memory stays auditable.

  An agent-authored entry has `source_type='agent'`, a NULL operator id, and
  provenance derived from the persisted inbound message's graph record. Retrieval
  is lexical (PostgreSQL FTS) plus a current-subject boost and recency; the
  semantic and salience axes in
  [`runtime/memory-retrieval.md`](/runtime/memory-retrieval) remain to be
  implemented.
* **prompt snapshots** — built and live, keyed to `runtime_agents(id)`. The turn
  engine records the assembled system prompt before provider execution and each
  durable model-call row references that snapshot, so the audit record and
  invocation cannot silently drift apart.
* **tool grants** — *not built.* `0003` created `tool_sets` / `tool_set_revisions`
  speculatively; nothing ever read them and `0009` dropped them. They return
  designed against the tool contract, not resurrected — see the 0009 header for
  what a real grant schema has to carry.
* **profile state** — there is no separate profile row. The profile *is* the
  `runtime_agents` row (`display_name`, the three model-role columns, `settings`)
  plus its persona revisions; `0009` dropped `agent_profiles` rather than keep a
  1:1 surrogate that had to be kept in sync.

The first three bullets are the honest reason to read the migration headers rather
than this file when asking "what can the system do today": applied SQL is
executable, and a design doc is not.


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