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

# sovseal Memory Model: Semantic Memory vs. State Replication

> How store/recall (flat, content-addressed semantic memory) and snapshot/restore/lineage (sequence-numbered zero-knowledge checkpoints) are two distinct systems — record shapes, the real SDK method table, and constraints to design around.

<style>
  {`
      main, article, .prose {
        margin-left: 2.5cm !important;
        margin-right: 2.5cm !important;
      }
      `}
</style>

sovseal has two data models doing two different jobs, both encrypted client-side before anything leaves your device. Conflating them is the single easiest way to misunderstand the system, so this page keeps them strictly separate.

<CardGroup cols={2}>
  <Card title="Semantic memory — store/recall" icon="brain">
    Flat, content-addressed facts. `"User prefers TypeScript"` in, ranked search results out. No paths, no hierarchy — a fact is just a string with metadata attached.
  </Card>

  <Card title="State replication — snapshot/restore/lineage" icon="timeline">
    Zero-knowledge checkpoints of an entire agent's working state, ordered by a strict per-agent sequence number. Built for audit and point-in-time recovery, not for search.
  </Card>
</CardGroup>

***

## Semantic memory: the record shape

A stored memory is a flat record, not a tree. `store_memory({ content: string })` takes a self-contained factual statement — there is no `path`, no nested `metadata` object, and no `parent` argument. See [store\_memory](/platform/core-concepts/store-memory) for the full write pipeline.

```json theme={null}
{
  "id": "a86938e9-de49-4a87-89de-edb62bef27b8",
  "text": "User prefers Vitest over Jest for new TypeScript projects.",
  "embedding": "[384-dim float32 vector — local only, never sent to the server]",
  "type": "semantic",
  "reinforce_count": 1,
  "provenance": "explicit",
  "last_reinforced": "2026-08-04T09:12:03.000Z"
}
```

Only the encrypted `text` field and its `client_payload_hash` anchor ever reach the replication server when write-behind sync is enabled — the embedding vector stays local. See [Zero-Knowledge Guarantees](/platform/core-concepts/zero-knowledge) for exactly what crosses the boundary.

## Typing, reinforcement, and provenance (schema v2)

Every record carries metadata that shapes how it's recalled:

| Field             | Values                                 | Role                                                                                                                                           |
| ----------------- | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`            | `episodic` · `semantic` · `procedural` | Sets the recall decay half-life (14d / 90d / 180d) — see [recall\_memory](/platform/core-concepts/recall-memory) for the full ranking formula. |
| `reinforce_count` | integer                                | Incremented when the same fact is stored again, instead of inserting a duplicate row. Boosts recall ranking.                                   |
| `provenance`      | `explicit` · `observed`                | Whether the fact was explicitly asked to be remembered, or inferred from context.                                                              |
| `last_reinforced` | timestamp                              | Drives temporal decay in the ranking formula.                                                                                                  |

**Reinforcement — storing the same thing twice.** `store_memory` deduplicates by content: storing an identical fact doesn't append a new row, it increments that record's `reinforce_count` and refreshes `last_reinforced`. Recall rewards this via the composite ranking formula `score = similarity × decay × reinforcement` — a fact you keep restating outranks a one-off entry of the same raw similarity.

<Tip>
  `sovseal mind` surfaces reinforced memories under "Recurring Patterns." See [recall\_memory → Reinforcement-Aware Ranking](/platform/core-concepts/recall-memory) for the full breakdown.
</Tip>

***

## State replication: the snapshot shape

A snapshot is a full checkpoint of one agent's working state, encrypted client-side and ordered by a plain integer, not a content hash:

```json theme={null}
{
  "agent_id": "agent-id-hash",
  "sequence_number": 4,
  "parent_snapshot": "<previous snapshot id>",
  "policy_hash": "0000…0000",
  "active_context": { "...": "arbitrary JSON, encrypted before it leaves your process" },
  "client_payload_hash": "sha256(canonicalize(payload))",
  "timestamp": "2026-08-04T09:12:03.000Z"
}
```

**Ordering is a strict, per-agent, monotonic sequence — not a content-addressed chain.** The server tracks the latest confirmed `sequence_number` for each `agent_id` and only accepts the next one: `sequence_number` must equal `latest + 1`, starting at `0` for a brand-new agent (`0` also requires `parent_snapshot: null` — this is the genesis check). Anything else is rejected with `409 sequence_gap`. Sending a duplicate `(agent_id, sequence_number)` with the same `client_payload_hash` is idempotent and returns the original receipt unchanged; the same sequence with a *different* hash is a `409 sequence_conflict`.

`client_payload_hash` — `sha256(canonicalize(payload))` — is an **integrity anchor for a single snapshot**, not a link in a hash chain. It's what [Verified Semantic Recall](/platform/core-concepts/verified-semantic-recall) re-derives and compares on restore to catch tampering or substitution. It does not itself encode the parent pointer.

## What the SDK actually exposes

| Method                             | Does                                                                       |
| ---------------------------------- | -------------------------------------------------------------------------- |
| `store(content)`                   | Persist a fact to local semantic memory.                                   |
| `recall(query, opts)`              | Ranked semantic search over local memory.                                  |
| `snapshot({ payload, key })`       | Encrypt and publish one state checkpoint at the next sequence number.      |
| `restore({ agentId })`             | Fetch the latest confirmed checkpoint's receipt + ciphertext URL.          |
| `restoreAt({ agentId, sequence })` | Fetch a checkpoint at a specific sequence number — point-in-time recovery. |
| `lineage({ agentId, limit })`      | Walk the sequence chain backward, most-recent first.                       |

That's the complete surface (see the [Node SDK reference](/sdk-reference/node-sdk) for exact signatures). There is no `fork()`, no `rollback()`, and no generic `delete(path)` — those aren't primitives sovseal implements. If you need to "branch" state, the real pattern is simpler than a first-class fork: restore the state you want to branch from, then `snapshot()` it as sequence `0` under a **new** `agent_id`. Each agent's sequence chain is independent from the start.

"Rolling back" means calling `restoreAt(agentId, sequence)` for an earlier sequence number — it fetches that checkpoint; it does not delete or hide anything newer. Every snapshot the server has accepted for that agent remains retrievable by its sequence number regardless of what the "latest" one is.

***

## Constraints to design around

<AccordionGroup>
  <Accordion title="Semantic memory records are not blobs">
    `store_memory` content is a bounded text string (`STORE_MEMORY_MAX_CHARS`). For large binary data, store a reference (URL, object key) as the fact — not the raw bytes.
  </Accordion>

  <Accordion title="Snapshot payloads are size-capped">
    Encrypted `active_context` ciphertext is capped at `MAX_PAYLOAD_BYTES` (256 KB). `snapshot()` throws a `RangeError` client-side before any network call if you exceed it — see the [Node SDK reference](/sdk-reference/node-sdk#snapshot).
  </Accordion>

  <Accordion title="Two independent systems, two independent failure domains">
    A `store`/`recall` outage (native host unreachable) doesn't affect `snapshot`/`restore` (HTTP to your configured `endpoint`), and vice versa. They don't share state, sequencing, or a client\_payload\_hash namespace.
  </Accordion>

  <Accordion title="Embeddings are a rebuildable index, not the source of truth">
    If you change the embedder model, the vector index needs rebuilding. The encrypted `text` records are untouched — plan model migrations as an index rebuild, not a data migration.
  </Accordion>
</AccordionGroup>

***

## Next steps

<CardGroup cols={2}>
  <Card title="store_memory" icon="database" href="/platform/core-concepts/store-memory">
    The full write pipeline: redaction, embedding, encryption, and the write-behind outbox.
  </Card>

  <Card title="recall_memory" icon="magnifying-glass" href="/platform/core-concepts/recall-memory">
    How a query becomes ranked, decrypted results — entirely on-device.
  </Card>

  <Card title="Verified Semantic Recall" icon="shield" href="/platform/core-concepts/verified-semantic-recall">
    The two-check pattern that catches tampering and substitution on every restore.
  </Card>

  <Card title="Deterministic Lineage" icon="timeline" href="/platform/core-concepts/deterministic-lineage">
    How the sequence chain enables point-in-time recovery and crash-safe replication.
  </Card>
</CardGroup>
