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

# store_memory: Write-Behind Local Commit in Under 5ms

> store_memory commits to local LanceDB and returns in under 5ms. Ciphertext replication is asynchronous — zero RTTs block the call path.

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

`store_memory` is an **MCP tool**, exposed by `@sovseal/mcp-server`. It is built around a single operational principle: **no tool call ever blocks on I/O.** It redacts, embeds, encrypts, writes to the local LanceDB index, and returns — without waiting for the replication endpoint.

<Note>
  `store_memory` is exposed as an MCP tool by `@sovseal/mcp-server`. `@sovseal/sdk` (`v1.0.0+`) and `sovseal-sdk` (`v1.1.0+`) also expose `store(content)` via framed IPC to the local native host (`~/.sovseal/native-host/run.sh`). If the native host is absent, version-mismatched (`protocolVersion: 1`), or times out, SDK calls throw/raise `EngineUnavailableError` (`reason`: `"not-installed"` | `"version-mismatch"` | `"timeout"`) with zero cloud fallback. See [Quickstart](/platform/quickstart).
</Note>

***

## The write contract

| Property                               | Guarantee                                           |
| -------------------------------------- | --------------------------------------------------- |
| Local durability on return             | **Yes** — committed to disk before the call returns |
| Remote durability on return            | **No** — replication is asynchronous (write-behind) |
| Latency p50                            | **3.8 ms**                                          |
| Latency p95                            | 7.2 ms                                              |
| Latency p99                            | 12.5 ms                                             |
| Network behavior                       | **0 RTT on the call path**                          |
| Failure mode if replication is offline | Buffered locally; flushed when the network returns  |

Reproduce these numbers: `pnpm --filter @sovseal/mcp-server test bench-v2`.

***

## Arguments

```ts theme={null}
store_memory({ content: string })
```

That is the entire input schema — a single non-empty `content` string, length-capped by `STORE_MEMORY_MAX_CHARS`. There is no `path`, no `metadata`, and no `parent` argument.

## Return value

```json theme={null}
{
  "id": "a86938e9-de49-4a87-89de-edb62bef27b8",
  "reinforced": false,
  "redacted": 0,
  "redactedRules": []
}
```

* **`id`** — the local record identifier.
* **`reinforced`** — `true` when the content matched an existing memory closely enough to increment `reinforce_count` instead of inserting a new row.
* **`redacted`** / **`redactedRules`** — how many high-risk PII matches were masked before embedding, and which rules fired. The matched values are never returned or logged.

***

## The write pipeline

<Steps>
  <Step title="Redact high-risk PII">
    Content passes through the redaction chokepoint **before** anything else. The always-on trio — SSN, Luhn-validated credit cards, and provider API keys — is masked to `[REDACTED:…]` tokens. The secret therefore never reaches the vector, the stored row, or the sync envelope.
  </Step>

  <Step title="Embed on-device">
    The cleaned text runs through the local `Xenova/all-MiniLM-L6-v2` ONNX model (quantized, \~22 MB, auto-downloaded to `~/.sovseal/models/` and SHA-256 pinned), producing a **384-dimensional** vector. The embedding is stored locally and is **never sent to the server**.

    <Note>
      The MCP server and the browser extension currently run **different** embedders (`Xenova/all-MiniLM-L6-v2` vs. `intfloat/multilingual-e5-small`) — a same-day integrity-pinning fix reverted a brief mid-development unification. The two surfaces do not currently share one vector space. See `logs/escalation/EMBEDDER-minilm-e5-prefix-mismatch.md`.
    </Note>
  </Step>

  <Step title="Encrypt at rest">
    The `text` field is sealed with AES-256-GCM under `k_rest` — envelope format `sgcm1:` + base64(IV‖ciphertext‖tag), with a per-row 96-bit IV and `AAD = utf8(id|schema_version)`. The key is an HKDF subkey of a master that lives in your OS keychain.
  </Step>

  <Step title="Write to LanceDB, or reinforce">
    If an identical fact already exists, `reinforce_count` and `last_reinforced` are updated instead of inserting a duplicate. Otherwise a new Schema-v2 row is written.
  </Step>

  <Step title="Enqueue replication and return">
    The record enters the write-behind outbox and the call returns. A background `SyncWorker` seals the snapshot under `k_sync` and pushes ciphertext to the edge endpoint.
  </Step>
</Steps>

<Note>
  **Embedding vectors remain in the clear** on the local disk. Only `text` is encrypted at rest. This is a documented residual, not an oversight — see [Zero-Knowledge](/platform/core-concepts/zero-knowledge).
</Note>

***

## Calling it

<CodeGroup>
  ```json MCP tool call theme={null}
  // Sent by the AI client
  {
    "name": "store_memory",
    "arguments": {
      "content": "I prefer Vitest over Jest for new TypeScript projects."
    }
  }

  // Response
  {
    "id": "a86938e9-de49-4a87-89de-edb62bef27b8",
    "reinforced": false,
    "redacted": 0,
    "redactedRules": []
  }
  ```

  ```typescript Node SDK (store over local IPC) theme={null}
  import { AgentStateClient, EngineUnavailableError } from "@sovseal/sdk";

  const client = new AgentStateClient({
    endpoint: "https://ksrlmubaxzwufziwarps.supabase.co/functions/v1/v2-agent-state",
    apiKey: process.env.SOVSEAL_API_KEY!,
  });

  // Communicates over framed IPC with ~/.sovseal/native-host/run.sh.
  // Throws EngineUnavailableError if host is absent or version mismatched.
  try {
    const result = await client.store("I prefer Vitest over Jest for new TypeScript projects.");
    console.log(result.id, result.reinforced);
  } catch (err) {
    if (err instanceof EngineUnavailableError) {
      console.error(`Host unavailable: ${err.reason}, install at ${err.installUrl}`);
    }
  }
  ```
</CodeGroup>

***

## Failure modes

| Failure                                | What happens                                                                                                                |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Local disk is full                     | The write rejects before commit; no record is created                                                                       |
| Replication endpoint returns 4xx / 5xx | Local write is unaffected; the record stays in the outbox and retries                                                       |
| Network is offline                     | Same — buffered locally, flushed on reconnect                                                                               |
| Process crashes after commit           | The record survives locally; the outbox re-flushes on next start                                                            |
| Payload exceeds the chunk cap          | Rejected at the edge with `413` — the ciphertext cap is **256 KB**, see [Limits & SLAs](/platform/features/limits-and-slas) |

The design invariant: **replication failures can never lose or block a local write.**

***

## What reaches the server

Only what is needed to store and later restore an opaque blob:

* `agent_id` — `sha256(project_id ‖ ":" ‖ key)`. The server never learns the raw key name.
* `ciphertext` — AES-256-GCM sealed under `k_sync`.
* `client_payload_hash` — `sha256(canonicalize(payload))`, the integrity anchor for [Verified Semantic Recall](/platform/core-concepts/verified-semantic-recall).
* `sequence_number`, `parent_snapshot`, `timestamp` — lineage metadata.

**Never sent:** the plaintext, the encryption key, or the embedding vector.

***

## Next steps

<CardGroup cols={2}>
  <Card title="recall_memory" icon="magnifying-glass" href="/platform/core-concepts/recall-memory">
    How stored records become ranked query results — locally, with zero RTTs.
  </Card>

  <Card title="Verified Semantic Recall" icon="shield" href="/platform/core-concepts/verified-semantic-recall">
    What prevents a malicious server from substituting your ciphertext on restore.
  </Card>
</CardGroup>
