Keep our memory stack. Do not install agentsmemory.

Version v1.2.18 · Updated 2026-08-16 12:58 EEST · Model Grok 4.6 (grok-4.6) · effort:high · Origin: Grok· agent:grok_intel
One line: their repo is a useful idea list. MPRO already runs the same notebook, and most of their good ideas are already in our JavaScript. Do not install their Go server, their curl | bash kit, or a second memory brain beside :3069.

Plain-language summary. "Agent memory" is the notebook an AI keeps between chats. We compared github.com/atvirokodosprendimai/agentsmemory (AGPL-3.0, still "early skeleton") against the live MPRO stack. Licence read 2026-08-16: GNU AGPL-3.0 — copying their Go into our network service would force source disclosure. Ideas may be reimplemented in JS. Re-measured this turn: closet boost, content-hash, as-of knowledge-graph query, and a nightly sleep-consolidation dry-run already exist on our side. The only remaining useful idea is their hallway/tunnel association graph.

🔴 What requires action

No CEO decision. Sleep-consolidation mutate stays dry-run on purpose (the unit already says so). Do not run their installer.

One remaining idea worth copying (agent-owned, not CEO): hallway + tunnel association graph — entity co-occurrence inside a project, plus cross-project links, plus a traverse tool. MPRO still has no hallway/tunnel symbols in tools/agent-memory*.js (grep 2026-08-16). Independent JS on Postgres, never their AGPL Go. Owner: existing node task:harness.eval-agentsmemory-mcp (do not fork a sibling).

Sleep pass is no longer missing: tools/agent-memory-consolidate.js exists, timer last ran 2026-08-16 04:43 EEST, dry-run mutated=false gists=25 crossAgent=10 contradictions=270 downscale=5 promote=5. Keep apply off.

🔴 The decision (top priority)

Recommendation: (A) KEEP + FIX ours, and adopt their best IDEAS in pure JavaScript on the infrastructure we already run.
Not a swap, not their server. We fix our own break (done this session), and we copy the smart parts of their ranking maths onto our existing Postgres + pgvector + Ollama stack - zero new services.

Why, in one honest paragraph. As a central notebook that many AI agents read and write at the same time, MPRO's engine sits on Postgres - a database built for many writers at once (called MVCC: everyone can write together without stepping on each other) - plus a fast approximate vector search (HNSW) and a live change-broadcast bus (pg_notify). agentsmemory's durable store is a single SQLite file with no "wait-your-turn" setting configured, and its own code comments admit its locks do not coordinate across copies - so the exact thing it is designed for (many agents, many server copies) meets a single-file write bottleneck. So the foundation is ours to keep. Ours was "broken" only by a few hours of configuration drift (see the Live hard-proof tab); theirs is an unproven early skeleton whose concurrency limit is baked into the architecture. [multiagent lens; head-to-head lens]

🏆 Where THEIRS was better — 2026-08-16 remapped

  • Normalized hybrid ranking. Adopted in 23cdd44ba. ours now
  • Closet topic-boost. Live in tools/agent-memory-quality.js + wired at agent-memory-mcp-server.js (~2265). ours now
  • Content-hash dedup. content_sha on write + mine idempotency. ours now
  • As-of knowledge graph. kgQuery(..., asOf) in agent-memory-capabilities.js. Populate-from-mine is still thin (task:memory.populate-bitemporal-kg). code ours / data sparse
  • Hallway / tunnel graph. Still theirs. Only remaining adopt. theirs
  • AGPL SaaS extras (billing, 2FA, per-tenant Qdrant, GDPR SQLite export, installer sandboxes). Not wanted for a single-org fleet. skip

🛡️ Where OURS is genuinely better (do not regress)

  • Real many-writer concurrency (Postgres MVCC). N agents write at once as a first-class property. ours
  • Live cross-agent bus (pg_notify). Changes broadcast in real time; theirs has none. ours
  • Fast search by default (HNSW). Theirs full-scans SQLite unless you stand up Qdrant. ours
  • Forgetting / decay lifecycle. Stale notes fade + archive automatically; theirs never ages a memory out. ours
  • Session management + a working tier. Resume, crash-detection, cross-agent handoff, pinned core-memory blocks. ours

The two designs, side by side

agentsmemory (Go) stateless network service, per-team vaults N remote agents (any machine) POST /mcp with a bearer token Stateless Streamable-HTTP MCP (Go) bearer -> one team; scales behind a load balancer SQLite = source of truth SINGLE writer, no WAL (the concurrency bottleneck) Qdrant index OPTIONAL (ANN) default = brute-force scan Per-team physical vault + GDPR export cryptographic isolation (a real strength) MPRO memory (Node + Postgres) one central DB, one trusted fleet N stdio MCP children + bridges + bots self-declared agent_id (honor-system) Postgres mpro_core - MVCC (many writers) pool + backoff + circuit-breaker pgvector HNSW fast ANN by default + value_tsv GIN (keyword) pg_notify bus live cross-agent events + session lifecycle Decay / forgetting daemon + namespaces theirs has NO aging at all
Two philosophies: a multi-tenant network service (left) vs a single-org concurrent-substrate fleet memory (right). Solid arrow = default path; dashed = optional. Grounded in cmd/server/main.go, store/hybrid.go, store/sqlitevec/sqlitevec.go (theirs) and tools/agent-memory-mcp-server.js, core/db.js (ours).

When would a SWAP actually win?

To be fair to their design: a swap to their self-hosted server would win ONLY if all five of these became true - and none is true today:

  1. MPRO must serve multiple untrusted tenants (external customers, not one company) - so their per-team physical vault earns its keep.
  2. We accept AGPL-3.0 network-copyleft on an externally-exposed service.
  3. We accept standing up + operating Qdrant + Ollama bge-m3 + a Go service as new infrastructure.
  4. agentsmemory proves stable under many concurrent agents (needs WAL + database advisory locks + a stress test - unproven, 0 production users).
  5. We accept losing MVCC concurrency, the pg_notify realtime bus, HNSW-by-default, session lifecycle, and decay - features theirs simply does not have.

Until those flip, (A) is the grounded call. The one idea worth banking from a swap for the far future is their bearer-token + stateless-HTTP tenant boundary - adopt it only IF/WHEN MPRO ever exposes memory to untrusted external tenants across machines. That is a business decision for later, not a technical one for now. [multiagent lens - recommendation section]

🛡️ The live hard-proof - ours was silently broken, then fixed (don't trust paper)

The uncomfortable truth first (satya). Every strength we claim for MPRO was not actually working in real life until this session. The code was writing memories with 768-number "fingerprints" (embeddings) but the live database column only accepted 384-number fingerprints - a size mismatch that made the search crash and silently fall back to "just show the newest few". Nobody's memory search was really working. This is the whole point of grounding a claim in a live probe, not a paper design.

1. BEFORE - the probe caught it red-handed

Source of truth: live-proof.json (a real read-only probe of the live DB this session).

FATAL: different vector dimensions 384 and 768 has_tsvector: false rows: 14 · embedded: 5 ollama_embed dims: 768
  • Dimension mismatch. The embedder produces 768-d vectors (Ollama nomic-embed-text), but the live agent_memory.embedding column was vector(384) - so a hybrid search errored with FATAL: different vector dimensions 384 and 768.
  • No keyword arm live. has_tsvector: false - the value_tsv full-text column was not present, so the keyword half of "hybrid" search did not exist.
  • Most rows unembedded. Only 5 of 14 rows had a vector at all - 9 of 14 had none. So recall silently degraded to recency-only ("newest N"), NOT "most relevant".
Diagnosis (honest): config drift, NOT an architecture flaw. The hybrid path, decay, and namespaces were all coded - the column dimension had just fallen out of sync with the model.

2. THE FIX - commit 23cdd44ba

3. AFTER - proven working, both arms firing

Source of truth: live-proof-after.json.

embedding_coltype: vector(768) has_tsvector: true (value_tsv) rows: 14 · embedded: 14 BOTH_ARMS_FIRED: true

A real query ("OLLAMA BRIDGE found REVIEW review TASK") now recalls the right memory with BOTH arms contributing:

recalled_key : ollama-bridge-returns-canned-greeting
vector_sim   : 0.675   (meaning match - the semantic arm)
bm25         : 0.0317  (keyword match - the lexical arm)
similarity   : 1.000   (normalized fused score = top rank)
BOTH_ARMS_FIRED: true
Result: genuine hybrid recall restored - the vector arm and the keyword arm both fire and blend, on infrastructure we already run. The other four candidates fall away cleanly (vector 0.45-0.46, bm25 0.0). [multiagent lens live-state; live-proof-after.json]

Why this matters more than any table below

The comparison tabs weigh two designs. This tab proves the harder point: a beautiful design that is mis-configured is worse than a plain one that runs. Ours was the mis-configured one - now it is the running one. Verify it yourself:

python3 -c "import json;d=json.load(open('/home/darius/MPRO/docs/agentsmemory-eval/live-proof-after.json'));print('cols',d['embedding_coltype'],'| tsv',d['has_tsvector'],'| embedded',d['rows']['emb'],'/',d['rows']['n'],'| both arms',d['hybrid_proof']['BOTH_ARMS_FIRED'])"
# -> cols vector(768) | tsv True | embedded 14 / 14 | both arms True

⚖️ Whole-capability comparison - honest both ways

Every row is grounded in a real function body read on both sides (satya / validate-body-not-title). The "winner" column is called plainly, with the reason. Legend: theirs agentsmemory stronger · ours MPRO stronger · tie / neither.

CapabilityagentsmemoryMPROWinner + why
Recall fusion (ranking maths)rank.go rankHybrid: real Okapi-BM25, min-max normalized to [0,1], then 0.6*vec + 0.4*bm25 + closetBoost; stable-sort ties.Was 0.7*vec + 0.3*ts_rank_cd with BM25 un-normalized (~0.01-0.1) -> keyword term dwarfed -> effectively vector-only. Now normalized (this session's fix).theirs taught it; the single biggest recall-quality gap - now closed on our side. [head-to-head]
Candidate poolservice.go: over-fetch limit*3 (or 10000 when filtering), re-rank survivors.Each CTE arm hard-capped at LIMIT 50; FULL OUTER JOIN admits a keyword-only hit within its own 50.theirs (marginal) - sizes the pool to the request. [head-to-head]
Backend recall (scale)Default = brute-force exact cosine over SQLite (O(N)); ANN only if Qdrant wired.pgvector HNSW ANN by default (sub-linear), generated tsvector + GIN.ours - ours scales by default; theirs full-scans until Qdrant stood up. [head-to-head]
Dedup / write identitychunk.go DrawerID = SHA256(team,wing,room,source,chunkIndex,content) - identical content is idempotent; distinct content never collides.content_sha on agent_memory + mine-file idempotency (tools/agent-memory-mine.js). Key upsert still exists; hash prevents silent same-body forks.ours now - content-hash landed after the July eval. [remeasured 2026-08-16]
Supersede / temporal KGkg.go bitemporal: no-auto-supersede, valid_to keeps history, as-of time-travel, inverted-interval guards, current-dedup.kgQuery(..., asOf) in agent-memory-capabilities.js (lines 95-123). Mining still barely fills the table (task:memory.populate-bitemporal-kg open).code ours / data sparse - as-of query exists; extraction is the remaining leak. [remeasured 2026-08-16]
Topic index / closetcloset.go: extract action-phrases + headers + quotes -> embedded pointer index; diminishing rank-boost [0.40,0.25,0.15,0.08,0.04].computeClosetBoosts / applyClosetBoosts in tools/agent-memory-quality.js, applied in search at agent-memory-mcp-server.js (~2265) via memory_topics.ours now - July "no searchable topic-boost" is stale. [remeasured 2026-08-16]
Chunking + entity/dateBoundary-aware chunker (1600/320/50), entity extraction (COCA stoplist), content-date extraction (frontmatter -> body).Stores the whole value as ONE un-split row; no entity/date extraction.theirs outright (impact smaller for our short notes). [head-to-head]
Multi-agent shareabilityONE network server; cross-machine, cross-tenant; versioned team skills.ONE central Postgres; shared/team namespaces + pinned Letta core-memory blocks broadcast to all.tie - theirs central across machines; ours central across a trusted fleet on one box. [multiagent]
Tenant isolationPhysical: one Qdrant collection per team; bearer -> exactly one team at one choke point (ResolveToken). A missing filter cannot leak.Logical only: shared table + namespace filter; agent_id is self-declared (no bearer, no RLS at the memory layer) - spoofable by any DB-connected process.theirs for untrusted multi-tenancy; fine for one trusted org (ours). [multiagent]
Concurrency / consistencySingle SQLite SoT, no WAL / busy_timeout set anywhere; in-process locks that "do NOT coordinate across horizontally scaled instances" (their comment).Postgres MVCC - real concurrent writers; pool + backoff + circuit-breaker; row-level upsert.ours clearly - the biggest gap on THEIR side for many agents. [multiagent]
Transport / scaleStateless Streamable-HTTP MCP - trivially horizontal behind a load balancer (on paper).stdio MCP plus live AgentMemoryHTTP :3069 (mpro-AgentMemoryHTTP.service, health 200 on 2026-08-16). Bridges share one Postgres; pg_notify is the bus.ours - HTTP share for kimi/grok/ollama already exists; do not add a second MCP. [remeasured 2026-08-16]
Realtime busNone (pure store).pg_notify streams (agent_events / memory_block_update) + session heartbeat, crash detection, cross-agent handoff.ours - live propagation theirs does not have. [multiagent]
Lifecycle / forgettingNONE - a drawer lives forever until deleted/re-mined.temporal_class + search-time decay filter + startMemoryDecayCleanup daemon (ephemeral@3d / short@30d -> archive) + valid_to.ours decisively - theirs never ages a memory out. [lifecycle, head-to-head]
Working tier / session mgmtNone - no pinned core memory, no session concept.Letta memory_blocks (pinned, ~2000-token budget at resume) + memory_load_layers (L0-L3) + full session lifecycle.ours - a real hot buffer; theirs is a flat store. [lifecycle]
Consolidation - associativeClosets + hallways (entity co-occurrence ≥2) + tunnels = a derived memory graph.None (has addressing, no derived association graph).theirs - genuinely brain-like association. [lifecycle]
Consolidation - summarize / gistStill ABSENT on their side (drawers stay full).agent-memory-consolidate.js + nightly timer. Last run 2026-08-16 04:43 EEST dry-run: gists=25 crossAgent=10 contradictions=270 downscale=5 promote=5 mutated=false. Apply stays off.ours (dry-run) - July "neither has it" is stale. Keep mutate off. [remeasured 2026-08-16]
Usage telemetry in rankNone on drawers (L7 edge dynamics exist but are dormant scaffolding, never updated).access_count / surface_count / last_surfaced_at updated on every read; feeds the decay score.ours - a real recency-of-use signal. [lifecycle]
Code quality / DDDA-: textbook bounded contexts, ubiquitous language IS the schema, correct dependency direction, ports-and-adapters.A large, battle-tested JS server; less formal DDD but hardened in a live fleet for years.theirs for structure; ours for production mileage. [code-review]
Tests / coverageTests B+ (golden-parity ranker suite); coverage C+/B- static estimate; MCP tool boundary = 0 tests.TDD-gated across the harness; the memory server is exercised live (this session's probes are the proof).split - their domain math is well-tested; their transport/boundary is the hole. [code-review]
SecurityA-: tenant isolation by construction, const-time compares, PKCE, fail-closed webhooks. Gaps: cookie/rate-limit/supply-chain hardening.Honor-system single-tenant by design (one org); code-based signing + RLS elsewhere in the harness.theirs for multi-tenant security posture. [code-review]
Export / GDPRdataexport.BuildTeamArchive - a scoped standalone SQLite with credential redaction + fail-closed table manifest.No per-subject export tool in the memory server (has a decay archive + pg_dump).theirs outright - a genuine per-tenant portable export. [head-to-head, multiagent]
LicenseAGPL-3.0 (network copyleft) - a real constraint if ever exposed externally + modified.Internal to MPRO; no external-copyleft obligation.ours for our use; theirs is a business-risk to weigh before any "expose it" idea. [multiagent, cta]
Deployment / opsSelf-contained Go binary + Dockerfile - clean as a standalone product. But adds Qdrant + Ollama bge-m3 + Go as new surface for us.Runs inside the existing MPRO stack (Postgres + pgvector + Ollama already live) - zero new services.ours for MPRO; theirs cleaner as a shipped product. [multiagent]
Row scoreboard (honest): across the multi-agent lens the split is roughly even and architectural, not "better/worse". Theirs is a multi-tenant network service that teaches us retrieval-quality maths (normalized fusion, closet, content-hash, bitemporal KG); ours is a single-org concurrent-substrate fleet memory that keeps the lifecycle + infra + multi-agent advantages (MVCC, pg_notify, HNSW, decay, sessions).

👀 What you (the CEO) most likely did NOT know

Plain-language, one risk per card. These are the things that change the decision.

1. Ours was broken in real life

The shared memory was silently recalling "newest few" instead of "most relevant", because the fingerprint size the code wrote (768) did not match the live database column (384). Nobody's memory search was really working today. Fix was hours, not a rebuild - and it is done + proven this session.

2. Their isolation is real; ours is honor-system

In MPRO an agent's identity (agent_id) is just a value it types - no password proves it. Fine because we are one trusted company, but it means our memory is single-tenant and could not safely hold other companies' data the way theirs can (each team gets its own locked vault via a bearer token).

3. Their concurrency is unproven, maybe weaker

They are built to run many copies behind a load balancer, but all copies still write to one SQLite file with no "wait-your-turn" setting. Under many simultaneous agents that can jam. Ours (Postgres) is designed for exactly this. Their own code comments admit the locks do not coordinate across copies.

4. License: AGPL-3.0 (network copyleft)

If we ever ran their code as a service other people reach over a network AND we modified it, AGPL can legally require us to publish our modified source. Fine for purely internal use - but a real business constraint before any "expose it externally" idea. It is not disclosed on their landing page, only in the repo.

5. Their default install ships a SaaS data-egress path

The default curl | bash installer registers a remote MCP at aiagentmemory.dev/mcp - so every memory read + write leaves the machine to their cloud, by default, not behind a flag. It also rewrites your .claude config (a Stop hook + a CLAUDE.md bootstrap) and can chain a second curl|bash from a third-party org. For MPRO this is disqualifying - our memory (company + client context) must never leave MPRO infra. "Adopt agentsmemory" could only ever mean self-host, never this.

6. A swap is a migration + new operational surface, not a drop-in

Every existing memory would have to be moved and re-embedded into a different model's vectors, and we would lose our realtime cross-agent bus (pg_notify), our session-lifecycle recovery, and our decay/aging - features theirs simply does not have. Plus three new services to keep alive (Go + Qdrant + Ollama bge-m3).
Fair to them: the SaaS-egress installer and AGPL are normal, defensible choices for an open-source SaaS product aimed at outside developers. They are only disqualifying for MPRO's data-isolation rule - not a criticism of their engineering. The self-host go build path avoids the egress entirely. [audit lens sec 0; cta lens; multiagent lens]

🧠 The exciting part - what the sleeping brain does, and what NEITHER tool copies

The big idea in plain words. Your brain does not keep every memory forever, and not in one place. While awake, you grab experiences fast into a scratchpad (the hippocampus). While you SLEEP, the brain quietly replays the day, copies the important bits into long-term storage (the neocortex), throws away the noise, and turns many similar experiences into one general lesson (a "gist"). This is exactly the shape a good agent memory should have - and MPRO is half built for it. We have the "forgetting" half. We are missing the "sleep" half. That missing piece is the top upgrade.

The five brain mechanisms (each cited to a real paper)

MechanismPlain meaning + the citation
Sleep replay + systems consolidationIn deep sleep the brain re-plays the day's firing patterns at high speed and slowly moves memories from the fast temporary store to the slow permanent one. Diekelmann & Born 2010, Nat Rev Neurosci nrn2762; Wilson & McNaughton 1994, Science (seminal replay); Rasch & Born 2013, Physiol Rev.
SHY - sleep downscales synapsesBy night the brain is "louder" from a day of use; deep sleep turns the overall volume DOWN - weak, rarely-used connections shrink toward zero (forgotten), strong ones survive. Forget the noise, keep the signal. Tononi & Cirelli 2006, Sleep Med Rev PMID 16376591; 2014 review, Neuron.
CLS - a fast store + a slow storeThe hippocampus learns FAST from one experience (episodic); the neocortex learns SLOWLY over many (semantic). Sleep is the bridge, avoiding "catastrophic forgetting". The direct blueprint for a two-tier agent memory. McClelland, McNaughton & O'Reilly 1995, Psych Review; Kumaran, Hassabis & McClelland 2016, Trends Cogn Sci (the AI-facing update).
Adaptive forgetting + the forgetting curveForgetting the right things on purpose makes you smarter - it stops stale details misleading today's decisions. Retention drops roughly exponentially (R = e^(-t/S)) unless reviewed; each review flattens the curve. Richards & Frankland 2017, Neuron S0896-6273(17)30365-3; Ebbinghaus 1885.
Salience / emotional taggingAn important or emotional memory gets "tagged", and the tag lets it capture the scarce resources to become permanent. Retention tracks what matters. Frey & Morris 1997, Nature 385:533; Redondo & Morris 2011, Nat Rev Neurosci nrn2963.

The AI bridge is not new: reinforcement-learning "experience replay" is a literal copy of hippocampal replay (Mnih et al. 2015, Nature - DQN), and Generative Agents (Park et al. 2023, UIST) already score memories by recency × importance × relevance and periodically write higher-level reflections back - a software echo of tagging + gist.

The cognitive-tier map - both tools, five brain functions

Brain function agentsmemory MPRO Gap? 1. Working / conscious tierpinned hot set, always in front ABSENT PRESENT (blocks + L0-L3) MPRO wins 2. Deep / long-term tierlarge store, retrieved on demand yes (brute-force) yes (HNSW ANN) ~tie 3a. Consolidation - associativelink related memories closets+hallways+tunnels ABSENT theirs wins 3b. Consolidation - summarize / GISTcompress many into fewer, better ABSENT ABSENT NEITHER (the gap) 4. Forgetting / decay / archivalage out the stale ABSENT decay daemon + filter MPRO wins 5. Learned salience ABSENT (dormant) partial (importance static 0.5) MPRO leads, unfinished
agentsmemory has 3 of 5 tiers missing (working, forgetting, salience) but is strongest on association; MPRO has 4 of 5 in some form but its consolidation is manual and its forgetting is age-cutoff not curve. The highlighted row - true gist summarization - is missing in both. [lifecycle lens; brainscience lens]

The brain-inspired MPRO roadmap (ranked, all pure-JS on our stack)

No Qdrant, no new service, no data migration - Postgres + pgvector + Ollama, using columns we already have.

#UpgradeThe HOW (concrete)
1 ⭐The "SLEEP" consolidation pass (build first - closes the gap NEITHER tool has)An idle-time daemon modeled on the decay daemon, guarded to never fire while a session is active. Four phases: REPLAY (pull recent rows since last run) -> GIST-MERGE (cluster near-duplicates by the embedding cosine we already compute, then call the local Ollama model to write ONE consolidated "gist" row, temporal_class:'long') -> DOWNSCALE (archive the weak raw episodics - extend the existing startMemoryDecayCleanup) -> PROMOTE the salient rows + new gists into the working tier. Read-mostly, reversible (sources kept). [brainscience Upgrade 1; lifecycle #1]
2Learned salience (cheapest, high value - MPRO already has the inputs)End the static importance = 0.5. Recompute in the decay daemon: importance = clamp(0.3 + 0.12*ln(1+surface_count) + 0.08*ln(1+access_count) - staleness + kg_link_bonus, 0.05, 1.0). Because importance already feeds the search decay score, frequently-surfaced memories auto-resist decay = the rehearsal/spacing effect, for free. Pure SQL. [brainscience Upgrade 3; lifecycle #2]
3Real forgetting curve + prune the unbounded classesAdd a stability column (starts ~1, +=1 per surface); retention R = exp(-days_since_surfaced / stability); archive when R < 0.1 for ALL classes incl. the default medium (today search-hidden but never physically pruned = a disk leak). Each retrieval flattens the curve. [lifecycle #3]
4Adopt their association layer + a bounded working setPort their closets/hallways (entities -> a co-occurrence + topic-boost table that lifts recall - MPRO has none, theirs proves its value). And make memory_blocks a true attention buffer: when the pinned-block budget is exceeded, auto-demote the least-recently-surfaced block. [lifecycle #4; brainscience Upgrade 2/4]

Caveat (satya): the "sleep-inspired LLM memory" arXiv preprint (2603.14517) was seen in this turn's search listing only - a pointer, not a validated result. The five brain mechanisms above are each cited to a seminal paper AND a current review.

🌟 Part 4 - Can the KB @ 3001 be our long-term brain? YES - it already IS it.

The three brain tiers are not something we need to build - they map onto three MPRO objects we already run. [grounded in SYSREF-004 (Knowledge Base) + SYSREF-001 (Mastermind)]

Brain tierThe MPRO object we already run
Working / consciousLetta memory_blocks (pinned) - the small hot set always kept in front of the agent.
Fast episodic / recent
(hippocampus + recent neocortex)
agent_memory rows - the pgvector hybrid, just fixed to 768-d.
Crystallized semantic
(the neocortex proper)
KB @ 3001 (knowledge.items, 4,371 items), imported by 177 fleet files - the shared neocortex the whole company reads.

The KB is more neocortex-like than a plain search box: it is a full RAG stack - a reranker (Ollama cross-encoder) + a CRAG confidence-grader + a HyDE query-expander + a 5-guard hallucination check + graph-community associations. And the load-bearing detail: the KB and agent_memory embed through the SAME RAGGateway (nomic-embed-text), so promoting a memory from Tier-2 to Tier-3 needs no re-embed - rock-solid now the 384->768 dimension fix has landed. Mastermind is the brain's salience filter: only confirmed, generalizable knowledge crystallizes into the KB; raw daily episodics stay in agent_memory or decay away.

🧠 Part 5 - the memory CIRCUIT MPRO already has (write-wire reconnected)

Put together, these three tiers form a real brain circuit - and the write-wire between them was cut since the Windows->Linux migration and is now reconnected:

Mastermind = the salience trigger (SYSREF-001 - the amygdala's "this matters, keep it")
→ the learn-capture hook = the hippocampal write path (JUST FIXED, commit ec79448ac)
→ KB @ 3001 = the neocortex store (SYSREF-004).

Design takeaway: don't build a new store. The three tiers already exist - the work is to wire them: promotion/demotion between tiers + the sleep-consolidation pass (the Fix-first tab), all on the stack we already own.

🤝 For the agentsmemory developer - constructive review

First, the praise - it is earned. This is a well-architected, security-conscious, honestly-commented codebase whose domain core is properly tested. The gaps below are concentrated in the transport/wiring layer and a handful of hardening items - all cheap relative to the quality of the foundation. Every finding cites a real file:line we read.

The scorecard (static read; Go was not installed, so coverage is a labelled estimate)

AxisGradeOne-line
Architecture / DDDA-Textbook bounded contexts; ubiquitous language IS the schema; clean domain->transport direction.
Code qualityA-Exceptional why-comments, sentinel errors, small functions; a few real error-swallows.
TDD / testsB+Critical maths genuinely tested incl. golden-parity; transport layer has 0 tests.
Coverage (est.)C+/B-~55-70% overall; domain 75-90%, MCP tool surface & cmd/server ~0%; no coverage/-race gate in CI.
SecurityA-Tenant isolation by construction; const-time compares, PKCE, fail-closed webhooks.
ReliabilityBSensible bounds + in-proc locks; one non-atomic data-loss window; no -race.

Single biggest strength: tenant isolation is enforced by construction - the bearer token resolves to a TeamID at exactly one choke point (tenant.go:284), threaded through every query as Where("team_id = ?"); no MCP tool ever reads a team id from its arguments; even a hypothetical foreign vector hit is dropped by a defense-in-depth re-filter (service.go:428). For a multi-tenant SaaS that is the thing that matters most, and it is done right.

Top constructive findings (most severe first)

#Finding + locationThe fix
R1Non-atomic mine = silent data-loss window. Mine purges the whole prior version of a source before storing the new drawers, and an embed call that can fail sits in between (mine.go:128-166). A crash mid-re-mine leaves the source erased with no rollback.Embed before purge, and/or wrap purge + store + closet-build in one transaction that commits only after all writes succeed. Add the failing-embedder test. Highest-impact - it is silent loss of the product's core asset.
T1The MCP tool surface has 0 tests. internal/mcpserver/* (~927 LOC of handlers - the actual boundary agents call) + cmd/server have no _test.go. This is where a tenant-isolation regression would hide.Add handler-level tests: (a) missing/foreign token rejected by admit, (b) args sanitized, (c) output shape. Add go test -race -coverprofile to CI to turn the honest "we don't know the number" into a tracked one.
R2Interval-blind KG dedup silently drops updates. KGAdd returns the existing id whenever any open fact matches, ignoring the requested valid_from/valid_to (kg.go:179-190,351-355). Re-adding with a corrected start or a bounded interval is discarded.Include the interval in the dedup match, or return a distinct signal so the caller knows nothing was recorded. Add a test.
S1/S2Web session hardening. Auth/2FA/passkey cookies lack the Secure flag; no HSTS. No server-side rate-limit on login/TOTP; the 2FA counter lives in a user-held cookie (bypassable). (web.go:80-86,299-319)Set Secure: true (dev-gated) + emit HSTS; add per-user + per-IP failed-attempt lockout for both factors.
S3/S4Installer has no integrity check. The release binary is downloaded with no checksum/signature, default version latest; --recommended pipes a third-party curl|bash from another org's main, unpinned. (install.sh:46-62, main.go:30)Publish + verify a per-asset sha256 (ideally a signature); pin the version in the shown command; pin/vendor the third-party fetch with explicit consent naming the source.
polishDoc/behavior mismatch: rank.go:158 comment says "min-max normalized" but the code is max-only (ordering unaffected). Swallowed setSessionUser error redirects a not-logged-in user to /dashboard (oauth.go:137).Fix the comment; redirect to /login on the non-nil error, mirroring the branch above it.

Conversion / adoption (from the cold-buyer journey audit)

Fair and friendly: the product is well-built, but a cold developer does not adopt today - and every fix is free. Journey scores: FEEL 6.5/10, TRUST 3/10, ACT 4/10.

Reassuring finding from our read: across every script, there were no reverse-shells, no hidden phone-home beyond the by-design remote MCP, no prompt-injection payloads. The flagged behaviours are visible and understandable - not malware. [audit lens sec 0; cta lens; code-review lens]

🛠️ Details - what we implemented, and what is tracked next

✅ Done this session

📋 Adopt-their-ideas backlog (tracked, pure-JS on our stack)

Idea (from their code)StatusNote
Normalized hybrid fusionDONEShipped as part of the live fix (23cdd44ba).
Closet topic-boost indexDONEWired 2026-08-16 remeasure: computeClosetBoosts + memory_topics.
Content-hash idempotent dedupDONEcontent_sha + mine idempotency present.
memory_mine pipelineDONEtools/agent-memory-mine.js + file miner exist.
Bitemporal KG as-of queryDONE (code)kgQuery(asOf) exists. Populate-from-mine still open on task:memory.populate-bitemporal-kg.
Sleep-consolidation passDONE (dry-run)Nightly timer; 2026-08-16 04:43 EEST mutated=false. Keep apply off.
Hallway / tunnel association graphopenOnly remaining idea. Independent JS. Do not copy AGPL Go. Tracked on task:harness.eval-agentsmemory-mcp.
Their installer / second MCP / GDPR SQLite exportskipAGPL + fights managed hooks + we are one org. SkillAPI :3045 already covers versioned skills (health 200, 417 rich skills).

🔄 Changelog (newest first)

Sources (grounded, re-checkable)

🧩 Architecture diagrams - Mermaid source + rendered + ASCII, for BOTH systems

Why this tab exists. This report is shared with agentsmemory's creator, who may feed it to his own AI agents. So every diagram is given as machine-parseable TEXT - a copyable ```mermaid block AND a plain-text ASCII box diagram - alongside the rendered picture. Nothing here needs a CDN or a live script: the PNGs were rendered offline with the repo pipeline (tools/scripts/validate-mmd.js + @mermaid-js/mermaid-cli) and embedded as static images. Copy any block below and hand it straight to an agent. Every component is grounded in the real code read this session - none is invented.

1. agentsmemory - the memory-palace architecture

agentsmemory memory-palace architecture
Stateless HTTP MCP + bearer->tenant + per-team physical vault (SQLite SoT, optional Qdrant); the Wing/Room/Drawer/Closet/Hallway/Tunnel/KG schema; the normalized hybrid ranker. Grounded in cmd/server/main.go, internal/tenant/tenant.go, internal/palace/{service,mine,chunk,entity,closet,hallway,tunnel,kg,rank}.go, internal/store/{sqlitevec,qdrant,hybrid}.go, internal/embed/ollama.

Mermaid source - copy the fenced block into any Mermaid viewer:

```mermaid
%%{init: {'theme': 'dark'}}%%
flowchart TB
  A1["N remote agents (any machine)<br/>POST /mcp + Bearer token"]
  A1 -->|bearer| MCP
  subgraph SVC["Stateless Streamable-HTTP MCP (Go)"]
    MCP["server.WithStateLess(true)<br/>OAuth 2.1 + direct bearer"]
    RT["ResolveToken<br/>bearer maps to ONE team (tenant)"]
    MCP --> RT
  end
  RT -->|team_id| MINE
  subgraph MINING["Mining pipeline (per source, keyedMutex)"]
    MINE["Mine: purge-then-write"]
    CHUNK["ChunkText 1600/320/50 boundary-aware"]
    ENT["entity + content-date extraction"]
    MINE --> CHUNK --> ENT
  end
  ENT --> EMB["Ollama embed - bge-m3 (1024-d)"]
  EMB --> SQLITE
  EMB -. optional .-> QDR
  subgraph VAULT["Per-team physical vault (cryptographic isolation)"]
    SQLITE[("SQLite = SOURCE OF TRUTH<br/>single writer, no WAL")]
    QDR[("Qdrant collection per team<br/>mempalace_(sha16)_drawers<br/>OPTIONAL ANN index")]
  end
  subgraph PALACE["Memory-palace schema"]
    WING["Wings = project namespaces"]
    ROOM["Rooms = aspects"]
    DRAWER["Drawers = verbatim chunks<br/>DrawerID = SHA256(team,wing,room,content)"]
    CLOSET["Closets = topic/quote index<br/>team::closets namespace"]
    HALL["Hallways = within-wing links<br/>entity co-occurrence 2+"]
    TUN["Tunnels = cross-wing links"]
    KG["Knowledge-Graph<br/>bitemporal, as-of time-travel"]
    WING --> ROOM --> DRAWER
    DRAWER --> CLOSET
    DRAWER --> HALL --> TUN
    DRAWER --> KG
  end
  SQLITE --- PALACE
  subgraph RANK["Hybrid ranker (rank.go rankHybrid)"]
    VEC["vector sim (bge-m3 cosine)"]
    BM["BM25 Okapi -> min-max [0,1]"]
    CB["closet-boost 0.40..0.04"]
    FUSE["fused = 0.6*vec + 0.4*bm25 + closetBoost"]
    VEC --> FUSE
    BM --> FUSE
    CB --> FUSE
  end
  SQLITE --> RANK
  QDR --> RANK
```

ASCII - no renderer needed (agent-friendly):

        N remote agents (any machine)  --POST /mcp + Bearer token-->
                              |
                              v  bearer
   +----------------------------------------------------------+
   |  Stateless Streamable-HTTP MCP (Go)                      |
   |  server.WithStateLess(true) + OAuth2.1 / direct bearer   |
   |  ResolveToken:  bearer  -->  ONE team (tenant)           |
   +----------------------------------------------------------+
                              |  team_id
                              v
   +----------------------------------------------------------+
   |  Mining pipeline (per source, keyedMutex)                |
   |  Mine purge-then-write --> ChunkText 1600/320/50         |
   |  --> entity + content-date extraction                    |
   +----------------------------------------------------------+
                              |
                              v
                 Ollama embed  bge-m3 (1024-d)
                       |                    \  optional
                       v                     v
   +===========================+   +==========================+
   | SQLite = SOURCE OF TRUTH  |   | Qdrant per-team          |
   | single writer, no WAL     |   | collection (ANN index)   |
   +===========================+   +==========================+
      \____ per-team PHYSICAL vault (cryptographic isolation) ____/
                       |
                       v   MEMORY-PALACE SCHEMA
   Wings (project ns) --> Rooms (aspects) --> Drawers (verbatim chunks,
                                              DrawerID = SHA256(content))
        Drawers --> Closets          (topic/quote index, team::closets)
        Drawers --> Hallways         (within-wing, entity co-occur >= 2)
                        Hallways --> Tunnels (cross-wing links)
        Drawers --> Knowledge-Graph  (bitemporal, as-of time-travel)
                       |
                       v   HYBRID RANKER (rank.go rankHybrid)
   fused = 0.6*vector(bge-m3 cosine) + 0.4*BM25(min-max [0,1]) + closet-boost

2. MPRO memory - the 3-tier brain architecture

MPRO 3-tier memory architecture
The brain write-circuit (Mastermind salience -> learn-hook write -> KB store); the 3 tiers (Letta memory_blocks -> agent_memory pgvector -> KB @ 3001); the normalized pgvector hybrid search; decay daemon + pg_notify bus + namespaces on Postgres MVCC. Grounded in tools/agent-memory-mcp-server.js, tools/agent-memory-capabilities.js, core/db.js, migration 006-memory-vectors.sql, .claude/hooks/learning-capture.js.

Mermaid source:

```mermaid
%%{init: {'theme': 'dark'}}%%
flowchart TB
  C1["N agents in one trusted fleet<br/>stdio MCP children + bridges + bots<br/>self-declared agent_id"]
  C1 --> WRITE
  C1 --> READ
  subgraph BRAIN["Brain write-circuit (JUST RECONNECTED)"]
    MM["Mastermind = salience / amygdala trigger"]
    LH["learn-hook (Stop) = hippocampal write-path<br/>FIXED commit ec79448ac"]
    MM --> LH
  end
  LH --> WRITE
  WRITE["memory_write<br/>ON CONFLICT (agent, category, key)"]
  WRITE --> EMB["RAGGateway to Ollama<br/>nomic-embed-text (768-d)"]
  subgraph TIERS["3 cognitive tiers"]
    T1["TIER 1 - working / conscious<br/>Letta memory_blocks (pinned) + L0-L3 layers"]
    T2[("TIER 2 - deep / sub-conscious<br/>agent_memory Postgres pgvector<br/>embedding vector(768) + value_tsv")]
    T3[("TIER 3 - crystallized neocortex<br/>Knowledge Base @ 3001")]
    T1 --> T2 --> T3
  end
  EMB --> T2
  LH -. mirror @source:lessons .-> T3
  subgraph SEARCH["pgvector HYBRID search (JUST FIXED)"]
    V["vector cosine 768-d - HNSW ANN"]
    B["tsvector BM25 - GIN index"]
    F["normalized 0.6*vec + 0.4*bm25 fusion"]
    D["decay filter - drop score below 0.1"]
    V --> F
    B --> F
    F --> D
  end
  READ["memory_search / session_resume"] --> SEARCH
  T2 --> SEARCH
  subgraph LIFE["Lifecycle + realtime"]
    DECAY["decay daemon (forgetting)<br/>startMemoryDecayCleanup<br/>ephemeral@3d / short@30d to archive"]
    BUS["pg_notify realtime bus<br/>agent_events / memory_block_update"]
    NS["namespaces: private / shared / team"]
  end
  T2 --> DECAY
  T2 --> BUS
  T2 --> NS
  PG[("Postgres MVCC - many writers")]
  PG --- T2
```

ASCII:

   N agents, one trusted fleet: stdio MCP children + bridges + bots
   (self-declared agent_id)
        |                                                  |
        |  BRAIN WRITE-CIRCUIT (just reconnected)          |  query
        v                                                  v
   Mastermind (salience / amygdala trigger)          memory_search /
        |                                             session_resume
        v                                                  |
   learn-hook (Stop) = hippocampal write-path              |
   [FIXED commit ec79448ac]                                |
        |                                                  |
        +--------------------> memory_write <--------------+
                                    |  ON CONFLICT (agent, category, key)
                                    v
                    RAGGateway --> Ollama nomic-embed-text (768-d)
                                    |
   +======================= 3 COGNITIVE TIERS =======================+
   | TIER 1  working / conscious : Letta memory_blocks (pinned)     |
   |                               + memory_load_layers L0-L3       |
   |            |  promote / demote                                 |
   |            v                                                   |
   | TIER 2  deep / sub-conscious: agent_memory (Postgres pgvector) |
   |                               vector(768) + value_tsv          |
   |            |  Mastermind crystallizes confirmed knowledge      |
   |            v      (SAME RAGGateway embed --> no re-embed)       |
   | TIER 3  crystallized neocortex: Knowledge Base @ 3001          |
   +================================================================+
              |                    |                    |
              v                    v                    v
   pgvector HYBRID search   decay daemon           pg_notify bus
   0.6*vec(HNSW 768d)       (forgetting)           agent_events /
   + 0.4*BM25(tsvector/GIN) ephemeral@3d /         memory_block_update
   --> normalized fuse      short@30d --> archive
   --> decay filter (<0.1)                         namespaces:
   [JUST FIXED]             Postgres MVCC          private / shared / team
                           (many writers)

3. Side-by-side data-flow - write path + recall path on both

Side-by-side write and recall data flow
The exact write path and recall path on each system, laid side by side. Note both now normalize the hybrid fusion 0.6/0.4 (ours was the JUST-FIXED change); ours adds a decay filter + a live pg_notify broadcast; theirs full-scans SQLite by default unless Qdrant is wired.

Mermaid source:

```mermaid
%%{init: {'theme': 'dark'}}%%
flowchart TB
  subgraph AM["agentsmemory (Go) - multi-tenant network service"]
    direction LR
    aw1["WRITE: agent -> POST /mcp (bearer)"] --> aw2["mine -> chunk -> entity/date"] --> aw3["embed bge-m3 1024-d"] --> aw4["SQLite (SoT) + closet index"] --> aw5["Qdrant index (optional)"]
    ar1["RECALL: query -> embed"] --> ar2["SQLite brute-force cosine<br/>(or Qdrant ANN)"] --> ar3["BM25 over candidate pool (x3)"] --> ar4["normalized fuse 0.6/0.4<br/>+ closet-boost"] --> ar5["ranked drawers"]
  end
  subgraph MP["MPRO (Node + Postgres) - single-org fleet memory"]
    direction LR
    mw1["WRITE: agent -> stdio MCP (agent_id)"] --> mw2["memory_write<br/>+ learn-hook auto-capture"] --> mw3["embed nomic 768-d"] --> mw4["agent_memory pgvector<br/>+ value_tsv"] --> mw5["pg_notify broadcast"]
    mr1["RECALL: query -> embed"] --> mr2["HNSW ANN vector CTE"] --> mr3["GIN tsvector BM25 CTE"] --> mr4["normalized 0.6/0.4 fuse<br/>-> decay filter"] --> mr5["ranked memories"]
  end
  AM ~~~ MP
```

ASCII:

   agentsmemory (Go) - multi-tenant network service
     WRITE : agent --POST /mcp(bearer)--> mine->chunk->entity/date --> embed bge-m3(1024d)
             --> SQLite(SoT) + closet index --> Qdrant index (optional)
     RECALL: query --> embed --> SQLite brute-force cosine (or Qdrant ANN)
             --> BM25 over candidate pool (x3) --> normalized fuse 0.6/0.4 + closet-boost
             --> ranked drawers

   MPRO (Node + Postgres) - single-org fleet memory
     WRITE : agent --stdio MCP(agent_id)--> memory_write (+ learn-hook auto-capture)
             --> embed nomic(768d) --> agent_memory pgvector + value_tsv --> pg_notify broadcast
     RECALL: query --> embed --> HNSW ANN vector CTE + GIN tsvector BM25 CTE
             --> normalized 0.6/0.4 fuse --> decay filter --> ranked memories

4. The brain cognitive-tier map (both tools, five brain functions)

Brain cognitive-tier map of both tools
Working / deep / consolidation / forgetting / salience across both tools. The highlighted tier 3b - true gist summarization (the "sleep" pass) - is the one thing the sleeping brain does that NEITHER tool copies. [brainscience + lifecycle lenses]

Mermaid source:

```mermaid
%%{init: {'theme': 'dark'}}%%
flowchart TB
  W["1. WORKING / conscious (hippocampus)<br/>MPRO: memory_blocks + L0-L3 (PRESENT)<br/>agentsmemory: ABSENT"]
  D["2. DEEP / long-term (neocortex)<br/>MPRO: pgvector HNSW ANN<br/>agentsmemory: SQLite brute-force (Qdrant optional)"]
  CA["3a. CONSOLIDATION - associative<br/>agentsmemory: closets + hallways + tunnels (WINS)<br/>MPRO: ABSENT"]
  CG["3b. CONSOLIDATION - gist / summarize<br/>NEITHER has it = the shared gap = the SLEEP pass"]
  F["4. FORGETTING / decay / archival<br/>MPRO: decay daemon + search filter (WINS)<br/>agentsmemory: none"]
  S["5. SALIENCE-weighted retention<br/>MPRO: partial (importance, surface_count)<br/>agentsmemory: none (dormant L7 scaffolding)"]
  W --> D --> CA --> CG --> F --> S
  CG:::gap
  classDef gap fill:#7c3f12,stroke:#fbbf24,stroke-width:2px,color:#fde68a
```

ASCII:

   BRAIN FUNCTION                 agentsmemory           MPRO
   ----------------------------   --------------------   ----------------------------
   1 working / conscious          ABSENT                 memory_blocks + L0-L3   (MPRO wins)
   2 deep / long-term             SQLite brute-force     pgvector HNSW ANN       (~tie)
                                  (Qdrant optional)
   3a consolidation-associative   closets + hallways     ABSENT                  (theirs wins)
                                  + tunnels
   3b consolidation-GIST/summary  ABSENT                 DRY-RUN nightly timer   (MPRO leads; apply off)
   4 forgetting / decay           none                   decay daemon + filter   (MPRO wins)
   5 salience-weighted retention  none (dormant L7)      partial (importance,    (MPRO leads)
                                                         surface_count)

   Remaining gap is 3a hallway/tunnel, not gist. Gist exists as dry-run; keep apply off.