# Open Agent Memory Standard (OAMS) v0.1 — Public Draft

**Author:** REM Labs (Slopshop Inc.)
**Date:** 2026-04-27
**Status:** Public Draft, comments welcome
**License:** [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/) — the spec text is freely usable; reference implementations carry their own licenses.

---

## §1 Motivation

Modern AI agents lose context across vendors, sessions, and devices. Every memory provider — Mem0, Zep, MemPalace, REM, Letta, custom in-house systems — invents its own schema, its own retrieval semantics, its own export format, and its own consolidation hooks. This vendor-locks the user into the first tool they tried and makes it nearly impossible for downstream tooling (research, journalism, audit, regulators) to reason about what an agent actually knows.

OAMS is a portable schema and protocol for agent memory. It is intentionally minimal: a JSON object shape, five core operations, a namespace convention, a provenance contract, and an optional consolidation hook. Vendors implementing OAMS may layer additional capabilities on top — but a baseline OAMS-conforming export from one vendor MUST be ingestible by any other OAMS-conforming vendor.

The goal is not to standardize how memory is *retrieved* — fusion, rerank, hybrid search, and embeddings remain implementation details. The goal is to standardize how memory is *expressed and exchanged*, so that:

- Users can move their memory between agents the way they move email between providers.
- Researchers can audit what an agent knew at a point in time.
- Journalists and regulators can cite the original source of an agent claim.
- Open-source agents can plug into commercial memory backends and vice versa.

OAMS does not assume a particular embedding model, vector database, or LLM. It does not require a server — a single JSONL file on disk is a valid OAMS store.

---

## §2 Schema

A **memory** is a single JSON object with the following shape:

```json
{
  "key": "string",
  "namespace": "string",
  "value": "string",
  "tags": ["string", "..."],
  "metadata": { "...": "..." },
  "created_at": "2026-04-27T12:00:00Z",
  "updated_at": "2026-04-27T12:00:00Z",
  "embedding_model": "string",
  "embedding": [0.0123, -0.0456, "..."],
  "parent_id": "string | null",
  "source_id": "string | null"
}
```

### Field definitions

- **`key`** *(required, string)* — A stable identifier within a namespace. Implementations MAY use ULID, UUIDv7, content-hash, or a human-readable slug. The pair `(namespace, key)` is unique.
- **`namespace`** *(required, string)* — Scope envelope; see §4. Cross-namespace lookup is opt-in.
- **`value`** *(required, string)* — The memory content as a UTF-8 string. Markdown is permitted; binary is not. Implementations MAY define `value_type` in `metadata` (e.g. `markdown`, `plain`, `code`).
- **`tags`** *(optional, array of strings)* — Free-form labels for filtering. Tags are case-sensitive; implementations SHOULD lowercase on ingest.
- **`metadata`** *(optional, object)* — Arbitrary JSON-serializable map. Reserved keys: `value_type`, `confidence` (0.0–1.0), `last_used_at`, `decay_score`, `language`, `pii` (boolean).
- **`created_at`** *(required, RFC 3339 timestamp, UTC)* — When the memory was first written.
- **`updated_at`** *(required, RFC 3339 timestamp, UTC)* — Last write. Equal to `created_at` if never updated.
- **`embedding_model`** *(optional, string)* — Identifier of the embedding model used (e.g. `text-embedding-3-small`, `voyage-3`, `e5-mistral-7b`). Required if `embedding` is present.
- **`embedding`** *(optional, array of float32)* — Precomputed embedding vector. Producers MAY omit; consumers MUST handle absence by re-embedding under their own model.
- **`parent_id`** *(optional, string | null)* — `(namespace, key)` reference of the memory this one consolidates from. Used by dream/summarization pipelines.
- **`source_id`** *(optional, string | null)* — Provenance pointer to the original artifact (URL, file hash, transcript ID, message ID). See §5.

A memory is **valid** if it has `key`, `namespace`, `value`, `created_at`, and `updated_at`. Everything else is optional.

---

## §3 Operations

OAMS defines five core operations. Each is offered as a REST verb and a JSON-RPC method. Implementations MAY add operations but MUST support these five.

### `STORE` — write a memory

- **REST:** `PUT /v1/oams/memories/{namespace}/{key}` with the memory object as body.
- **JSON-RPC:** `oams.store({ memory })`.
- Returns the stored memory with server-assigned `created_at` / `updated_at` if not provided. Idempotent on `(namespace, key)`.

### `RECALL` — retrieve memories

- **REST:** `POST /v1/oams/recall` with `{ namespace?, query, k?, tags?, since?, until? }`.
- **JSON-RPC:** `oams.recall({ namespace, query, k, tags, since, until })`.
- `query` is a string; `k` is the desired result count (default 8). Returns an ordered array of memories. Ranking algorithm is implementation-defined; servers SHOULD include `score` in `metadata` of returned objects.

### `LIST` — enumerate without ranking

- **REST:** `GET /v1/oams/memories/{namespace}?cursor=&limit=&since=&tags=`.
- **JSON-RPC:** `oams.list({ namespace, cursor, limit, since, tags })`.
- Returns paged memories sorted by `updated_at` desc. Used for export and audit.

### `FORGET` — delete a memory

- **REST:** `DELETE /v1/oams/memories/{namespace}/{key}`.
- **JSON-RPC:** `oams.forget({ namespace, key })`.
- Returns `204 No Content` on success. Implementations MAY support soft-delete; if so, deleted memories MUST NOT appear in `RECALL` or `LIST` results.

### `BATCH_STORE` — write many memories atomically

- **REST:** `POST /v1/oams/memories/batch` with `{ memories: [...] }`.
- **JSON-RPC:** `oams.batch_store({ memories })`.
- Either all writes succeed or none do. Returns an array of stored memories.

### Errors

All operations return errors in the JSON-RPC error shape:

```json
{ "error": { "code": -32001, "message": "namespace not found", "data": { ... } } }
```

Reserved error codes:

- `-32001` namespace not found
- `-32002` memory not found
- `-32003` validation failed
- `-32004` quota exceeded
- `-32005` cross-namespace access denied

---

## §4 Namespaces

A **namespace** is the access-control envelope around a set of memories. Convention:

```
<owner-hash>:<scope>
```

- **`owner-hash`** — A stable identifier for the owning principal (user, org, agent). Implementations SHOULD use a hash so namespaces don't leak identifiers in logs. Example: `user-x123ab`.
- **`scope`** — A free-form label scoping the memory: `project-y`, `personal`, `archive`, `shared-team-q3`. Slashes and colons are not permitted in `scope`.

Examples:

- `user-x123ab:personal`
- `user-x123ab:project-mithril`
- `org-acme:legal-archive`
- `agent-research-bot:scratchpad`

### Cross-namespace retrieval

By default `RECALL` is scoped to a single namespace. Cross-namespace retrieval is opt-in per query:

```json
{
  "query": "what did I learn about FedRAMP?",
  "namespaces": ["user-x123ab:personal", "user-x123ab:project-mithril"],
  "k": 8
}
```

Implementations MUST refuse cross-namespace queries that span owners (e.g. `user-x123ab:*` and `user-y456cd:*`) unless the caller presents explicit consent for both owners. This is enforced by error `-32005`.

---

## §5 Provenance

Every memory SHOULD carry a `source_id` pointing to the original artifact it was derived from. This makes OAMS stores **citation-friendly** for research, journalism, regulatory audit, and downstream debugging.

Recommended `source_id` formats:

- URL: `https://example.com/article` (treat as opaque)
- File: `sha256:abc123...` (content-hash of original)
- Message: `imap:msgid:<...>` or `slack:CH123:1700000000.123456`
- Transcript: `transcript:<call-id>:<offset-seconds>`
- Synthesized (no single source): `null`

Consolidated memories produced by §6 dream strategies MUST set `parent_id` to the input memory key and SHOULD preserve `source_id` from the strongest input (or set it to a synthetic `dream:<strategy>:<run-id>` value).

When exporting (§7), implementations MUST NOT strip `source_id`. When importing, implementations MUST preserve it as-is — even if the importing system cannot resolve the URI.

---

## §6 Consolidation Hooks

OAMS defines an OPTIONAL `dream_strategy` enum that vendors MAY use to label consolidation operations. The enum is informational — OAMS does not specify how a strategy is implemented, only that vendors agree on the names.

```
dream_strategy ∈ {
  synthesize,      // merge multiple inputs into one canonical memory
  pattern_extract, // surface recurring structure across inputs
  insight_generate, // produce novel statement not present verbatim
  compress,        // lossy summary preserving key facts
  associate,       // link memories without rewriting them
  validate,        // cross-check a memory against others, flag contradictions
  evolve,          // update a memory in light of new evidence
  forecast,        // produce a forward-looking claim grounded in inputs
  reflect          // metacognitive summary about the memory store itself
}
```

When a vendor performs consolidation, the resulting memory SHOULD carry:

- `parent_id` pointing to the strongest input.
- `metadata.dream_strategy` set to one of the enum values.
- `metadata.dream_inputs` as an array of input `(namespace, key)` pairs.
- `metadata.dream_run_id` as a UUID grouping all outputs of one consolidation pass.

Vendors MAY define additional strategies as `dream_strategy: "vendor:<name>"` — these are passed through on export but downstream vendors MAY treat them as opaque.

---

## §7 Export Format

The canonical export format is **JSONL** (one memory object per line, UTF-8, LF-terminated). A complete export bundle is a directory:

```
oams-export-<timestamp>/
  manifest.json          # spec version, source vendor, namespace list, counts
  memories.jsonl         # one memory per line, sorted by created_at asc
  embeddings.bin         # OPTIONAL packed float32 vectors keyed by line offset
  README.md              # OPTIONAL human-readable summary
```

`manifest.json` shape:

```json
{
  "oams_version": "0.1",
  "source_vendor": "rem-labs",
  "exported_at": "2026-04-27T12:00:00Z",
  "namespaces": ["user-x123ab:personal", "user-x123ab:project-mithril"],
  "memory_count": 4218,
  "embedding_model": "text-embedding-3-small",
  "checksum_sha256": "..."
}
```

### Markdown serialization (optional)

For human-readable export, OAMS defines a Markdown serialization where each memory is a section:

```markdown
## key: 01HX...

**namespace:** `user-x123ab:personal`
**created:** 2026-04-27T12:00:00Z
**updated:** 2026-04-27T12:00:00Z
**source:** https://example.com/article
**tags:** `research`, `memory`

The actual `value` text goes here as Markdown body.

---
```

### Compatibility with existing vendors

OAMS is designed to be a clean superset of common vendor exports:

- **Mem0 export** — Mem0 `messages` and `memories` arrays map to OAMS memories with `metadata.mem0_role` preserved. Mem0 `user_id` becomes the `owner-hash` half of `namespace`.
- **Zep export** — Zep `Session` becomes a `scope` segment. Zep `Message` becomes a memory with `metadata.zep_role`. Zep summaries become memories with `metadata.dream_strategy = "compress"`.
- **MemPalace export** — MemPalace nodes map 1:1; edges become OAMS `parent_id` chains plus `metadata.mempalace_edge_type`.
- **REM export** — REM `dreams` map to OAMS memories with `metadata.dream_strategy` populated from the existing REM strategy enum.

A reference converter for each vendor SHOULD be published alongside the vendor's OAMS implementation.

---

## §8 Versioning Policy

OAMS follows [Semantic Versioning](https://semver.org/) 2.0.0.

- **PATCH** (0.1.0 → 0.1.1) — clarifications, typos, non-normative additions.
- **MINOR** (0.1 → 0.2) — backward-compatible additions: new optional fields, new enum values, new operations. Existing implementations continue to interoperate.
- **MAJOR** (0.x → 1.0) — first stable release. Breaking changes thereafter (1.0 → 2.0) require a 12-month deprecation window, dual-support guidance, and an explicit migration document.

The `oams_version` string in `manifest.json` MUST match the spec version a producer was built against. Consumers SHOULD accept any compatible MINOR version and SHOULD warn (not error) on unknown enum values.

The current draft is **0.1**. It is unstable and subject to change until 1.0.

---

## §9 Reference Implementations

- **REM Labs** — Private beta Q3 2026. Backed by REM's existing memory backbone with a thin OAMS adapter on `/v1/oams/*`. Full export + import + cross-vendor migration.
- *(vendors invited to PR — open an issue with your implementation status and we will list it here)*

If you ship an OAMS-conforming implementation, please open a PR adding:

- Vendor name and homepage
- Conformance level (read-only export, full read/write, full + consolidation)
- Last spec version tested against
- Link to your converter / SDK

---

## §10 PR / Contribution

OAMS is a public draft and welcomes external input.

### How to propose a change

1. Open an issue at `https://github.com/remlabs-ai/oams-spec/issues` describing the problem and a proposed solution. Search for existing discussion first.
2. For non-trivial changes, write a one-page rationale before the PR. Include: motivation, alternatives considered, backwards-compatibility analysis, migration impact.
3. Open a PR against `main`. Spec changes go in this file (`OAMS-SPEC.md`). Reference-implementation changes go in their own repos.
4. PRs require at least one maintainer review. Spec text changes also require a 7-day comment window before merge.

### Style

- Use RFC 2119 keywords (MUST, SHOULD, MAY) for normative statements.
- Examples are illustrative; do not rely on them as test fixtures.
- Prefer JSON over prose when defining shapes.

### Governance

OAMS is currently stewarded by REM Labs. The intent is to move it to a vendor-neutral foundation (a workgroup under an existing standards body, or a new lightweight foundation) once we have at least three independent implementations. Until then, REM Labs commits to:

- Publishing all spec changes as PRs with public comment windows.
- Refusing to add features that only REM Labs can implement.
- Accepting RFCs from any vendor with a working implementation.

### License recap

Spec text: **CC-BY 4.0** — copy, fork, adapt, redistribute. Attribution: "Open Agent Memory Standard, REM Labs et al."

Reference implementations: each carries its own license. The REM Labs reference implementation is dual-licensed AGPL-3.0 / commercial.

---

*Comments and questions: dev@remlabs.ai*
