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.
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.
"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.
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.
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.
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.
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.
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.
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 →
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.
Claude Codex Gemini Grok ← agents PROPOSE └───────┴───┬───┴────────┘ ▼ staging (proposals) ▼ consolidation worker ← the OWNER ▼ durable memory + provenance + scope + supersedes
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.
┌────────┐ ┌───────┐ ┌────────┐ ┌──────┐ ┌──────────┐ │ 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.
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);
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.Each failure from the top maps to a property of the layer — not a feature of any model.
Try Grok for a week, fall back to Claude, route a task to Codex — memory follows the work, not the tool.
A lesson any agent learns is instantly available to all of them. No re-deriving the same runbook three times.
Propose-then-own plus a claims ledger means weak guesses never harden into facts.
Every background task has a lease, a retry and a watermark. Work resumes; nothing is lost in silence.
One pgvector index over everything every agent has promoted — ask in plain language, get the right memory.
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.
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.
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.