# Open Memory Interchange — Formal Specification

**Spec ID:** OMI-AI/0.1-draft  
**Status:** Public Review Draft / not a stable 1.0 release  
**Format version:** `0.1`  
**Primary file extension:** `.omi.json`  
**Primary media type:** `application/vnd.omi+json`  
**Streaming file extension:** `.omi.jsonl`  
**Streaming media type:** `application/vnd.omi+jsonl`  
**JSON Schema:** JSON Schema Draft 2020-12, with L0 and L1 schemas in Appendix B  
**Canonical release posture:** small, neutral, snapshot-first memory interchange floor

> **Name and acronym are provisional.** “Open Memory Interchange” and “OMI-AI” are working names. The floor’s value is neutrality, not ownership or branding. Before public launch, the working group should resolve naming, domain, repository ownership, and governance. The format was previously named “Open Memory Record” (OMR), but that acronym collided with the widely used acronym for Optical Mark Recognition; it has since been renamed to Open Memory Interchange (OMI-AI). Do not lock the name or acronym until searchability and standards-positioning have been checked. A memory portability floor adopters do not perceive as one author’s front door is the floor most likely to be adopted.

---

## 0. Abstract

Open Memory Interchange is a minimal, vendor-neutral JSON format for exporting and importing AI, assistant, and agent memory between tools. Its only job is **portability**: a producer can emit an OMI-AI file, and a consumer can read that file without sharing a storage engine, query language, governance model, ontology, vector index, or vendor-specific runtime.

OMI-AI is deliberately thin. It defines:

1. a file **envelope**;
2. a human-readable **memory record**;
3. a small set of optional descriptive fields;
4. an extension object, `ext`, for everything above the floor;
5. two serializations of the same model: a single JSON document and a JSON Lines streaming form.

OMI-AI does **not** define a query language, schema language, lifecycle model, full provenance graph, integrity/signature scheme, embedding standard, storage engine, sync protocol, or notation language. Those concerns are real, but they belong in optional profiles layered on top of the floor.

The core invariant is simple:

> A floor-only OMI-AI record remains legible from `content` alone.

A record may carry type hints, source hints, validity dates, tags, entities, relations, language metadata, and extension profiles. But a consumer that understands none of those still receives a readable memory.

This document is not a claim that OMI-AI is stable. It is a formal public-review draft. A stable 1.0 should require implementation feedback, conformance fixtures, at least two independent import/export implementations, and a governance home.

---

## 1. Design goals and non-goals

### 1.1 Goals

1. **Portability above all.** A file is self-describing and tool-independent.
2. **A floor anyone can reach.** Existing provider exports, assistant memories, agent memories, CRM notes, local knowledge-vault notes, and application-specific memory stores can be converted into OMI-AI without adopting a theory of memory.
3. **Snapshot-first interchange.** OMI-AI core represents export/import snapshots. Incremental synchronization, tombstones, mutation operations, and conflict policies are optional profile concerns.
4. **Human-readable anchor.** Every record has `content`: a readable text anchor. The record is not only an opaque structured object.
5. **Open memory type vocabulary.** `type` is an open string. OMI-AI recommends `semantic`, `episodic`, and `procedural`, but does not require or exhaust memory taxonomy.
6. **Forward and outward compatibility.** Unknown extension profiles do not make a file invalid. Lossless round-trip processors preserve unknown extensions.
7. **Profile pressure valve.** Governance, integrity, schema, provenance, retrieval, and sync live in named profiles under `ext`, not in the core.
8. **Large-export viability.** OMI-AI supports both ordinary JSON files and JSON Lines for large exports and streaming pipelines.
9. **Boring on purpose.** Plain JSON, no custom syntax, no required cryptography, no required ontology, no required embeddings, no required hosted registry.

### 1.2 Non-goals

OMI-AI explicitly does **not** specify, and a floor implementation MUST NOT require, any of the following:

- **A query or traversal language.** Searching and querying memories are consumer/runtime concerns.
- **A schema, shape, or ontology language.** Per-domain validation belongs in the optional `schema` profile. OMI-AI core only validates the generic interchange envelope and record floor.
- **A governance or lifecycle model.** States, review workflows, immutability-with-supersession, effective views, and acceptance semantics belong in the optional `governance` profile. In OMI-AI core, a relation with type `supersedes` is a link hint only.
- **An integrity, hash, seal, or signature scheme.** OMI-AI core defines no `hash` field. Content-only hashes create false assurance because they do not protect record metadata, source, validity, relations, or extensions. Hashing, canonicalization, sealing, and signatures belong in the optional `integrity` profile.
- **An embedding or vector portability model.** Embeddings are model-specific retrieval artifacts. They are not portable memory substance. Embedding vectors and vector references belong in the optional `retrieval` profile.
- **A sync protocol.** Delta exports, tombstones, deletes, last-write-wins, conflict resolution, cursors, and operations belong in the optional `sync` profile.
- **A storage engine, index, transport, or authorization model.** OMI-AI defines file interchange, not runtime infrastructure.
- **A canonical claim graph.** Strong claim immutability, provenance chains, authority, formal composition, and governed query/mutation are higher-layer concerns, not OMI-AI core.

These exclusions are a commitment, not an omission. They are what make OMI-AI politically and technically small enough to be a shared floor between parties who disagree about everything above it.

---

## 2. Governance, licensing, and release status

### 2.1 Governance intent

OMI-AI is intended to be governed by a neutral standards body, foundation, or open working group. No implementation is required to use any specific vendor, hosted registry, storage service, model provider, or cloud endpoint.

The reference repository SHOULD be owned by a neutral organization before any stable release. The public draft MAY be authored by an individual or company, but the release text MUST make clear that the format is intended for neutral stewardship.

### 2.2 Proposed licenses

For public release, the recommended licensing split is:

| Artifact | Recommended license |
|---|---|
| Specification text | CC BY 4.0 or CC0-1.0 |
| JSON Schemas | MIT or Apache-2.0 |
| Test fixtures | MIT or Apache-2.0 |
| Reference implementation | MIT or Apache-2.0 |

The final chosen license MUST be stated in the repository before public release. A serious implementer should not have to infer reuse rights from repository convention.

### 2.3 Release status

This document is suitable for **public review** after editorial cleanup and repository packaging. It is not suitable for a stable 1.0 release until the following exist:

1. versioned schemas;
2. conformance fixtures;
3. at least two independent import/export implementations;
4. an extension/profile registry policy;
5. declared license and governance;
6. a resolved publication name/domain/repository.

---

## 3. Conformance and terminology

The key words **MUST**, **MUST NOT**, **REQUIRED**, **SHOULD**, **SHOULD NOT**, **MAY**, and **OPTIONAL** are to be interpreted as described in RFC 2119 and RFC 8174.

### 3.1 Conformance levels

OMI-AI defines two data conformance levels.

| Level | Name | Requirements |
|---|---|---|
| **L0** | Core | Valid envelope; every record has `id`, `content`, and `created`. |
| **L1** | Interchange | L0 plus: every record has `type`; record IDs are unique within the file; timestamp fields are valid RFC 3339 date-times where required; `valid_from` and `valid_to` are valid date or date-time values where present; every record has an effective subject, either inherited from the envelope or present on the record. |

A producer SHOULD emit L1 unless it is performing a minimal legacy conversion. A consumer MUST accept L0. A consumer SHOULD accept L1. A consumer MUST NOT reject a record solely because optional fields, unknown fields, or unknown `ext` profiles are present.

### 3.2 Processor conformance classes

Data conformance and processor behavior are separate. A tool MAY claim one or more of the following processor classes:

| Processor class | Meaning |
|---|---|
| `omi-reader` | Can parse OMI-AI and expose recognized core fields. |
| `omi-writer` | Can produce OMI-AI at a declared conformance level. |
| `omi-validator-l0` | Can validate the L0 structural floor. |
| `omi-validator-l1` | Can validate L1 rules, including ID uniqueness and effective subject. |
| `omi-lossless-roundtrip` | Can import and re-export OMI-AI while preserving unknown fields and unknown `ext` profiles according to §10.3. |
| `omi-lossy-importer` | Can import OMI-AI into a native store but may discard unknown fields/extensions; MUST disclose this behavior. |
| `omi-profile-<name>` | Implements a named profile, e.g. `omi-profile-integrity`. |

A validator is not required to preserve unknown data. A round-trip processor is. An importer that discards unknown `ext` MUST NOT advertise lossless round-trip support.

### 3.3 Glossary

- **Record** — one memory item; the atomic unit of OMI-AI.
- **Envelope** — the file-level object containing format identity, optional subject/default metadata, records, and file-level extensions.
- **JSON serialization** — the ordinary `.omi.json` form: one JSON object containing an envelope and a `memories` array.
- **JSONL serialization** — the `.omi.jsonl` form: one envelope object on the first line, followed by one record object per line.
- **Profile** — an optional, separately specified feature set carried under a key in `ext`.
- **Subject** — the principal the memory is primarily about: a person, agent, organization, group, project, system, device, account, topic, or other identifiable memory owner/topic.
- **Effective subject** — the record-level `subject` if present; otherwise the envelope-level `subject` if present.
- **Snapshot** — a complete export view at a point in time. Absence of a record in a snapshot is not a deletion instruction.
- **Delta** — an incremental synchronization payload. Deltas are not defined by OMI-AI core; they belong in the `sync` profile.
- **Extension profile** — a named block under `ext`, such as `integrity`, `governance`, or `retrieval`.
- **Floor-only processor** — a processor that implements OMI-AI core but no optional profiles.

---

## 4. File formats and serializations

OMI-AI defines one data model with two serializations.

### 4.1 Ordinary JSON serialization

The ordinary `.omi.json` file is a single UTF-8 JSON document, without a byte-order mark, containing exactly one envelope object.

Rules:

- A `.omi.json` file MUST be valid JSON as defined by RFC 8259.
- A `.omi.json` file MUST contain one envelope object.
- The envelope object MUST contain a `memories` array.
- The envelope `serialization` field MAY be omitted or set to `"json"`.
- Producers SHOULD end the file with a trailing newline.
- Consumers MUST NOT require object-key order.
- OMI-AI core does not require canonical JSON serialization.

Example:

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "serialization": "json",
  "subject": { "id": "user-123", "type": "person", "label": "Freddy" },
  "generated_at": "2026-06-06T09:00:00Z",
  "generator": "example-tool/1.4",
  "memories": [
    {
      "id": "01JZ0WFR4K2Q6N7S8T9V0ABCDF",
      "content": "User prefers direct, critical pushback over agreement.",
      "type": "semantic",
      "created": "2026-01-15T10:30:00Z"
    }
  ]
}
```

### 4.2 JSON Lines serialization

The `.omi.jsonl` serialization exists for large exports, streaming, command-line processing, append-friendly pipelines, and mobile/edge importers that should not have to load a large array into memory.

Rules:

- A `.omi.jsonl` file MUST be UTF-8 without a byte-order mark.
- Each line MUST be one complete JSON object.
- Blank lines MUST NOT appear.
- The first line MUST be an envelope object.
- In JSONL serialization, the envelope object MUST set `serialization` to `"jsonl"`.
- In JSONL serialization, the envelope object MUST omit `memories`.
- Each subsequent line MUST be one memory record object.
- A JSONL file containing only the envelope line represents an empty memory set.
- Record order is the order of subsequent lines.
- The JSONL serialization uses the same envelope fields, record fields, conformance levels, extension rules, and profile rules as the ordinary JSON serialization.
- A processor MAY convert `.omi.jsonl` to `.omi.json` by collecting all record lines into the `memories` array of the first-line envelope.

Example:

```jsonl
{"format":"open-memory-interchange","version":"0.1","serialization":"jsonl","subject":{"id":"user-123","type":"person","label":"Freddy"},"generated_at":"2026-06-06T09:00:00Z","generator":"example-tool/1.4"}
{"id":"01JZ0WFR4K2Q6N7S8T9V0ABCDF","content":"User prefers direct, critical pushback over agreement.","type":"semantic","created":"2026-01-15T10:30:00Z"}
{"id":"01JZ0WG9N2RC94Z6K9TDTA3Q8M","content":"User lives in Dubai.","type":"semantic","created":"2026-05-01T09:02:11Z"}
```

### 4.3 Timestamp and date rules

OMI-AI distinguishes timestamp fields from validity-boundary fields.

| Field category | Fields | Allowed form |
|---|---|---|
| Timestamp fields | `generated_at`, `created`, `updated` | RFC 3339 date-time only, e.g. `2026-06-06T09:00:00Z`. |
| Validity boundary fields | `valid_from`, `valid_to` | RFC 3339 date-time or RFC 3339 full-date, e.g. `2026-06-06T09:00:00Z` or `2026-06-06`; `valid_to` may also be `null`. |

A date is not the same as midnight UTC. Producers SHOULD use date-only values where only date precision is honestly known. Consumers MUST NOT reinterpret a date-only validity boundary as a precise timestamp unless a profile explicitly defines that convention.

### 4.4 Character encoding

All strings are Unicode strings in JSON. A file MUST be UTF-8. Producers SHOULD normalize strings to Unicode NFC where practical, but consumers MUST NOT reject a file solely because string normalization differs.

---

## 5. The envelope

The envelope is the file-level object. It identifies the format, version, optional default subject, optional ID namespace, generation metadata, the records, and file-level extension profiles.

### 5.1 Envelope example

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "serialization": "json",
  "subject": {
    "id": "user-123",
    "type": "person",
    "label": "Freddy"
  },
  "id_namespace": "urn:omi:example-tool:user-123:",
  "generated_at": "2026-06-06T09:00:00Z",
  "generator": "example-tool/1.4",
  "memories": [],
  "ext": {}
}
```

### 5.2 Envelope field reference

| Field | Type | Card. | Notes |
|---|---|---|---|
| `format` | string | 1 | MUST be `"open-memory-interchange"`. |
| `version` | string | 1 | Format version, `major.minor`. This document defines `"0.1"`. |
| `serialization` | string | 0..1 | `"json"` for `.omi.json`; `"jsonl"` is REQUIRED on the first line of `.omi.jsonl`. If absent in `.omi.json`, default is `"json"`. |
| `subject` | object | 0..1 | Default subject inherited by records that omit record-level `subject`. REQUIRED at L1 unless every record carries its own `subject`. |
| `id_namespace` | string | 0..1 | Optional namespace used to scope non-global record IDs during merge/import. See §6.2 and §13. |
| `generated_at` | timestamp | 0..1 | When the export file was produced. |
| `generator` | string | 0..1 | Producing tool and version, e.g. `"example-tool/1.4"`. |
| `memories` | array | 1 in `.omi.json`; omitted in `.omi.jsonl` | Zero or more record objects. MAY be empty. |
| `ext` | object | 0..1 | File-level extension profiles. |

A consumer MUST reject a file whose `format` is not `"open-memory-interchange"`. A consumer MUST reject a major `version` it does not support. A consumer SHOULD accept later minor versions by ignoring fields it does not recognize, subject to §10.

### 5.3 Subject object

A `subject` object identifies the principal the memory is primarily about.

| Field | Type | Card. | Notes |
|---|---|---|---|
| `id` | string | 1 | Stable subject identifier if available. Opaque to OMI-AI core. |
| `type` | string | 0..1 | Recommended values include `person`, `agent`, `organization`, `group`, `project`, `system`, `device`, `account`, `topic`. Open vocabulary. |
| `label` | string | 0..1 | Human display name. |

A record MAY carry its own `subject`. If present, the record-level subject overrides the envelope-level subject for that record. If absent, the record inherits the envelope-level subject. At L1, every record MUST have an effective subject: record-level or inherited.

Examples:

```json
"subject": { "id": "user-123", "type": "person", "label": "Freddy" }
```

```json
"subject": { "id": "workspace-778", "type": "group", "label": "Design Review Slack Channel" }
```

```json
"subject": { "id": "project-infra", "type": "project", "label": "INFRA" }
```

### 5.4 Multi-subject exports

Multi-subject exports are allowed. Producers SHOULD use one of two strategies:

1. put a common default subject on the envelope and override only exceptional records; or
2. omit envelope `subject` and put `subject` on every record.

At L1, the second strategy is valid only if every record has a record-level `subject`. This makes group chats, Slack exports, Discord servers, CRM exports, shared team agents, and multi-agent traces portable without hiding subject data in an extension profile.

---

## 6. The memory record

The record is the atomic memory item. The required L0 floor is only:

```text
id + content + created
```

Everything else is optional.

### 6.1 Record example

```json
{
  "id": "01JZ0WFR4K2Q6N7S8T9V0ABCDF",
  "subject": { "id": "user-123", "type": "person", "label": "Freddy" },
  "content": "User prefers direct, critical pushback over agreement.",
  "type": "semantic",
  "created": "2026-01-15T10:30:00Z",
  "updated": "2026-05-01T09:02:11Z",
  "confidence": 0.92,
  "lang": "en",
  "tags": ["communication", "preference"],
  "source": {
    "platform": "claude",
    "ref": "session-882",
    "method": "extracted"
  },
  "valid_from": "2026-01-15",
  "valid_to": null,
  "entities": [
    { "id": "ent-freddy", "label": "Freddy", "type": "person" }
  ],
  "relations": [
    { "type": "relates_to", "target": "01JZ0WG9N2RC94Z6K9TDTA3Q8M", "label": "working style" }
  ],
  "ext": {}
}
```

### 6.2 Record field reference

| Field | Type | Card. | Notes |
|---|---|---|---|
| `id` | string | 1 | Opaque non-empty record identifier. MUST be unique within the file at L1. SHOULD be stable and collision-resistant across repeated exports. |
| `subject` | object | 0..1 | Record-level subject. Overrides envelope subject for this record. See §5.3–§5.4. |
| `content` | string | 1 | The memory as human-readable text. May contain Markdown. This is the neutral anchor: a record is always legible from `content` alone. |
| `type` | string | 0..1 | Open vocabulary. REQUIRED at L1. See §8. |
| `created` | timestamp | 1 | When the memory was first recorded. MUST be RFC 3339 date-time. |
| `updated` | timestamp | 0..1 | When the record was last materially updated by the source system. MUST be RFC 3339 date-time if present. |
| `confidence` | number | 0..1 | Number in `[0.0, 1.0]`. Asserted belief strength or source confidence. |
| `lang` | string | 0..1 | BCP 47 language tag for `content`, e.g. `en`, `ar`, `ku`, `en-GB`. |
| `tags` | array of string | 0..1 | Free-form labels. |
| `source` | object | 0..1 | Lightweight provenance/source hint. See §7. |
| `valid_from` | date-time \| date | 0..1 | Start of real-world validity. |
| `valid_to` | date-time \| date \| null | 0..1 | End of real-world validity. `null` or absent means open/unknown. |
| `entities` | array of object | 0..1 | Descriptive entity mentions or references. See §9. |
| `relations` | array of object | 0..1 | Typed links to local records or external references. See §9. |
| `ext` | object | 0..1 | Record-level extension profiles. |

There is intentionally no core `hash` field and no core `embedding` field. Checksums and signatures belong in `ext.integrity`. Embeddings and retrieval artifacts belong in `ext.retrieval`.

### 6.3 ID stability and collision guidance

The record `id` is opaque. Consumers MUST NOT infer semantics from the structure of an `id`.

Producers SHOULD emit stable, collision-resistant IDs across repeated exports of the same underlying memory. Recommended forms include:

- UUIDv7;
- UUIDv4;
- ULID;
- URN;
- absolute URI;
- a source-namespaced identifier.

Simple sequential identifiers such as `"1"` or `"2"` SHOULD NOT be emitted unless scoped by an `id_namespace` or otherwise guaranteed not to collide during merges.

If an export must preserve source-local IDs, the producer SHOULD set envelope `id_namespace`.

Example:

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "id_namespace": "urn:omi:legacy-ios:user-123:",
  "memories": [
    {
      "id": "1",
      "content": "User prefers concise meeting notes.",
      "type": "semantic",
      "created": "2026-01-01T00:00:00Z"
    }
  ]
}
```

For merge/import purposes, a consumer MAY treat the effective merge key as the tuple `(id_namespace, id)` where `id_namespace` is present. OMI-AI core does not require consumers to concatenate these values into a single string. In-file relation resolution still uses exact local `id` matching first (§9.3).

### 6.4 Unknown record fields outside `ext`

Unknown fields outside `ext` are allowed for forward compatibility. However:

- Producers SHOULD place non-core data under `ext` rather than minting new top-level record fields.
- Consumers MUST NOT interpret unknown top-level fields as OMI-AI core semantics.
- Lossless round-trip processors MUST preserve unknown fields according to §10.3.
- Validators MAY warn about unknown fields outside `ext`, but MUST NOT reject them solely on that basis unless the validator is running a stricter profile.

The purpose of this rule is to prevent the core from becoming a loose collection of vendor-specific semi-core fields while still allowing additive evolution and safe round-trips.

Because the interchange schemas in Appendix B are intentionally lenient (they tolerate unknown properties), an implementation MAY additionally publish a *strict* producer-side schema variant that sets `additionalProperties: false` on the envelope and record objects, so producers can catch misspelled field names before export. A strict schema is a producer linting aid only; consumers MUST remain lenient per §6.4 and §10.

---

## 7. Source and lightweight provenance

The `source` object is intentionally lightweight. It is not a W3C PROV graph and does not define authority, derivation, or governance. It gives an importer enough context to preserve where a memory came from.

### 7.1 Source object field reference

| Field | Type | Card. | Notes |
|---|---|---|---|
| `platform` | string | 0..1 | Origin tool/provider/system, e.g. `"chatgpt"`, `"claude"`, `"mem0"`, `"local-agent"`. |
| `ref` | string | 0..1 | Opaque origin reference: session ID, message ID, document ID, URI, trace ID, etc. |
| `method` | string | 0..1 | Recommended vocabulary below; open string. |

### 7.2 Recommended `source.method` vocabulary

`source.method` is an open string. Consumers MUST NOT reject unknown methods. Producers SHOULD use the following values where applicable:

| Method | Meaning |
|---|---|
| `asserted` | Directly stated by a user, human, or agent. |
| `extracted` | Extracted from a conversation, document, trace, or event. |
| `imported` | Converted from another memory format or source store. |
| `observed` | Captured from event, tool use, sensor, runtime, or environment observation. |
| `derived` | Inferred from other records or reasoning output. |

Rich provenance belongs in the `provenance` profile. For example, W3C PROV-style derivation graphs, source spans, evidence anchors, model call traces, and authority chains should be carried under `ext.provenance`, not in core.

---

## 8. Memory types

`type` is an **open string**. It is REQUIRED at L1 and OPTIONAL at L0.

Producers SHOULD use one of the three recommended base values when they fit:

| Recommended value | Meaning |
|---|---|
| `semantic` | Facts, concepts, preferences, standing knowledge. |
| `episodic` | Time-bound events, sessions, experiences, observations. |
| `procedural` | How-to knowledge, runbooks, step-by-step processes. |

Any other string is permitted. Consumers MUST NOT reject a record solely because `type` is unrecognized.

Finer-grained taxonomies such as `preference`, `decision`, `incident`, `runbook`, `profile_fact`, `task_memory`, or `tool_trace` MAY be used directly as open strings. A shared formal taxonomy, if needed, belongs in the `schema` profile.

---

## 9. Entities, relations, and reference resolution

OMI-AI core allows records to carry descriptive entities and typed relations. This is not a graph database. It is just enough structure to preserve common links during export/import.

### 9.1 Entities

`entities` is an optional array of descriptive entity objects.

| Field | Type | Card. | Notes |
|---|---|---|---|
| `id` | string | 1 | Opaque entity identifier or reference. |
| `label` | string | 0..1 | Human display label. |
| `type` | string | 0..1 | Open vocabulary: `person`, `organization`, `place`, `concept`, `technology`, `file`, `project`, etc. |

Entity IDs are descriptive identifiers, not mandatory graph nodes. If an entity `id` exactly equals a local record `id`, a consumer MAY link them. OMI-AI core does not require entity resolution, and unresolved entity IDs MUST NOT be treated as validation errors by floor-only processors.

### 9.2 Relations

`relations` is an optional array of typed links.

| Field | Type | Card. | Notes |
|---|---|---|---|
| `type` | string | 1 | Open vocabulary. |
| `target` | string | 1 | Local record id, absolute URI/URN, or opaque external identifier. |
| `label` | string | 0..1 | Human-readable description of the link. |

Recommended relation types:

| Type | Meaning |
|---|---|
| `relates_to` | General related-memory link. |
| `derived_from` | This record was derived from another record/source. |
| `supersedes` | Author considers this record to replace another. No governance semantics in core. |
| `contradicts` | Author considers this record to conflict with another. |
| `part_of` | This record is part of a larger record/topic/process. |
| `references` | This record cites or references another record/resource. |

Any other relation type is permitted. Consumers MUST NOT reject unknown relation types.

### 9.3 Relation target resolution

Because `relations[].target` can be either a local record id or an external reference, target resolution MUST be explicit:

1. If `target` exactly equals the `id` of a record in the same OMI-AI file, it resolves to that local record.
2. Otherwise, if `target` is an absolute URI or URN, it is an external reference.
3. Otherwise, `target` is an opaque unresolved external identifier.
4. Unresolved external identifiers MUST NOT be treated as validation errors by floor-only processors.

At L1, local relation resolution relies on the L1 unique-ID requirement. At L0, processors MAY attempt local resolution but MUST NOT assume uniqueness.

The envelope `id_namespace` is for merge/import scoping. It does not change the in-file exact-match rule above.

Relation targets are not automatically namespace-qualified. A bare `target` resolves only within the id space of a single file. When files are merged under `(id_namespace, id)` keys (§13.3), a bare `target` such as `"1"` can become ambiguous across the merged set. An importer that merges files SHOULD rewrite or qualify relation targets so they remain unambiguous after merge; OMI-AI core does not define automatic relation rewriting.

### 9.4 Supersession is only a hint in core

A relation of type `supersedes` records that the author or source considers one record to replace another. In OMI-AI core, this does **not** impose immutability, does not define a lifecycle, does not forbid editing, does not define effective view semantics, and does not require consumers to hide superseded records.

Those obligations belong to the `governance` profile or to a higher-layer memory substrate.

---

## 10. Extensions and profiles

OMI-AI’s extensibility is concentrated in one field: `ext`.

### 10.1 The `ext` object

`ext` MAY appear on the envelope and on any record. It is an object keyed by profile name. Each value is opaque to OMI-AI core and defined by that profile’s own specification.

Example:

```json
"ext": {
  "integrity": {
    "record_hash": {
      "alg": "sha256",
      "canonicalization": "jcs-rfc8785",
      "scope": "record",
      "value": "9f2b6c0a..."
    }
  },
  "governance": {
    "state": "canonical",
    "supersedes": null
  },
  "retrieval": {
    "embedding": {
      "model": "text-embedding-3-large",
      "dim": 3072,
      "ref": "vec://mem-001"
    }
  }
}
```

Profile keys SHOULD be either:

1. a reserved profile name from §10.4; or
2. a reverse-DNS string for private use, such as `"com.example.feature"`.

### 10.2 Unknown profiles

A processor MUST NOT fail solely because an unknown `ext` profile is present.

A processor that does not understand a profile MUST treat that profile’s value as opaque data. It MUST NOT interpret it as OMI-AI core semantics.

### 10.3 Extension preservation conformance

The old rule “all processors MUST preserve unknown `ext` on read and write” is too broad. OMI-AI instead defines preservation by processor claim.

| Processor behavior | Requirement |
|---|---|
| Parser/validator | MUST NOT reject solely due to unknown `ext`; not required to preserve because it may not emit output. |
| Reader | MUST expose or safely ignore unknown `ext`; not required to preserve unless it re-exports. |
| Writer | SHOULD place non-core data under `ext`; not required to preserve data it never imported. |
| Lossless round-trip processor | MUST preserve unknown `ext` profiles byte-for-byte or semantically equivalently. |
| Native importer/re-exporter | SHOULD preserve unknown `ext` where practical; MUST declare whether re-export is lossless or lossy. |
| Lossy importer | MAY discard unknown `ext`, but MUST NOT claim lossless OMI-AI round-trip support. |

This makes conformance realistic without giving up the forward-compatibility goal.

### 10.4 Reserved profile names

The following profile names are reserved by this specification but defined in separate documents:

| Profile | Purpose |
|---|---|
| `integrity` | Canonical hashing, whole-record digests, seals, signatures, key binding. |
| `governance` | Lifecycle states, review workflow, supersession semantics, effective view. |
| `schema` | Domain validation, field shapes, relational constraints, taxonomy declarations. |
| `provenance` | Rich provenance graphs, evidence anchors, W3C PROV-style derivation. |
| `sync` | Delta exports, tombstones, operations, cursors, conflict policy. |
| `retrieval` | Embeddings, sparse vectors, vector references, chunk IDs, index hints. |

A tool advertising a profile MUST implement that profile’s specification. A floor-only implementation advertises none.

### 10.5 Unknown top-level fields versus `ext`

Producers SHOULD place non-core data in `ext`. Unknown top-level or record-level fields are tolerated for forward compatibility, but they are not profile-safe. A private or experimental feature SHOULD use `ext["com.example.feature"]` rather than a new top-level field.

---

## 11. Integrity, retrieval, and sync are out of core

This section is normative because it prevents accidental false semantics.

### 11.1 No core `hash`

OMI-AI core defines no `hash`, `content_hash`, `checksum`, `seal`, or `signature` field.

Reason: a content-only digest protects only the `content` string while leaving `type`, `created`, `updated`, `source`, `confidence`, validity, relations, subject, and extensions unprotected. A weak security-like primitive can create more false assurance than no primitive.

If an importer sees a legacy content checksum, it SHOULD preserve it under `ext.integrity`, for example:

```json
"ext": {
  "integrity": {
    "content_hash": {
      "alg": "sha256",
      "scope": "content",
      "value": "9f2b6c0a..."
    }
  }
}
```

A full integrity profile SHOULD define:

- canonical serialization;
- hash scope;
- algorithm identifiers;
- whether hash covers record, envelope, file, or selected fields;
- signature algorithms;
- key binding;
- verification failure semantics.

Profiles that hash or sign JSON SHOULD use RFC 8785 JSON Canonicalization Scheme unless the profile specifies another canonicalization.

### 11.2 No core embedding

OMI-AI core defines no `embedding` field.

Reason: embeddings are not portable memory substance. A vector generated by one embedding model may be meaningless, lower quality, or actively misleading in another model’s vector space. Inline high-dimensional vectors also bloat a portability file and harm streaming/inspection.

Embedding data, vector references, sparse retrieval signals, BM25 metadata, chunk IDs, and index names SHOULD be stored under `ext.retrieval`.

Example:

```json
"ext": {
  "retrieval": {
    "embedding": {
      "model": "text-embedding-3-large",
      "dim": 3072,
      "ref": "vec://mem-001"
    }
  }
}
```

Producers SHOULD prefer references over inline vectors for large exports unless the goal is same-model backup/restore.

### 11.3 No core tombstone

OMI-AI core defines no `deleted`, `deleted_at`, `tombstone`, or mutation operation.

Reason: a tombstone is not a memory record; it is a sync operation about a memory record. OMI-AI core is snapshot-first. In a snapshot export, absence of a record MUST NOT be interpreted as a deletion instruction.

Deletion, redaction history, delta import, and mutation operations belong in `ext.sync`.

Example sync-profile sketch:

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "subject": { "id": "user-123" },
  "ext": {
    "sync": {
      "mode": "delta",
      "operations": [
        {
          "op": "delete",
          "id": "urn:omi:example:user-123:mem-014",
          "deleted_at": "2026-06-06T09:00:00Z"
        }
      ]
    }
  },
  "memories": []
}
```

A floor-only consumer MUST NOT apply deletions from an OMI-AI file unless it explicitly supports the `sync` profile and the file declares sync semantics.

---

## 12. Temporal and language model

### 12.1 Created and updated

`created` is when the memory was first recorded by the source system or exporter. It is required.

`updated` is when the source record was last materially changed before export. It is optional because many systems cannot distinguish record creation from later edits.

Both fields MUST be RFC 3339 date-times when present.

### 12.2 Validity

`valid_from` and `valid_to` express real-world validity where known.

Examples:

```json
"valid_from": "2024-01-01",
"valid_to": null
```

```json
"valid_from": "2026-06-06T09:00:00Z",
"valid_to": "2026-06-06T11:30:00Z"
```

A record without `valid_from` or `valid_to` makes no claim about real-world validity. OMI-AI core does not define a bi-temporal transaction-time model; richer temporal semantics belong in profiles or higher layers.

### 12.3 Language

`lang` is an optional BCP 47 language tag for `content`.

Examples:

```json
"lang": "en"
```

```json
"lang": "en-GB"
```

```json
"lang": "ar"
```

If `content` mixes multiple languages, the producer MAY omit `lang` or use the dominant language. Structured multilingual content belongs in a profile.

---

## 13. Snapshot and merge semantics

OMI-AI core defines snapshot merge guidance, not a synchronization protocol.

### 13.1 Snapshot default

An OMI-AI file is a snapshot unless a supported profile explicitly says otherwise.

In a snapshot:

- absence of a record MUST NOT be interpreted as deletion;
- record order has no semantic priority;
- `generated_at` is the export time, not a memory truth time;
- `updated` is a source-system hint, not a universal conflict-resolution timestamp.

### 13.2 Record order

The `memories` array order in `.omi.json` and the record-line order in `.omi.jsonl` are not semantically significant.

Producers SHOULD preserve source order where useful for readability. Consumers MUST NOT infer confidence, priority, recency, or truth from order.

### 13.3 Duplicate and conflict rules

For floor-only merge tools:

1. Records are keyed by effective merge key.
2. If two records have the same effective merge key and are byte-identical after RFC 8785 (JCS) canonicalization, they are duplicates.
3. If two records have the same effective merge key but differ in any field, this is a merge conflict.
4. Floor-only merge tools MUST NOT silently choose one conflicting record.
5. If two records have different IDs but equivalent-looking `content`, deduplication is heuristic and out of scope.
6. Last-write-wins is not a core rule. It may be defined by the `sync` profile or by a host application.

The effective merge key SHOULD be:

- the record `id`, if it is globally scoped by construction, such as a URN, absolute URI, UUID, or ULID;
- otherwise the tuple `(id_namespace, id)`, if envelope `id_namespace` is present;
- otherwise the tuple `(file-scope, id)`, where file-scope is determined by the importing tool.

Inspecting the *form* of an `id` (for example, recognizing a UUID, ULID, URN, or URI) solely to choose a merge key is permitted and is not the semantic interpretation of `id` structure forbidden by §6.3. A merge tool MUST NOT derive record meaning from `id` form; it MAY use `id` form only to select a merge key.

### 13.4 Merge conflicts

A merge conflict is not an invalid OMI-AI record. It is a condition encountered by a merge tool. A merge tool SHOULD preserve both conflicting records or surface the conflict for human/application resolution rather than discarding one.

---

## 14. Mapping from existing exports

OMI-AI is meant to be reachable by a thin adapter from the memory exports tools already produce. Field names vary by tool; match by concept, not exact key.

| OMI-AI field | Common equivalents in existing exports |
|---|---|
| envelope `format` / `version` | `schema` / `schema_version`, document `@context`, top-level version tag |
| envelope `subject.id` | `owner.id`, `user_id`, `account_id`, workspace/user identifier |
| envelope `subject.label` | owner/user/workspace display name |
| envelope `id_namespace` | source namespace, account namespace, provider namespace, export namespace |
| `memories[]` | `memories`, `items`, `records`, one memory per file |
| record `id` | `id`, UUID, ULID, URN, URI, provider-local id |
| record `subject` | per-row user/contact/channel/project/account |
| `content` | `content`, `text`, `body`, `memory`, note text |
| `type` | `type`, `memoryType`, `kind`, category |
| `created` | `created`, `created_at`, `timestamp`, first_seen |
| `updated` | `modified`, `updated_at`, last_seen, last_modified |
| `confidence` | `confidence`, `score`, `weight`, probability |
| `lang` | `lang`, `language`, locale hint |
| `tags` | `tags`, `labels`, categories |
| `source.platform` | `platform`, `provider`, `source`, provenance provider |
| `source.ref` | session id, message id, trace id, document id, URI |
| `source.method` | asserted/extracted/imported/observed/derived equivalent |
| `valid_from` / `valid_to` | validity interval, effective date, start/end date |
| `entities[]` | entities, mentions, named entities |
| `relations[]` | relations, relationships, links, edges |
| `ext.integrity` | content hash, checksum, signature, seal |
| `ext.retrieval` | embeddings block, vector reference, chunk metadata, index hints |
| `ext.governance` | lifecycle state, acceptance status, supersession state |
| `ext.provenance` | derivation graph, source spans, evidence anchors |
| `ext.*` | extensions, metadata, provider-specific blobs |

When an export carries information OMI-AI core has no field for, an adapter SHOULD place it under the appropriate `ext` profile rather than discard it.

Examples:

- A legacy `content_hash` maps to `ext.integrity.content_hash`, not to a core field.
- An embedding vector maps to `ext.retrieval.embedding`, not to a core field.
- A lifecycle status maps to `ext.governance.state`, not to a core field.
- A deletion tombstone maps to `ext.sync.operations[]`, not to a core record field.

---

## 15. Validation model

### 15.1 Schema validation versus conformance validation

JSON Schema validates structural shape. Some OMI-AI conformance rules require additional checks.

| Rule | JSON Schema can enforce? | Notes |
|---|---:|---|
| Required envelope fields | Yes | `format`, `version`, `memories` for `.omi.json`. |
| Required record fields | Yes | L0: `id`, `content`, `created`; L1 also `type`. |
| Date-time field format | Partly | Validators MUST enable `format` assertion. |
| Validity date/date-time shape | Yes, with schema and format assertion | See Appendix B. |
| Effective subject | Mostly | L1 schema enforces envelope subject or record-level subjects for JSON form. |
| Unique record IDs by `id` property | No, not portably in JSON Schema 2020-12 | L1 validators MUST implement this check outside pure JSON Schema. |
| Reference resolution | No | Implemented by OMI-AI validator. |
| Merge conflict detection | No | Implemented by merge tools. |
| Profile validation | No | Each profile validates its own `ext.<profile>` block. |

If prose and schema conflict, that is a specification defect. The prose defines semantics; the versioned JSON Schema defines structural validation. A public release MUST NOT knowingly publish conflicts between them.

### 15.2 L0 validation checklist

A file is L0 valid if:

1. it is valid `.omi.json` or `.omi.jsonl` per §4;
2. its envelope `format` is `"open-memory-interchange"`;
3. its envelope `version` has a supported major version;
4. every record has non-empty `id`;
5. every record has `content`;
6. every record has `created`;
7. timestamp fields are valid RFC 3339 date-times;
8. validity boundary fields, if present, are date or date-time values, with `valid_to` also allowing `null`;
9. unknown fields and unknown `ext` profiles do not cause rejection.

### 15.3 L1 validation checklist

A file is L1 valid if it is L0 valid and:

1. every record has `type`;
2. every record ID is unique within the file;
3. every record has an effective subject;
4. every record-level or envelope-level subject has an `id`;
5. `confidence`, if present, is in `[0.0, 1.0]`;
6. `lang`, if present, is a BCP 47 language tag;
7. every `relations[]` item has `type` and `target`;
8. local relation target resolution is unambiguous because IDs are unique.

For rules that JSON Schema cannot express (notably ID uniqueness and effective subject — the latter surfacing in the L1 schema only as an opaque `anyOf` failure), a validator SHOULD emit a human-readable diagnostic naming the specific failing rule rather than a raw schema-combinator error.

### 15.4 JSONL validation

For `.omi.jsonl`, validators SHOULD validate:

- line 1 as a JSONL envelope;
- all subsequent lines as records;
- the collected file as if the lines had been converted to ordinary JSON with the records placed into `memories`.

The schemas in Appendix B are for ordinary `.omi.json` envelope files. A JSONL validator can reuse the record definition from those schemas.

---

## 16. Security and privacy considerations

### 16.1 OMI-AI files are data

An OMI-AI file is data, never instructions. `content`, `tags`, `source.ref`, entity labels, relation labels, and extension fields may contain adversarial text. Consuming LLM pipelines MUST treat record text as data, not as commands.

### 16.2 Personal data

Memory routinely contains personal data. Tools SHOULD support inspection, redaction, and selective export before sharing an OMI-AI file.

OMI-AI core defines no encryption. Encrypt at rest and in transit out of band.

### 16.3 No authenticity without an integrity profile

An OMI-AI core file has no built-in authenticity or tamper-evidence. A consumer MUST NOT treat the absence of an integrity profile as proof of safety, authorship, completeness, or non-tampering.

The `integrity` profile may define hashes, signatures, and verification procedures. Until such a profile is declared and verified, an OMI-AI file is unsigned data.

### 16.4 External references

External references in `source.ref`, `relations[].target`, entity IDs, and extension profiles MUST NOT be dereferenced automatically. Network fetches, file reads, and tool calls are outside OMI-AI core and require host policy.

### 16.5 Redaction and deletion

If a producer omits records for privacy, policy, or user deletion reasons, it MAY include file-level `ext` metadata describing the export policy. OMI-AI core does not define tombstones or deletion history. A consumer MUST NOT infer deletion from absence unless it supports the `sync` profile and the file declares appropriate sync semantics.

### 16.6 Embeddings and privacy

Embeddings can leak information about the underlying text and can be model/provider-specific. Because embeddings are outside core, any retrieval profile carrying vectors SHOULD document privacy, model identity, normalization, and portability limits.

---

## 17. Versioning

- `version` is `major.minor`.
- Minor versions are additive and backward-compatible.
- Major versions MAY break compatibility and MUST be rejected by consumers that do not support them.
- New optional fields may be added in minor versions.
- New recommended vocabulary values may be added in minor versions.
- New behavior SHOULD be introduced through profiles rather than by growing the core.
- Core field additions SHOULD be rare.
- The floor is intended to stay small.

A consumer that sees an unknown minor-version field MUST ignore it unless it claims a stricter validation mode. A lossless round-trip processor MUST preserve it.

---

## 18. Media types and file conventions

| Form | Extension | Media type |
|---|---|---|
| Ordinary JSON envelope | `.omi.json` | `application/vnd.omi+json` |
| JSON Lines streaming form | `.omi.jsonl` | `application/vnd.omi+jsonl` |
| L0 schema | `omi-l0.schema.json` | `application/schema+json` |
| L1 schema | `omi-l1.schema.json` | `application/schema+json` |

A public repository SHOULD use a package layout similar to:

```text
/spec/open-memory-interchange-0.1.md
/schema/omi-l0.schema.json
/schema/omi-l1.schema.json
/examples/minimal.omi.json
/examples/interchange.omi.json
/examples/multisubject.omi.json
/examples/streaming.omi.jsonl
/tests/valid/*.json
/tests/invalid/*.json
/profiles/README.md
/LICENSE
/README.md
```

---

## 19. Conformance fixture suite

A public draft SHOULD ship test fixtures. The following fixture names and purposes are recommended.

### 19.1 Valid fixtures

| Fixture | Purpose |
|---|---|
| `valid/l0-minimal.omi.json` | Smallest valid L0 file. |
| `valid/l1-basic.omi.json` | Basic L1 file with envelope subject and typed records. |
| `valid/record-level-subject.omi.json` | Multi-subject file with subject on each record. |
| `valid/jsonl-basic.omi.jsonl` | Streaming JSONL export. |
| `valid/unknown-ext-preserved.omi.json` | Unknown extension profile present. |
| `valid/unknown-top-level-fields.omi.json` | Unknown top-level field tolerated. |
| `valid/multilingual.omi.json` | Records with `lang` values. |
| `valid/relation-local-and-external.omi.json` | Relation targets resolving local and external references. |
| `valid/namespaced-local-ids.omi.json` | Sequential source IDs scoped by `id_namespace`. |
| `valid/retrieval-profile-placeholder.omi.json` | Embedding data under `ext.retrieval`, not core. |
| `valid/integrity-profile-placeholder.omi.json` | Hash data under `ext.integrity`, not core. |

### 19.2 Invalid fixtures

| Fixture | Purpose |
|---|---|
| `invalid/missing-content.omi.json` | Record missing L0 `content`. |
| `invalid/missing-created.omi.json` | Record missing L0 `created`. |
| `invalid/bad-created-date-only.omi.json` | `created` is a date instead of date-time. |
| `invalid/bad-valid-from-natural-language.omi.json` | `valid_from` is `"next Tuesday"`. |
| `invalid/duplicate-id-l1.omi.json` | Duplicate record IDs under L1 validation. |
| `invalid/l1-missing-type.omi.json` | L1 record missing `type`. |
| `invalid/l1-no-effective-subject.omi.json` | L1 record without record or envelope subject. |
| `invalid/confidence-out-of-range.omi.json` | `confidence` outside `[0.0, 1.0]`. |
| `invalid/jsonl-envelope-has-memories.omi.jsonl` | JSONL first line incorrectly contains `memories`. |
| `invalid/jsonl-missing-serialization.omi.jsonl` | JSONL envelope missing `serialization: "jsonl"`. |

---

## Appendix A — Examples

### A.1 Minimal L0

The smallest useful OMI-AI file.

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "memories": [
    {
      "id": "mem-001",
      "content": "User is a cloud infrastructure engineer.",
      "created": "2025-01-15T00:00:00Z"
    }
  ]
}
```

### A.2 Basic L1

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "serialization": "json",
  "subject": {
    "id": "user-123",
    "type": "person",
    "label": "Freddy"
  },
  "generated_at": "2026-06-06T09:00:00Z",
  "generator": "example-tool/1.4",
  "memories": [
    {
      "id": "01JZ0WFR4K2Q6N7S8T9V0ABCDF",
      "content": "Freddy prefers direct critical pushback.",
      "type": "semantic",
      "created": "2026-05-01T09:02:11Z",
      "confidence": 0.96,
      "lang": "en",
      "tags": ["communication", "preference"],
      "source": {
        "platform": "example-chat",
        "ref": "session-882",
        "method": "extracted"
      },
      "valid_from": "2026-05-01",
      "valid_to": null
    }
  ]
}
```

### A.3 Multi-subject L1

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "generated_at": "2026-06-06T09:00:00Z",
  "generator": "group-agent/0.9",
  "memories": [
    {
      "id": "01JZ0WFR4K2Q6N7S8T9V0AAAAA",
      "subject": { "id": "user-123", "type": "person", "label": "Freddy" },
      "content": "Freddy prefers direct technical criticism.",
      "type": "semantic",
      "created": "2026-06-06T09:00:00Z"
    },
    {
      "id": "01JZ0WFR4K2Q6N7S8T9V0BBBBB",
      "subject": { "id": "user-456", "type": "person", "label": "Ava" },
      "content": "Ava prefers morning calls.",
      "type": "semantic",
      "created": "2026-06-06T09:01:00Z"
    }
  ]
}
```

### A.4 Relation resolution

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "subject": { "id": "user-123", "type": "person" },
  "memories": [
    {
      "id": "mem-001",
      "content": "User prefers short meeting notes.",
      "type": "semantic",
      "created": "2026-01-01T00:00:00Z",
      "relations": [
        {
          "type": "relates_to",
          "target": "mem-002",
          "label": "same communication preference cluster"
        },
        {
          "type": "references",
          "target": "https://example.com/source-doc",
          "label": "source document"
        }
      ]
    },
    {
      "id": "mem-002",
      "content": "User dislikes long status meetings.",
      "type": "semantic",
      "created": "2026-01-01T00:10:00Z"
    }
  ]
}
```

In this example, `mem-002` resolves locally because it exactly matches a record `id`. The HTTPS URL is external. Any nonmatching non-URI target would be opaque unresolved external data.

### A.5 Extension preservation

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "subject": { "id": "user-123" },
  "memories": [
    {
      "id": "01JZ0WFR4K2Q6N7S8T9V0ABCDF",
      "content": "User prefers concise summaries.",
      "type": "semantic",
      "created": "2026-01-15T10:30:00Z",
      "ext": {
        "com.example.private": {
          "native_record_id": "abc-123",
          "internal_score": 0.817
        }
      }
    }
  ]
}
```

A lossless OMI-AI round-trip processor must preserve the unknown `com.example.private` block.

### A.6 Integrity profile placeholder

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "subject": { "id": "user-123" },
  "memories": [
    {
      "id": "01JZ0WFR4K2Q6N7S8T9V0ABCDF",
      "content": "User prefers concise summaries.",
      "type": "semantic",
      "created": "2026-01-15T10:30:00Z",
      "ext": {
        "integrity": {
          "record_hash": {
            "alg": "sha256",
            "canonicalization": "jcs-rfc8785",
            "scope": "record",
            "value": "9f2b6c0a..."
          }
        }
      }
    }
  ]
}
```

### A.7 Retrieval profile placeholder

```json
{
  "format": "open-memory-interchange",
  "version": "0.1",
  "subject": { "id": "user-123" },
  "memories": [
    {
      "id": "01JZ0WFR4K2Q6N7S8T9V0ABCDF",
      "content": "User prefers concise summaries.",
      "type": "semantic",
      "created": "2026-01-15T10:30:00Z",
      "ext": {
        "retrieval": {
          "embedding": {
            "model": "text-embedding-3-large",
            "dim": 3072,
            "ref": "vec://01JZ0WFR4K2Q6N7S8T9V0ABCDF"
          }
        }
      }
    }
  ]
}
```

### A.8 JSONL export

```jsonl
{"format":"open-memory-interchange","version":"0.1","serialization":"jsonl","subject":{"id":"user-123","type":"person","label":"Freddy"},"generated_at":"2026-06-06T09:00:00Z","generator":"example-tool/1.4"}
{"id":"01JZ0WFR4K2Q6N7S8T9V0ABCDF","content":"User prefers direct, critical pushback over agreement.","type":"semantic","created":"2026-01-15T10:30:00Z"}
{"id":"01JZ0WG9N2RC94Z6K9TDTA3Q8M","content":"User lives in Dubai.","type":"semantic","created":"2026-05-01T09:02:11Z"}
```

---

## Appendix B — JSON Schemas

The `$id` URLs below are placeholders for this draft and SHOULD be replaced with final governance-domain URLs before stable release.

JSON Schema `format` is annotation-only unless a validator enables format assertion. An OMI-AI validator claiming L0 or L1 timestamp validation MUST enable format assertion or perform equivalent timestamp validation outside JSON Schema.

JSON Schema 2020-12 cannot portably enforce “record IDs are unique by the `id` property across `memories[]`.” An L1 validator MUST perform that check outside pure JSON Schema.

### B.1 L0 schema: `omi-l0.schema.json`

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://open-memory-interchange.example/schema/0.1/omi-l0.schema.json",
  "title": "Open Memory Interchange 0.1 L0 Core",
  "type": "object",
  "required": [
    "format",
    "version",
    "memories"
  ],
  "properties": {
    "format": {
      "const": "open-memory-interchange"
    },
    "version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+$"
    },
    "serialization": {
      "enum": [
        "json"
      ]
    },
    "subject": {
      "$ref": "#/$defs/subject"
    },
    "id_namespace": {
      "type": "string",
      "minLength": 1
    },
    "generated_at": {
      "$ref": "#/$defs/dateTime"
    },
    "generator": {
      "type": "string"
    },
    "memories": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/record"
      }
    },
    "ext": {
      "type": "object"
    }
  },
  "$defs": {
    "date": {
      "type": "string",
      "format": "date",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "dateTime": {
      "type": "string",
      "format": "date-time",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$"
    },
    "dateOrDateTime": {
      "anyOf": [
        {
          "$ref": "#/$defs/date"
        },
        {
          "$ref": "#/$defs/dateTime"
        }
      ]
    },
    "dateOrDateTimeOrNull": {
      "anyOf": [
        {
          "$ref": "#/$defs/date"
        },
        {
          "$ref": "#/$defs/dateTime"
        },
        {
          "type": "null"
        }
      ]
    },
    "subject": {
      "type": "object",
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1
        },
        "type": {
          "type": "string",
          "minLength": 1
        },
        "label": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "source": {
      "type": "object",
      "properties": {
        "platform": {
          "type": "string"
        },
        "ref": {
          "type": "string"
        },
        "method": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "entity": {
      "type": "object",
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1
        },
        "label": {
          "type": "string"
        },
        "type": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "relation": {
      "type": "object",
      "required": [
        "type",
        "target"
      ],
      "properties": {
        "type": {
          "type": "string",
          "minLength": 1
        },
        "target": {
          "type": "string",
          "minLength": 1
        },
        "label": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "record": {
      "type": "object",
      "required": [
        "id",
        "content",
        "created"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1
        },
        "subject": {
          "$ref": "#/$defs/subject"
        },
        "content": {
          "type": "string"
        },
        "type": {
          "type": "string"
        },
        "created": {
          "$ref": "#/$defs/dateTime"
        },
        "updated": {
          "$ref": "#/$defs/dateTime"
        },
        "confidence": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "lang": {
          "type": "string",
          "pattern": "^[A-Za-z]{2,8}(-[A-Za-z0-9]{1,8})*$"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "source": {
          "$ref": "#/$defs/source"
        },
        "valid_from": {
          "$ref": "#/$defs/dateOrDateTime"
        },
        "valid_to": {
          "$ref": "#/$defs/dateOrDateTimeOrNull"
        },
        "entities": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/entity"
          }
        },
        "relations": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/relation"
          }
        },
        "ext": {
          "type": "object"
        }
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": true
}
```

### B.2 L1 schema: `omi-l1.schema.json`

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://open-memory-interchange.example/schema/0.1/omi-l1.schema.json",
  "title": "Open Memory Interchange 0.1 L1 Interchange",
  "type": "object",
  "required": [
    "format",
    "version",
    "memories"
  ],
  "properties": {
    "format": {
      "const": "open-memory-interchange"
    },
    "version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+$"
    },
    "serialization": {
      "enum": [
        "json"
      ]
    },
    "subject": {
      "$ref": "#/$defs/subject"
    },
    "id_namespace": {
      "type": "string",
      "minLength": 1
    },
    "generated_at": {
      "$ref": "#/$defs/dateTime"
    },
    "generator": {
      "type": "string"
    },
    "memories": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/record"
      }
    },
    "ext": {
      "type": "object"
    }
  },
  "anyOf": [
    {
      "required": [
        "subject"
      ]
    },
    {
      "properties": {
        "memories": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/recordWithSubject"
          }
        }
      }
    }
  ],
  "$defs": {
    "date": {
      "type": "string",
      "format": "date",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "dateTime": {
      "type": "string",
      "format": "date-time",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$"
    },
    "dateOrDateTime": {
      "anyOf": [
        {
          "$ref": "#/$defs/date"
        },
        {
          "$ref": "#/$defs/dateTime"
        }
      ]
    },
    "dateOrDateTimeOrNull": {
      "anyOf": [
        {
          "$ref": "#/$defs/date"
        },
        {
          "$ref": "#/$defs/dateTime"
        },
        {
          "type": "null"
        }
      ]
    },
    "subject": {
      "type": "object",
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1
        },
        "type": {
          "type": "string",
          "minLength": 1
        },
        "label": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "source": {
      "type": "object",
      "properties": {
        "platform": {
          "type": "string"
        },
        "ref": {
          "type": "string"
        },
        "method": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "entity": {
      "type": "object",
      "required": [
        "id"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1
        },
        "label": {
          "type": "string"
        },
        "type": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "relation": {
      "type": "object",
      "required": [
        "type",
        "target"
      ],
      "properties": {
        "type": {
          "type": "string",
          "minLength": 1
        },
        "target": {
          "type": "string",
          "minLength": 1
        },
        "label": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "record": {
      "type": "object",
      "required": [
        "id",
        "content",
        "created",
        "type"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1
        },
        "subject": {
          "$ref": "#/$defs/subject"
        },
        "content": {
          "type": "string"
        },
        "type": {
          "type": "string"
        },
        "created": {
          "$ref": "#/$defs/dateTime"
        },
        "updated": {
          "$ref": "#/$defs/dateTime"
        },
        "confidence": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "lang": {
          "type": "string",
          "pattern": "^[A-Za-z]{2,8}(-[A-Za-z0-9]{1,8})*$"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "source": {
          "$ref": "#/$defs/source"
        },
        "valid_from": {
          "$ref": "#/$defs/dateOrDateTime"
        },
        "valid_to": {
          "$ref": "#/$defs/dateOrDateTimeOrNull"
        },
        "entities": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/entity"
          }
        },
        "relations": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/relation"
          }
        },
        "ext": {
          "type": "object"
        }
      },
      "additionalProperties": true
    },
    "recordWithSubject": {
      "allOf": [
        { "$ref": "#/$defs/record" },
        { "required": ["subject"] }
      ]
    }
  },
  "additionalProperties": true
}
```

---

## Appendix C — JSONL parsing algorithm

A JSONL consumer SHOULD process `.omi.jsonl` as follows:

1. Read the file as UTF-8.
2. Reject a byte-order mark.
3. Read the first line.
4. Parse the first line as JSON object.
5. Validate that `format` is `"open-memory-interchange"`.
6. Validate that `version` has a supported major version.
7. Validate that `serialization` is `"jsonl"`.
8. Validate that the first-line envelope does not contain `memories`.
9. For each subsequent line:
   1. reject blank lines;
   2. parse the line as JSON object;
   3. validate as a record;
   4. yield or store the record.
10. Apply L1 cross-record checks if L1 validation is requested, including ID uniqueness and effective subject.
11. Preserve file-level `ext` from the first-line envelope.

A JSONL producer SHOULD emit compact one-line JSON objects, but consumers MUST NOT depend on key order.

---

## Appendix D — Profile registry policy

The profile registry should be conservative. A profile name should be reserved only if it is likely to be used by multiple independent implementations.

### D.1 Reserved public names

Reserved names are listed in §10.4. A public profile specification SHOULD define:

1. profile name;
2. versioning rule;
3. envelope-level and record-level shapes;
4. preservation requirements;
5. validation rules;
6. interaction with OMI-AI core;
7. examples;
8. security/privacy considerations.

### D.2 Private profile names

Private profiles SHOULD use reverse-DNS names.

Examples:

```json
"ext": {
  "com.example.agent_runtime": {
    "native_id": "abc-123"
  }
}
```

A public implementation MUST NOT squat on another organization’s reverse-DNS namespace.

---

## Appendix E — Public draft release checklist

Before publishing a public draft, check:

1. The name and acronym are still acceptable.
2. The repository and domain do not imply single-vendor ownership.
3. The license is explicit.
4. The schemas validate the examples.
5. L0 and L1 schemas are separate.
6. JSONL behavior is documented.
7. No core `hash` field exists.
8. No core `embedding` field exists.
9. Record-level `subject` is supported.
10. ID collision guidance is explicit.
11. Reference resolution is explicit.
12. Merge behavior is explicit and does not define silent last-write-wins.
13. Tombstones/deletions are out of core and reserved for `sync`.
14. Extension preservation rules are conformance-specific and realistic.
15. `valid_from` / `valid_to` reject arbitrary natural-language date strings.
16. Unknown fields outside `ext` are tolerated but not blessed as core semantics.
17. Security and privacy sections warn that OMI-AI files are data, not instructions.
18. Test fixtures exist.
19. At least one reference validator exists.

---

*End of Open Memory Interchange formal specification (OMI-AI/0.1-draft).*
