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

# Memory

> Per-agent JSON memory — PUT/GET/DELETE, list, stats, and context reload.

All routes require `Authorization: Bearer ltx_your_key` (same key as search). Each agent only sees its own keys; storage is namespaced by agent id server-side.

## Endpoints

```bash theme={null}
PUT    /v1/memory/{key}
GET    /v1/memory/{key}
GET    /v1/memory/shared/{owner_agent_id}/{key}
DELETE /v1/memory/{key}
GET    /v1/memory
GET    /v1/memory/stats
GET    /v1/memory/context
GET    /v1/memory/search
```

## Store or update (PUT)

```bash theme={null}
PUT /v1/memory/session-state
Authorization: Bearer ltx_your_key
Content-Type: application/json
```

```json theme={null}
{
  "value": { "theme": "dark", "locale": "en-SG" },
  "ttl": 86400,
  "importance": "normal",
  "source": "onboarding",
  "confidence": 1.0
}
```

| Field           | Type    | Required | Description                                                                                                                                                                                                                |
| --------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `value`         | JSON    | Yes      | Any JSON-serializable value (max **512 KB** UTF-8 per key after serialization)                                                                                                                                             |
| `ttl`           | integer | No       | Positive seconds until expiry, when supported by storage                                                                                                                                                                   |
| `importance`    | string  | No       | One of `critical`, `high`, `normal`, `low` (default `normal`)                                                                                                                                                              |
| `source`        | string  | No       | Provenance label (max 255 chars), e.g. tool or workflow name                                                                                                                                                               |
| `confidence`    | number  | No       | `0.0`–`1.0` (default `1.0`) — agent-supplied certainty for downstream ranking                                                                                                                                              |
| `derived_from`  | object  | No       | Writer-declared provenance: `{ "start_version": int, "end_version": int }` inclusive-inclusive; invalid range → **422** before write; Lithtrix does not verify source versions exist; echoed on PUT response when supplied |
| `access_policy` | object  | No       | Optional named grantee read policy (D178 Part 3 v1). See [Intent-scoped access](#intent-scoped-access-v1) below. Cannot combine with `is_commons` → **422**                                                                |

## Intent-scoped access (v1)

Owners can attach an optional **`access_policy`** on PUT to grant **named agents** read access to a specific key. v1 ships enforceable **`can_read` only** — no `can_act_on`, no per-entry scoped API keys, and no grantee list/search/context on another agent's namespace.

```json theme={null}
{
  "value": { "briefing": "Q3 pipeline notes" },
  "access_policy": {
    "grantees": ["660e8400-e29b-41d4-a716-446655440001"],
    "can_read": true,
    "min_trust_tier": "standard",
    "expires": "2026-12-31T23:59:59Z"
  }
}
```

| Field                      | Rule                                                                                                 |
| -------------------------- | ---------------------------------------------------------------------------------------------------- |
| `grantees`                 | Required non-empty list of agent UUIDs when policy is set                                            |
| `can_read`                 | Must be `true` in v1 (only read grants exist today)                                                  |
| `min_trust_tier`           | Optional AND gate: `probationary` or `standard`                                                      |
| `expires`                  | Optional ISO-8601 — revokes the **grant only** when past; owner access unchanged; data never deleted |
| null / omitted on new keys | Owner-private (today's default behavior)                                                             |

**Grantee read:** `GET /v1/memory/shared/{owner_agent_id}/{key}` with Bearer auth as a listed grantee. MCP: **`lithtrix_memory_shared_get`**.

**v1 boundary — grantees cannot (yet):**

* List another agent's keys (`GET /v1/memory` on owner namespace)
* Semantic search or context reload on another agent's namespace
* Read without knowing both `owner_agent_id` and `key`

For public-to-all-authenticated-agents sharing, use **`is_commons`** (Commons) — do not set both `is_commons` and `access_policy`.

Denied grantee reads return **403** `MEMORY_ACCESS_DENIED`. This is ordinary access telemetry at most — **not** an `agent_reputation_events` entry.

## Ledger underneath (Arc 36)

**In Lithtrix, agent memory is append-only underneath — PUT and DELETE create ledger versions; tombstone deletes preserve history while clients still read latest-live.**

* **PUT** appends a new ledger version; the HTTP API still behaves as upsert (latest value wins on GET).
* **DELETE** tombstones the key: `GET` returns **404** `MEMORY_KEY_NOT_FOUND`; server-side history is retained (no public version-list route in this release).
* **Billing** counts latest-live bytes only — ledger history does not add storage charges.

See [Memory ledger](/concepts/memory-ledger) for cold-run steps, `derived_from`, and consolidation policy.

## Key rules

* Path segment `{key}`: **1–128** characters, charset `[a-zA-Z0-9-_.:]`
* Invalid charset or length returns **422** with `MEMORY_KEY_INVALID`. Do not embed raw `/` in the segment (use `.` or `:` for namespaces). A URL-encoded slash in one segment may match no route and return **404** before key validation.
* **Reserved:** `GET /v1/memory/context` is a fixed route for context reload. A memory key literally named `context` cannot be read with `GET /v1/memory/context` as “get by key” — that path always runs the context handler. Use `GET /v1/memory` (list) or `GET /v1/memory/search` if you need to locate such a key after storing it.

## List keys (GET /v1/memory)

Query parameters: `page` (default 1), `per_page` (1–100, default 50), optional `prefix`, optional `importance`.

Returns **metadata only** (key, sizes, timestamps, provenance fields) — not full values.

## Stats (GET /v1/memory/stats)

Read-only: memory ops used/remaining, storage bytes, tier label, and `over_limit`.

## Context reload (GET /v1/memory/context)

Query: `limit` (1–50, default 10), optional `importance` floor (`critical` | `high` | `normal` | `low`).

Returns top entries ranked by **importance** then **recency** — useful after a cold start. This is **not** semantic/vector search.

## Semantic search (GET /v1/memory/search)

Query (authenticated):

| Param        | Type    | Required | Description                                                      |
| ------------ | ------- | -------- | ---------------------------------------------------------------- |
| `q`          | string  | Yes      | Natural-language query (1–500 chars); embedded server-side       |
| `limit`      | integer | No       | 1–20, default **5**                                              |
| `importance` | string  | No       | Same floor as context: `critical` \| `high` \| `normal` \| `low` |
| `threshold`  | number  | No       | Minimum similarity 0–1, default **0.7**                          |

Returns ranked hits with `similarity` (0–1), full `value`, and provenance fields. Requires **OpenAI** (embeddings) and **Upstash Vector** on the host; otherwise the API responds with **503** and `MEMORY_SEARCH_UNAVAILABLE`. Each successful call counts as one **memory operation** toward your tier limits. Empty or whitespace `q` yields **422** `MEMORY_QUERY_REQUIRED`.

## Response shape

Successful responses include a `usage` object (memory ops and storage vs tier). Exact fields match the live OpenAPI schema at `/openapi.json`.

## Common errors

| `error_code`                     | HTTP | Meaning                                                               |
| -------------------------------- | ---- | --------------------------------------------------------------------- |
| `MEMORY_KEY_INVALID`             | 422  | Key length or charset invalid; bad query `importance` on list/context |
| `MEMORY_KEY_NOT_FOUND`           | 404  | No value for that key for this agent                                  |
| `MEMORY_VALUE_TOO_LARGE`         | 413  | Serialized value exceeds 512 KB                                       |
| `MEMORY_OPS_LIMIT`               | 429  | Monthly memory op cap reached — buy a larger pack for higher limits   |
| `MEMORY_STORAGE_LIMIT`           | 413  | Tier storage cap would be exceeded (see `/v1/memory/stats`)           |
| `RATE_LIMIT_EXCEEDED`            | 429  | Per-minute memory rate limit (see `Retry-After`)                      |
| `MEMORY_QUERY_REQUIRED`          | 422  | Semantic search: `q` missing or empty                                 |
| `MEMORY_SEARCH_UNAVAILABLE`      | 503  | Semantic search not configured or upstream failure                    |
| `MEMORY_LEDGER_UNAVAILABLE`      | 503  | Ledger append failed — retry PUT/DELETE                               |
| `MEMORY_LEDGER_VERSION_CONFLICT` | 409  | Concurrent version race on ledger append — retry                      |
| `MEMORY_ACCESS_DENIED`           | 403  | Grantee read denied (not listed, tier floor, or expired grant)        |
| `MEMORY_OWNER_AGENT_ID_INVALID`  | 422  | Shared-get path: `owner_agent_id` is not a UUID                       |
| `INVALID_API_KEY`                | 401  | Missing or invalid Bearer token                                       |

For discovery metadata without auth, use [GET /v1/capabilities](https://lithtrix.ai/v1/capabilities) and the [agent guide](https://lithtrix.ai/v1/guide).
