Memory interchange format

July 7, 2026 · View on GitHub

robrain export --format interchange writes the project's decision corpus as JSONL: one JSON object per line, one memory per object. The goal is that other agent-memory tools can import RoBrain memories without talking to Perception or its database.

← Back to README

Producing a file

npx robrain export --format interchange                 # JSONL to stdout (status on stderr)
npx robrain export --format interchange --out memories.jsonl

The export includes the full lifecycle — superseded and invalidated memories are present too, marked in lifecycle. Importers that only want live memories should keep lines where lifecycle.invalidated_at is null.

One line, one memory

{"format":"robrain-memory/v1","id":"5f3c…","decision":"Use pnpm for all workspace commands","rationale":"Repo is standardized on pnpm","rejected":[{"option":"npm","reason":"lockfile drift"}],"files_affected":["package.json"],"scope":"team","lifecycle":{"created_at":"2026-05-01T10:00:00.000Z","invalidated_at":null,"reviewed_at":"2026-05-02T09:00:00.000Z","supersedes_id":null},"provenance":{"session_id":"2026-05-01T09:58:11.873Z-8e39","source_turn_sequence":4,"source_excerpt":"please only ever use pnpm here"},"quality":{"historical_relevance":0.62,"injected_count":14,"used_count":11}}

Fields

Every line has every field. Optional values are explicit nulls, never missing keys, so importers can rely on the shape.

Top level

FieldTypeMeaning
formatstringAlways "robrain-memory/v1". Check this first; reject lines with a different value.
idstringStable unique id of the memory (UUID in RoBrain's database). Use it for dedup on re-import.
decisionstringThe decision itself, in plain language. This is the text a tool would inject into an agent's context.
rationalestring | nullWhy the decision was made.
rejectedarrayAlternatives that were considered and turned down. Each entry is {"option": string, "reason": string}. Empty array when none were captured.
files_affectedstring[]Repo-relative file paths the decision applies to. Empty array for project-wide decisions.
scopestringHow widely the decision applies: user, local, team, or global.

lifecycle — is this memory still in effect?

FieldTypeMeaning
created_atstring (ISO 8601)When the memory was captured.
invalidated_atstring | nullWhen it stopped being in effect (superseded or rejected in review). null = still live.
reviewed_atstring | nullWhen a human explicitly approved it. null = captured but never reviewed — treat with less trust.
supersedes_idstring | nullid of the earlier memory this one replaced, so importers can rebuild the decision chain.

provenance — where it came from

FieldTypeMeaning
session_idstringId of the coding session the decision was captured in.
source_turn_sequencenumber | nullTurn number within that session (1-based). null on rows captured before provenance snapshots existed.
source_excerptstring | nullUp to 300 characters of the user message that originated the decision — the human words behind the memory.

quality — how the memory has performed

FieldTypeMeaning
historical_relevancenumber | null0–1 score fed by the feedback loop: rises when injections are used and outcomes are confirmed, falls on ignored injections, reverts, and incidents. null on rows from older servers.
injected_countnumberHow many times the memory was injected into an agent's context.
used_countnumberOf those injections, how many times the reply actually drew on it. A large injected_count with a tiny used_count marks a memory agents consistently ignore.

Versioning

The format field is the contract. Breaking changes to any field will ship as robrain-memory/v2; v1 lines will keep the shape documented here. Additive changes within v1 may introduce new fields — importers should ignore keys they don't recognize.