Limited Edition Jonathan / agent memory
Series ▾
Architecture note · 2026

One memory, every agent.

Every AI harness keeps its own private memory. Claude Code remembers in one place, Codex in ~/.codex/memories, Gemini and Grok barely remember anything portable at all. Switch tools and your context evaporates.

Run three agents on one project and they each learn the same lessons separately — and occasionally contradict each other. Codex quietly shipped a clean little engine that solves the hard half of this. This note takes the pattern apart, then proposes lifting it out of any single vendor and hosting it in Supabase — so every agent you run shares one portable brain.

The unlock isn't a smarter model. It's a memory layer that doesn't belong to the model. Make memory portable and provenance-tracked, and the agent becomes swappable without the loss.

Today
Four walled memories. The same lesson learned four times.
→
With a shared layer
One brain. Every agent reads and writes the same memory.
01 / 07 — the problem

Memory is trapped inside the harness.

"Agent memory" today means whatever a single tool decided to persist for itself, in its own format, on its own disk. That produces four recurring failures.

Failure 01

Silos

Codex's lessons live in Codex; Claude's live in Claude. Neither reads the other, so the same fact gets re-learned in every harness.

Failure 02

Lock-in

Your working context becomes a hostage. Trying Grok for a week means starting cold — which quietly keeps you on whatever tool holds the most memory.

Failure 03

Drift & contradiction

Several agents writing freely into one doc rots it into duplicated, stale, conflicting "facts." We watched a guessed claim — "this person is in Russia," from one timezone field — land as verified truth.

Failure 04

No reliability spine

Extract, consolidate, re-embed, expire — all run as ad-hoc scripts with no leases, no retries, no record of what's processed. Crashes lose work in silence.

02 / 07 — the artifact

What Codex quietly got right.

Codex's memory engine is small — two tables — but the shape is the whole lesson. It treats memory not as a chat log but as a processing pipeline with a ledger. One table holds a structured extraction per session, gated by a selected_for_phase2 promotion flag; the other is a durable, leased, retryable job ledger. When I opened the export, that ledger was openly tracking five failed extraction jobs queued for retry — not lost, not hidden.

Codex pipeline
  raw session logs
       │
       ▼   per-session stage-1 extraction  (a job)
  stage1_outputs ── selected_for_phase2? ──▶ global consolidation (a job)
       │                                          │
       ▼                                          ▼
  reusable per-run memory               versioned MEMORY.md  (the "owned" memory)

Want the full teardown — the raw_memory anatomy, the exact columns, the lease mechanics? Read the Codex memory deep dive →

03 / 07 — the principle

Agents propose. A consolidation layer owns.

This is the single idea worth stealing. Agents may propose memory — raw runs and extracted candidates. They may not write directly into durable shared memory. A separate consolidation step owns promotion: it decides what becomes a durable fact, attaches provenance and scope, and supersedes anything it contradicts. That boundary is the exact fix for the guessed-claim failure — a proposal carrying weak evidence simply never gets promoted.

The strong boundary
  Claude   Codex   Gemini   Grok           ← agents PROPOSE
     └───────┴───┬───┴────────┘
                 ▼
         staging (proposals)
                 ▼
       consolidation worker                    ← the OWNER
                 ▼
   durable memory + provenance + scope + supersedes
04 / 07 — the vision

Lift it out of the vendor. Host it in Supabase.

Codex's pattern is right, but it's still Codex's — bound to one harness on one disk. The move is to rebuild it as a vendor-neutral service: Postgres on Supabase (pgvector for recall, row-level security for scoping, realtime for live sync), fronted by a thin MCP server so any agent that speaks MCP reads and writes the same memory.

Portable architecture
  ┌────────┐ ┌───────┐ ┌────────┐ ┌──────┐ ┌──────────┐
  │ Claude │ │ Codex │ │ Gemini │ │ Grok │ │ n8n /    │   any harness
  │  Code  │ │       │ │        │ │      │ │ custom   │
  └───┬────┘ └───┬───┘ └───┬────┘ └──┬───┘ └────┬─────┘
      └──────────┴────┬────┴─────────┴──────────┘
                      ▼
          MCP server  +  REST / SDK fallback        one interface
   memory.search · memory.propose · memory.get · memory.promote
                      ▼
  ┌─────────────────────────────────────────────────────┐
  │ SUPABASE · Postgres                                 │
  │   agent_runs → staging → memory_items → jobs        │
  │   + claims (provenance)   + embeddings (pgvector)   │
  │            ▲                                         │
  │    consolidation worker  (owns promotion)           │
  └─────────────────────────────────────────────────────┘

MCP is what makes it portable — a common tongue across Claude, Codex and others, so a single server exposes the same four verbs to every agent. Anything that can't speak MCP gets a REST endpoint or a thirty-line SDK. The memory stops belonging to a model and starts belonging to you.

05 / 07 — the shape

Four layers, one provenance spine.

The store is deliberately boring and legible: raw at the bottom, owned at the top, a ledger driving the workers between them, provenance threaded through. Tab through the layers.

Raw event layer. Append-only source of truth — every run, its source link, its raw events. Dumb and complete, for replay, audit, and re-extraction.

create table agent_runs (
  run_id       text primary key,
  agent_id     text not null,          -- claude | codex | gemini | grok
  workspace    text,
  task         text,
  source_uri   text,                   -- link back to the exact thread/PR
  started_at   timestamptz,
  raw_events   jsonb not null
);

Stage-1 extraction. One structured row per run, generated from raw events. This is what makes messy agent work portable across harnesses.

create table run_summaries (
  run_id        text primary key references agent_runs,
  summary       text not null,
  extracted     text not null,         -- candidate memory
  keywords      text[],
  entities      jsonb,
  decisions     jsonb,
  artifacts     jsonb,
  generated_at  timestamptz not null
);

Promoted, owned memory. Durable facts the consolidation layer decided to keep — each scoped, sourced, and supersedable.

create table memory_items (
  memory_id     text primary key,
  scope         text not null,         -- global|project|client|agent
  topic         text not null,
  content       text not null,
  source_runs   text[] not null,
  source_agent  text,
  confidence    real,
  superseded_by text,                  -- evolve, don't delete
  expires_at    timestamptz
);

Provenance spine — our edge over the Codex snapshot. Every claim carries a status and its evidence, so weak guesses can never harden into facts.

create table claims (
  claim_id    text primary key,
  memory_id   text references memory_items,
  status      text not null,           -- fact|inference|unverified|refuted
  confidence  real,
  source_type text,                    -- person|profile|jon|record
  source_ref  text,
  verified_by text
);

The reliability spine. Lease + watermark + retry for every background worker — extract, consolidate, re-embed, expire. Crashes resume; nothing is lost in silence.

create table jobs (
  kind          text not null,         -- extract | consolidate | embed
  job_key       text not null,
  status        text not null,         -- pending|running|done|error
  worker_id     text,
  lease_until   timestamptz,
  retry_at      timestamptz,
  retry_left    int not null,
  input_watermark      timestamptz,
  last_success_mark    timestamptz,
  primary key (kind, job_key)
);

Recall across everything. A pgvector index over promoted memory — ask in natural language, get the right item regardless of which agent wrote it.

create table embeddings (
  memory_id  text references memory_items,
  embedding  vector(1536),
  model      text
);
create index on embeddings
  using ivfflat (embedding vector_cosine_ops);

The lifecycle columns that earn their keep

  • scope — global · project · repo · client · workflow · agent, so a Grok run on Client A can't pollute the global layer.
  • source_agent & source_uri — every memory knows who proposed it and links back to the exact run.
  • superseded_by / conflicts_with — evolve facts without pretending the old ones never existed.
  • expires_at — operational facts decay on schedule instead of haunting you forever.
06 / 07 — payoff

What one shared brain actually fixes.

Each failure from the top maps to a property of the layer — not a feature of any model.

Portability

Try Grok for a week, fall back to Claude, route a task to Codex — memory follows the work, not the tool.

No silos

A lesson any agent learns is instantly available to all of them. No re-deriving the same runbook three times.

Quality

Propose-then-own plus a claims ledger means weak guesses never harden into facts.

Reliability

Every background task has a lease, a retry and a watermark. Work resumes; nothing is lost in silence.

Recall

One pgvector index over everything every agent has promoted — ask in plain language, get the right memory.

Control

It's your Postgres. Export it, version it, move it. The brain is an asset on your books, not a feature of someone's app.

07 / 07 — where this goes

Two builds, one direction.

This page is the why. The how splits into two concrete tracks — start with the fleet we already run, keep an eye on what OB1 can borrow.

Stop teaching every agent the same thing.

Give them one brain — portable, provenance-tracked, and yours. Codex proved the pattern. Supabase makes it neutral. MCP makes it universal. The agent becomes the cursor; the memory becomes the file.