_ _ _____ _ _______ ___ _ ___ ___ _____ _____ _ _
| \ | || ___| | | | ___ \/ _ \ | | | \/ || ___/ ___| | | |
| \| || |__ | | | | |_/ / /_\ \| | | . . || |__ \ `--.| |_| |
| . ` || __|| | | | /| _ || | | |\/| || __| `--. \ _ |
| |\ || |___| |_| | |\ \| | | || |____ | | | || |___/\__/ / | | |
\_| \_/\____/ \___/\_| \_\_| |_/\_____/ \_| |_/\____/\____/\_| |_/
Stop dumping memory into a flat file that grows until it breaks. NEURAL_MESH is the neural-mesh brain for agents: typed memory, a self-linking topology, resonance retrieval, hot/cold lanes, a sleep cycle that forgets on purpose, and versioned truth. Light enough for a tiny container, deep enough to share across agents. 🟦
Repo: github.com/BasedNUKEM/NEURAL_MESH · Status: LIVE · Latest: v0.21.0 — Rust-accelerated resonance · License: MIT
| Pain | Flat memory (Mem0 / vector DB) | NEURAL_MESH |
|---|---|---|
| Fact updates | old + new both retrieved → agent acts on stale truth | supersedes link → old fact skipped → current only |
| Memory types | one pile, one cosine | 5 typed lanes, filterable |
| Related memories | lonely singleton hit | resonance → the cluster |
| Big tool output | 200 KB eats context | mesh:// pointer, 36 bytes |
| Old/weak memories | accumulate forever | sleep → prune on purpose |
| Query speed | — | Rust hot path: 1.63× faster, exact parity |
We kept hitting the same wall in production agents (Hermes, Sibyl, Tony-Simons setups, Base agent infra):
- 🟦 Memory always full — a flat
MEMORY.mdgrows unbounded; context compression silently degrades what the agent "remembers." - 🟦 No memory types — an episode (a deploy failed) and a fact (user is in KL) get dumped in the same pile and retrieved by the same cosine search.
- 🟦 Stale truth — when a fact updates (Maya's editor was Vim → is now Neovim), flat vector search keeps both embeddings and returns both. The agent acts on the old one.
- 🟦 Big output in context — a 200 KB log dump eats the whole window.
NousResearch/hermes-agent opened the door. NEURAL_MESH is the fork-shaped
answer: a memory substrate that organizes itself, forgets on purpose, and serves
only what's current and relevant.
┌──────────────────────────────────────────┐
agent ─────► │ INGEST (typed write) │
│ semantic | episodic | procedural | │
│ sensory | prospective │
└───────────────┬──────────────────────────┘
│ auto-link by meaning
▼
┌────────────────────────────────────────────────────────┐
│ MESH (memory nodes self-link into a graph) │
│ │
│ ◉ semantic ◉ episodic ◉ procedural │
│ │ ╲ │ ╲ │ │
│ │ ╲──link─────┘ ╲──link───────┘ │
│ ▼ ▼ ▼ │
│ ◉ prospective ◉ sensory (supersedes ▸) │
│ │ │
│ HOT lane │ consolidation bus COLD lane │
└──────────────────────┼──────────────────────────────────┘
│ SLEEP: replay → strengthen → prune
▼
RESONANCE retrieval (query seeds nodes,
activation spreads to linked neighbours w/ decay)
│
▼
only CURRENT + RELEVANT memories → context
- 🟦 Five memory types, handled separately.
semantic,episodic,procedural,sensory,prospective(intentions/futures, not just the past). Retrieval can filter by type so a deploy log never dilutes a user fact. - 🟦 Mesh topology, not a list. Each node auto-links to its nearest neighbours (HippoRAG-style hippocampal indexing). Meaning lives in the edges.
- 🟦 Resonance retrieval (the differentiator). A query seeds nodes; activation spreads across links with decay and re-ranks by relevance + recency + trust. You get the cluster, not a lonely singleton.
- 🟦 Hot / Cold lanes + sleep. Short-term traces live
hot; a consolidation bus moves durable knowledgecold. The sleep cycle replays, strengthens, and prunes weak/aged/low-trust traces — memory that forgets on purpose. - 🟦 Versioning / no stale truth.
supersedeslinks soft-archive old facts. Retrieval skips them. The agent only ever sees current truth. - 🟦 Pointer protocol. Big tool output is stored externally; context receives a
mesh://…pointer (36 bytes instead of 200 KB). - 🟦 Cross-agent ready. Provenance, trust, and a portable
.meshinterchange let meshes be shared and merged.
Resonance query scoring now runs an optional Rust/PyO3 hot path in production while keeping the pure-stdlib Python backend as an automatic fallback.
from neural_mesh import Mesh
m = Mesh("mesh.db") # auto: rust when available, else python
m2 = Mesh("mesh.db", resonance_backend="rust") # pin it
m3 = Mesh("mesh.db", resonance_backend="python") # deterministic fallback- 🟦 Exact parity, not "close enough" — parity tests prove identical ranked hits across backends
- 🟦 One abi3
.soruns on any Python ≥ 3.9 — dev and prod, no rebuilds - 🟦
/healthreports the active backend; pin withNEURAL_MESH_RESONANCE_BACKENDfor transparent ops + rollback - 🟦 Reproduce:
PYTHONPATH=. python3 bench/rust_resonance_bench.py --nodes 5000 --repeats 7
Zero dependencies to run the core + demo:
git clone https://github.com/BasedNUKEM/NEURAL_MESH
cd NEURAL_MESH
python -m neural_mesh.demo # pure stdlib, no pip neededOptional: real embeddings (dense vectors, no torch — uses fastembed/ONNX):
python -m venv .venv && .venv/bin/pip install fastembed
PYTHONPATH=. .venv/bin/python -c "from neural_mesh.core import Mesh, MemoryType
from neural_mesh.embed_real import RealEmbedder
m = Mesh(embedder=RealEmbedder())"Or install it as a package:
pip install neural-mesh # pure-stdlib core; extras optionalfrom neural_mesh.core import Mesh, MemoryType
m = Mesh() # sqlite, local, in-memory by default
# 1. write by TYPE
m.add("User Cody is in Kuala Lumpur.", MemoryType.SEMANTIC, provenance="chat")
m.add("Deploy failed: Vercel blocked unknown git author.", MemoryType.EPISODIC, provenance="log")
m.add("Run validate, then gh workflow to ship.", MemoryType.PROCEDURAL, provenance="skill")
m.add("Refactor memory module before launch.", MemoryType.PROSPECTIVE, provenance="user")
# 2. resonance recall — surfaces the cluster, not one match
for n in m.recall("how do I ship the deploy?"):
print(n.type.value, n.content)
# 3. versioning — update a fact, old one auto-archives
old = m.add("Maya's editor is Vim.", MemoryType.SEMANTIC)
m.add("Maya's editor is Neovim.", MemoryType.SEMANTIC, supersedes=old.id)
# recall("what editor does Maya use?") -> Neovim only. Vim is gone from results.
# 4. sleep — prune + reflect
m.sleep(reflect_fn=lambda nodes: ["insight: deploys need a known git author"])
# 5. bulk ingest — batched embedding for large corpora (e.g. LoCoMo)
m.add_many(sentence_list, type=MemoryType.SEMANTIC, autolink=False)The four core primitives run as one inspectable production cycle:
from neural_mesh import MemoryLifecycle, MemoryType, Mesh
brain = MemoryLifecycle(
Mesh("mesh.db"),
pointer_root="runtime/pointers",
pointer_threshold=8_192,
)
report = brain.cycle(
huge_tool_output,
query="what happened during deploy?",
label="deploy-log",
type=MemoryType.EPISODIC,
mode="fact", # dense-heavy hybrid; use "associative" for resonance
)The flow is pointer-safe ingest → routed retrieval → hot/cold consolidation →
sleep/replay/prune. Payloads above the threshold stay outside model context;
the mesh stores a searchable preview plus mesh://… pointer metadata. Use
mode="fact" for direct lookup and mode="associative" when graph spreading is
the desired behavior. The REST equivalent is POST /mesh/cycle. Every retrieval
mode also accepts lane="hot", lane="cold", or None (all live lanes).
Maintenance can run as lightweight mode="sleep" or enriched mode="dream";
both consolidate lanes first.
server.py exposes the full mesh API — including the new authenticated ops:
GET /health — node count + version + resonance_backend
POST /mesh/add — {content, type?, source?, by?}
POST /mesh/recall — {query, top_k?, mode?, lane?}
POST /mesh/cycle — full ingest→retrieve→consolidate→sleep cycle
POST /mesh/dream — {muse?: "template"|"llm"|false}
POST /mesh/sleep — {mode?: "sleep"|"dream"} → maintenance report
POST /mesh/consolidate — lane consolidation
POST /mesh/pointer — big output → mesh:// pointer
POST /mesh/pointer/summary — bounded pointer stats
POST /mesh/export — {path?} → .mesh JSONL
POST /mesh/merge — {path, policy?} → cross-agent merge
POST /mesh/stamp — {node_id, agent_id, aura_score?, verified_handle?}
GET /mesh/public?q=&limit=N — searchable public feed
GET /mesh/stats — node count + provenance breakdown
POST /mesh/answer — {query, context_chunks[]} → extractive reader
POST /mesh/recall-proof — {query, top_k?, mode?} → recall + proof cards
POST /mesh/answer-proof — {query, top_k?, mode?} → answer + citations + proof cards
🟦 Server hardening (v0.12+): mutating endpoints can require
NEURAL_MESH_API_TOKEN (Authorization: Bearer *** or X-API-Key),
import/export paths are constrained under NEURAL_MESH_SAFE_IO_DIR, requests
are rate-limited, JSON bodies are capped, CORS is denied unless
NEURAL_MESH_CORS_ORIGINS is set, and the dashboard escapes mesh content before
rendering. Intended as a local/dev wrapper unless deployed behind a real
production gateway.
Live 3D brain: https://api.d0xeddev.com/brain — an interactive digital-brain visualization of the production mesh (drag to orbit, hover nodes), with full Open Graph/Twitter card metadata for social link previews.
Run it:
.venv-server/bin/python server.py(port 4021), thencurl -X POST http://localhost:4021/mesh/dream -H "Content-Type: application/json" -d '{"muse":"template"}'
Built by agents, for agents. Here's the orientation an agent (or human) needs:
- 🟦
AGENTS.md— the 2-minute orientation for AI agents dropped into this repo (conventions, gotchas, commands). Read it before editing. - 🟦
brainstorm.md— design notes / decisions log. - 🟦
docs/launch_post.md— public launch copy + release notes.
# Hermes / Claude Code / any Python agent — drop-in memory layer
from neural_mesh import Mesh, MemoryType
memory = Mesh("~/.agent/memory.db")
def remember(content, type=MemoryType.SEMANTIC, **kw):
return memory.add(content, type, **kw)
def remember_episode(tool_output, query):
# big output never hits context — pointer protocol handles it
return memory.cycle(tool_output, query=query, label="tool-output")from neural_mesh import Mesh, export_mesh, import_mesh, merge_peer_mesh, PeerPolicy
export_mesh(agent_a, "a.mesh") # portable JSONL
import_mesh("a.mesh", agent_b) # re-embeds locally
merge_peer_mesh(agent_b, "a.mesh", "agent_a", policy=PeerPolicy(trust=1.0))
# corroboration fuses duplicates · consensus keeps both sides · trust cappingneural-mesh info # version, backend, embedder
neural-mesh rust-info # rust extension status + functions
neural-mesh export|import|merge | benchmark
neural-mesh sleep | consolidate | pointer-put | pointer-summary
We benchmark against flat cosine vector search (what Mem0 / vanilla vector
DBs do) on the same dense embeddings (bge-small-en) — isolating the value of
the mesh + versioning. Run them yourself in bench/.
Corpus: 12 writes, 6 of them updates of a previous fact (Maya's editor, role, city, cat status, deploy rule, language preference). 6 questions ask for the current value.
VERSIONING / CONFLICT (n=6 update-questions, 12 writes / 6 updates)
Stale (wrong) hits in top-5:
FLAT : 17/6 queries returned stale data
MESH : 0/6 queries returned stale data
Top-1 points at CURRENT fact:
FLAT : 1/6 = 16.7%
MESH : 6/6 = 100.0%
NEURAL_MESH surfaces current truth top-1 100% of the time vs 16.7% for flat —
a 6× precision gap — and leaks zero stale memories (flat leaked 17).
This is the failure mode that silently breaks production agents. Flat vectors
can't fix it; a supersedes link can.
Reproduce:
PYTHONPATH=. .venv/bin/python bench/versioning_bench.py
On a clean 27-fact synthetic set with dense embeddings, flat cosine already hits ~100% recall@5, and MESH matches it. We report this as a tie — dense embeddings are genuinely good at single-fact recall, and pretending otherwise would be dishonest. The mesh's edge is precision under conflict (above) and subgraph completeness under context budgets (measured below).
Reproduce:
PYTHONPATH=. .venv/bin/python bench/locomo_hard.py
Flat retrieval scores content overlap; it can't tell you whether the mesh is surfacing a node's connected neighborhood. This benchmark measures exactly that: for a seed node with a known set of linked neighbors (the ground-truth subgraph), what fraction of those neighbors appear in a top-k recall — and how densely the retrieved set re-forms the original graph?
Three numbers per budget k:
- subgraph_recall@k —
|retrieved ∩ linked| / |linked|: did we get the neighbors? - edge_density@k — edges within the retrieved set / max possible: did we get them connected?
- topology_score — harmonic mean of the two, a single 0–1 "does retrieval preserve the graph" signal.
Live mesh (prod snapshot 2026-08-14: 580 rows / 173 live nodes, hashed embedder, Rust resonance backend):
budget k | subgraph_recall | edge_density | topology_score
5 | 0.120 | 0.874 | 0.169
10 | 0.199 | 0.809 | 0.239
20 | 0.273 | 0.740 | 0.293
50 | 0.431 | 0.708 | 0.428
Synthetic uniform-link baseline (500 nodes, 10 clusters, same harness, seed 42):
budget k | subgraph_recall | edge_density | topology_score
5 | 0.015 | 1.000 | 0.029
10 | 0.033 | 1.000 | 0.064
20 | 0.070 | 0.998 | 0.131
50 | 0.180 | 0.965 | 0.303
Honest findings: the real mesh surfaces a seed node's linked neighborhood ~4× better than a uniform random graph at k=20 (recall 0.273 vs 0.070) and ~2.4× at k=50 — because autolink builds semantically-connected clusters, not random edges. Edge density falls as the budget grows (retrieving more nodes dilutes clustering), which is expected; topology_score rises steadily because subgraph recall grows faster than density thins. The synthetic baseline's near-perfect edge density is itself an artifact — hashed bag-of-words autolink forms one dense blob, so any retrieved set looks connected. Real-embedder (fastembed) runs should widen the recall gap further (semantic neighbors rank above lexical collisions); that is unmeasured until the LLM-judge and real-embedder goals are funded.
Reproduce (synthetic, deterministic):
PYTHONPATH=. python3 bench/subgraph_completeness.py --nodes 500 --budgets 5,10,20,50 --limit 100Reproduce (live mesh — requires the prodmesh.db):PYTHONPATH=. python3 bench/subgraph_completeness.py --db mesh.db --budgets 5,10,20,50 --limit 50
Using authentic LoCoMo-10 (snap-research, all 10 conversations: 272 memory nodes + 1542 QA queries), we score whether the gold answer string is in the retrieved top-k context (retrieval grounding — the input to an LLM answerer, not end-to-end QA accuracy). Two ingestion strategies:
- whole — each
session_summaryindexed as one node. - chunk — each summary split into sentences, indexed as many small nodes.
LOCOMO RETRIEVAL GROUNDING (full locomo10: 272 nodes, 1542 queries)
ingestion embedder recall@1 recall@3 recall@5 MRR
whole hashed → 0.043 0.093 0.139 0.064
whole real(bge) → 0.013 0.035 0.058 0.019
chunk real(bge) → 0.003 0.007 0.007 0.005
Honest findings (no spin):
- The hashed (zero-dep bag-of-words) embedder beats dense
bge-smallon this grounding proxy (0.139 vs 0.058 recall@5). That's expected — the metric is a lexical substring check, so a lexical embedder has an unfair advantage on sparse gold answers (dates, names). It is not evidence that hashed > semantic in general; it's evidence this metric is lexical. - Chunking collapses recall@5 to 0.007 because the gold answer string is fragmented across sentence nodes, so a single-node substring match fails. Whole-document retrieval artificially inflates the same metric. This is a measurement artifact, not a quality regression.
- Conclusion: this grounding proxy is dominated by lexical overlap and is the wrong yardstick for dense retrieval. The mesh's defensible win remains versioning / no-stale-truth (100% current top-1 vs 16.7% flat, zero stale leakage). Honest next step: score LoCoMo end-to-end by feeding retrieved context to an LLM judge — that's where dense vectors should pull ahead, and it's on the roadmap.
Update (2026-07-20): the end-to-end LoCoMo run is now done. See "Real LoCoMo end-to-end QA (extractive reader proxy)" below — it confirms the prediction above: dense vectors pull ahead of lexical on context recall, and the old substring-grounding proxy was indeed the wrong yardstick.
Reproduce (whole, hashed, fast):
PYTHONPATH=. python bench/locomo_eval.py --locomo locomo10.jsonReproduce (whole, real, batched):PYTHONPATH=. .venv/bin/python bench/locomo_eval.py --locomo locomo10.json --embedder real --no-autolinkReproduce (chunk, real): add--chunk(warning: ~500s on CPU)
Note (2026-07):
--embedder realrequiresfastembed(pip install fastembedin a venv). With no real embedder installed the bench silently falls back tohashed— check the printedembedder=line so you know which numbers you're looking at.
We now score LoCoMo end-to-end: for each of 1542 questions, retrieve top-k nodes, then run a model-free extractive reader proxy (pick the retrieved sentence with highest SQuAD-style token-F1 vs the gold answer; exact-match vs gold = a hard lower bound on what a real LLM reader could do). This measures "can the memory surface the answer?" — a fair, reproducible proxy that does not require a generative LLM and does not claim end-to-end QA accuracy.
FULL LOCOMO QA (real bge-small, 272 nodes, 1542 queries, top_k=5, alpha=0.9)
dense ctxR@5=0.176 ctxR@1=0.097 F1@5=0.189 EM@5=0.000 MRR(ctx)=0.124
lexical ctxR@5=0.110 ctxR@1=0.044 F1@5=0.163 EM@5=0.000 MRR(ctx)=0.067
hybrid ctxR@5=0.182 ctxR@1=0.097 F1@5=0.191 EM@5=0.000 MRR(ctx)=0.126
HDR alpha sweep (hybrid ctxR@5 / F1@5 / MRR):
alpha=0.3 → 0.145 / 0.170 / 0.088 (lexical drag, worse than dense)
alpha=0.5 → 0.163 / 0.183 / 0.111
alpha=0.7 → 0.171 / 0.188 / 0.124 (≈ dense)
alpha=0.9 → 0.182 / 0.191 / 0.126 (+3.4% over dense — best)
Retrieval-mode comparison (α=0.9, top_k=5):
mode ctxR@5 ctxR@1 F1@5 EM@5 MRR(ctx)
dense 0.176 0.097 0.189 0.000 0.124
lexical 0.110 0.044 0.163 0.000 0.067
resonance 0.037 0.015 0.120 0.000 0.023 (spreading activation)
hybrid 0.182 0.097 0.191 0.000 0.126 (best)
Honest findings:
- Dense > hybrid@low-α > lexical for context recall. Unlike the old substring-grounding proxy (where hashed lexical "won"), a semantic metric correctly ranks dense first. The retrieval-grounding section above was a lexical artifact; this section is the corrected yardstick.
- Hybrid only helps when lexical weight is small. At α=0.9 (90% dense) it edges pure dense by +3.4% recall@5; at high lexical weight it hurts. So "hybrid" is not automatically better — it needs tuning, and dense alone is a strong baseline.
- F1@5 ≈ 0.19, EM@5 = 0.000. F1 is the meaningful extractive-QA lower bound: the best single retrieved sentence captures ~19% of gold-answer tokens. EM stays 0 because LoCoMo gold answers are long/complex and rarely sit as one node sentence — an exact-match reader can't reproduce them. A real deployment needs a generative reader (local LLM). The proxy only proves the context is retrievable, which is the honest ceiling for a retriever-only system.
- Resonance (spreading activation) underperforms flat dense on LoCoMo. ctxR@5 drops to 0.037 vs 0.176 dense — ~5× worse. This is honest and expected, not a bug: LoCoMo is a single-query → single-answer benchmark. Spreading activation trades direct query-similarity for associative recall — it surfaces neighbors topologically linked to the seed, many of which are semantically unrelated to the literal question. That dilution hurts top-k answer retrieval here. Resonance's value (connecting related memories a user didn't ask about directly) is a different capability this proxy metric can't see. Flat dense remains the right tool for direct QA; resonance is for exploratory/associative recall.
- Conclusion: the defensible, reproduced wins remain (a) no-stale-truth versioning (100% current top-1 vs 16.7% flat) and (b) dense retrieval surfaces answer context ~59% more often than lexical (0.176 vs 0.110 recall@5). Proof-aware extractive answers are supported; generated local-LLM answers remain future work.
Reproduce:
PYTHONPATH=. .venv/bin/python bench/locomo_qa.py --locomo locomo10.json --embedder real --top_k 5 --alpha 0.9(alpha sweep: try 0.3/0.5/0.7/0.9; α≈0.9 maximizes hybrid on this set)
The roadmap item above ("generated local-LLM answers remain future work") is
now executed. bench/locomo_llm_judge.py feeds retrieved context to a real
generative LLM (via the Hermes/Nous-portal model path — deepseek/deepseek-v4-flash,
OpenAI-compatible inference-api.nousresearch.com/v1) and scores its one-sentence
answers against gold. This is the honest end-to-end QA that the extractive proxy
was a stand-in for.
GENERATIVE LLM JUDGE (real retrieval, 100 queries, top_k=5, model=deepseek-v4-flash)
mode ctxR@5 EM@5 F1@5 MRR
dense 0.150 0.000 0.019 0.075 (smoke, n=20)
hybrid 0.120 0.000 0.041 0.068 (bounded run, n=100)
Honest findings:
- The pipeline is unblocked and measured. A real generative LLM now judges mesh answers on reproduced LoCoMo data via the Nous-portal model path. This closes the "future work" item and the earlier credit-gate: no OpenRouter / Anthropic / xAI balance needed.
- F1@5 ≈ 0.04 is low, and we won't spin it. This is expected for the setup: the reader gets a 5 × 800-char context window against long, multi-fact LoCoMo gold answers. It is a retrieval-ceiling measurement, not a claim of QA accuracy. ctxR@5 (~0.12–0.15) shows the answer text is surfaced in context about 1 in 7 queries, but the generative reader rarely reproduces the full gold sentence → EM stays 0 and F1 stays low.
- What this proves: end-to-end QA is now runnable and reproducible on this engine, and the numbers are real (no fabricated judge output). The next lever is the reader itself — larger context window + multi-pass answer synthesis — which is a reader-side improvement, not a mesh-retrieval one.
Reproduce:
OPENROUTER_API_KEY=<nous access_token> PYTHONPATH=. .venv/bin/python bench/locomo_llm_judge.py --locomo locomo10.json --limit 100 --model deepseek/deepseek-v4-flash --mode hybrid
We run the canonical LongMemEval (500-case long-term conversational memory)
harness in bench/longmemeval_harness.py: ingest every haystack message as an
episodic node, retrieve top-k, score retrieval (MRR / contextRecall) and an
optional LLM judge.
RETRIEVAL MODE SWEEP (real bge-small embedder, n=20 temporal-reasoning cases)
mode MRR cr@1 cr@5
hybrid 0.260 0.250 0.160 ← now the Mesh DEFAULT recall()
dense 0.238 0.200 0.160
resonance 0.238 0.200 0.160
lexical 0.225 0.200 0.130
FULL-100 (dense, real embedder, biased cases[:100] prefix, lexical ctxRecall):
MRR=0.161 cr@1=0.090 cr@5=0.112 (BIASED SLICE — not representative)
REPRESENTATIVE-100, SAME stratified sample, v4-flash judge — MODE COMPARISON:
mode MRR cr@1 cr@5 JudgeF1 EM n
hybrid 0.283 0.210 0.142 0.347 0.250 100/100
dense 0.277 0.210 0.150 0.362 0.260 100/100
paired (same 100 cases): ΔMRR=+0.006 ΔF1=−0.016 (hybrid wins 16 / ties 70 / loses 14)
Honest findings:
- Hybrid ≈ dense — a TIE at scale, not a win. The 20-case sweep hinted
hybrid +0.02 MRR, but on the same stratified 100-sample the gap collapses to
+0.006 MRR (noise) and dense is marginally better on Judge F1
(0.362 vs 0.347) and EM. Per-case: hybrid wins 16, ties 70, loses 14.
Mesh()still defaults tohybrid(v0.28.1) but that is NOT justified by retrieval quality — it is a coin-flip that is also ~33% slower per the sweep timing. Recommendation: revert the default todense(equal quality, faster). This is a pending product call, flagged honestly rather than hidden. - The honest ceiling is retrieval recall, not the judge. Both modes land at MRR ~0.28 / cr@1 ~0.21 — the right memory node is in the top-5 ~28% of the time. No judge model can score well on context it never retrieves. That is the real gap to attack (chunking, query rewriting, cross-session linkage), independent of which LLM grades the answer.
- The earlier dense MRR 0.161 is a BIASED reference, not a clean baseline.
It used
dataset[:100]which is 100%temporal-reasoningand skewed easy. Kept only as a labeled historical data point. The trustworthy comparison is the stratified 100-sample above (hybrid ≈ dense). The n=20 sweep is the only same-cases mode ranking and is now shown to be small-sample noise. - LLM-judge F1 IS a trustworthy number (v4-flash). The free
tencent/hy3:freejudge was rejected (0/10 empty-good but ~50% rambling meta-text → unusable).deepseek/deepseek-v4-flashvia the Nous path is the reliable free judge (same model the LoCoMo judge used): on the representative 100-sample it answered 100/100 with Judge F1 ≈ 0.35, EM ≈ 0.25, MRR ≈ 0.28 for both modes. Per-category F1 (hybrid): single-session-user 0.72, knowledge-update 0.42, temporal-reasoning 0.30, single-session-assistant 0.29, multi-session 0.25, single-session-preference 0.05. Temporal + preference are the weak spots — consistent with LongMemEval's known difficulty (multi-hop time reasoning, fine-grained preference), and the next retrieval targets.
Reproduce:
PYTHONPATH=. .venv/bin/python bench/longmemeval_harness.py --embedder real --top_k 5 --limit 100· representative sample:bench/sample_representative.py --n 100 --seed 7· judged run:NOUS_JUDGE_MODEL=deepseek/deepseek-v4-flash PYTHONPATH=. .venv/bin/python bench/longmemeval_harness.py --embedder real --mode {hybrid|dense} --judge --limit 100 --dataset data/longmemeval_oracle_sample100.json
LoCoMo is a single-query → single-answer task, so flat dense wins there (resonance ctxR@5 0.037 vs hybrid 0.182). But resonance/spreading activation has a real niche flat dense cannot touch: path-dependent recall — the answer is reachable only by walking a chain of links, with no lexical/semantic bridge from the query.
bench/associative_qa.py builds meshes where the target shares zero tokens with
the query and is connected only through a 3-hop link chain. We add enough
higher-overlap distractors that flat dense's top-5 is forced to exclude the
target, then show the associative walk still reaches it.
ASSOCIATIVE RECALL (hashed embedder, deterministic, 3 cases)
Q: what color is the living room couch
dense : miss (target shares 0 query tokens; ranked out of top-5)
resonance : reached walk-rank=7 -> SURFACED a target dense MISSED
Q: tell me about the researcher Mira
dense : miss (answer is only link-reachable)
resonance : reached walk-rank=4 -> SURFACED a target dense MISSED
Q: what is the deploy region
dense : HIT rank=1 (control: dense legitimately wins)
resonance : reached walk-rank=1 (and resonance also finds it)
path-dependent resonance-only reaches: 2 / 2
Honest framing: the 2 "resonance wins" cases are engineered to isolate the capability (target reachable only via links). The 3rd case is a control where dense legitimately wins and is included precisely to avoid overclaiming. Real corpora are mixed; the point is that resonance provides a retrieval mode flat dense structurally cannot, and the benchmark proves it on a measurable, reproducible case rather than asserting it as philosophy.
Reproduce:
PYTHONPATH=. python3 bench/associative_qa.py
- 🟦
by(Feature A) — everyMemoryNodecarries a first-classbyauthor field.Mesh.add(..., by=...)defaults it fromagent_id→provenance→"self". It persists in the SQLite row and round-trips through.meshexport. This is the literal "remember is by" — you always know who/what authored a memory, not just when. - 🟦 DREAM (Feature C) — an explicit, inspectable consolidation cycle (
neural_mesh/dream.py) with 5 phases:- Drift — age-based resonance decay
- Reinforce — Hebbian link-strengthening for co-retrieved neighbors
- Evaluate — attribution-weighted trust: a Helixa-verified high-aura author gets
author_weight = trust * (0.5 + 0.5 * aura); an unverified claim is discounted (* 0.6); folded intonode.meta["author_weight"] - Archive — prune low-resonance/low-trust/old nodes
- Muse — reflect surviving clusters into new insight nodes minted
by="dream", which then participate in later retrieval (the mesh grows memories about its own memories)
- 🟦 Reader swap-point (Feature D) —
neural_mesh/reader.pydefines aReaderinterface.ExtractedReaderis the model-free extractive proxy (default, used bybench/locomo_qa.py).CallableReader(fn)is the drop-in for a real local LLM: passfn(query, context) -> answerand generated answers become real with zero changes to the retrieval/benchmark code.
from neural_mesh import Mesh, dream
from neural_mesh.reader import CallableReader
m = Mesh()
# ... add memories ...
rep = dream(m, muse_fn=lambda survivors: [f"synthesis: {s.content[:40]}" for s in survivors[:1]])
# rep -> {"drifted", "reinforced", "archived", "author_boosted", "insights"}
# real generated answers once you have a local model:
reader = CallableReader(lambda q, ctx: my_local_llm(q, ctx))
print(reader.answer("who is Cody?", [n.content for n in m.recall("Cody")]))Reproduce DREAM + associative:
PYTHONPATH=. python3 bench/associative_qa.pyTests:PYTHONPATH=. python3 -m unittest tests.test_core(33 passing, incl.TestProvenanceBy,TestReaderInterface,TestDreamCycle,TestAssociativeRecall)
Export/import the whole graph (nodes + typed links + version history) to a single
JSONL file. Embeddings are not stored — they're embedder-specific — so a
.mesh file is portable across agents/models: the importer re-derives vectors
with its own embedder. Verified round-trip: 4 nodes + 6 edges + versioning
survive an export→import into a fresh mesh.
from neural_mesh import Mesh, export_mesh, import_mesh
export_mesh(mesh, "agent.mesh")
other = Mesh(":memory:"); import_mesh("agent.mesh", other) # re-embeds for other's modelReproduce:
PYTHONPATH=. python -c "from neural_mesh import *; ..."(round-trip verified in CI-less local run)
Agents can pool memory via the .mesh format, but naive pooling is dangerous —
duplicate facts, contradictory facts, and untrusted sources. NEURAL_MESH sharing
rests on three primitives (see neural_mesh/sharing.py):
- 🟦 Corroboration — identical facts from two agents fuse: trust rises by
1 - (1-t_a)(1-t_b)and the link set unions. No duplicates. - 🟦 Consensus — contradictory facts sharing a
conflict_groupare not overwritten; the highest-trust claim wins and the loser is retained-but-demoted (visible, never silently dropped). - 🟦 Trust capping — a per-peer
PeerPolicyscales/caps incoming trust, so an untrusted peer can't override local truth.
from neural_mesh import Mesh, merge_peer_mesh, PeerPolicy, export_for_peer
export_for_peer(agent_a, "a.mesh", "agent_a")
merge_peer_mesh(agent_b, "a.mesh", "agent_a", policy=PeerPolicy(trust=1.0))Bench result (reproducible): corroboration fused 1→1 node (trust 0.7→0.94); consensus kept both contradictors and surfaced the 0.9-trust claim over 0.4; trust capping pulled an untrusted peer's 1.0 down to 0.2.
Reproduce:
PYTHONPATH=. python bench/sharing_bench.pyLive demo:PYTHONPATH=. python -m neural_mesh.cross_agent_demo
After sleep consolidation, the mesh is curated truth (stale pruned, high-trust
kept, consensus resolved). That curated set is exactly the clean, high-signal
(instruction, response) data a LoRA adapter wants — instead of finetuning on
raw noisy logs, you finetune on the agent's consolidated memory.
mesh.sleep() # prune + reflect
ds = mesh.distill(min_trust=0.6) # -> {pairs, jsonl}
write_hf_jsonl(mesh, "lora.jsonl") # Alpaca-style for PEFT- high-trust + high-resonance live nodes become training pairs
- corroborated (
agent_idhas+) get a bonus weight so the adapter learns agreed-upon truth stronger than single-agent claims - outputs: native JSONL (with
weight+meta), Alpaca/HFjsonl, and a per-example weight-TAB-separated file for sample-weighted trainers
Bench result (reproducible): 3 examples from a 5-node mesh; stale + low-trust
nodes excluded; corroborated weight 1.188 > single-agent 0.9; both JSONL
formats parse and validate.
Reproduce:
PYTHONPATH=. python bench/distill_bench.py
D0xedDev's agent identity is anchored on Helixa (agentId 59322) on Base L2;
its Aura is on-chain reputation. A .mesh file shared between agents should
carry who vouched and how trustworthy that voucher is. That's what
neural_mesh/integrations/helixa_provenance.py does — as a metadata layer only:
- 🟦
HelixaStamp—{ agent_id, aura_score, vouched_at, source, signature, tx_hash, verified }, stored onnode.metaso it survives.meshexport. - 🟦
stamp_node()/export_manifest()— attach stamps and produce a human-reviewable manifest before any on-chain step. - 🟦
aura_trust_weight()— unverified stamps are capped at 0.2 so an unverified voucher can't dominate trusted local memory.
Safety contract (read this): this module never signs a transaction,
never broadcasts to a chain, never calls a Helixa write endpoint, and
never stores a private key. All "on-chain" effects are gated behind an
externally-supplied signature / verification result (e.g. the D0xedDev
/helixa-signer flow). Signing stays a separate, key-held, human-approved step.
Reproduce:
PYTHONPATH=. python -m unittest tests.test_core(3 Helixa tests)
template_muse(default) — zero-dep rule-based engine: clusters survivors by provenance, extracts top terms, synthesizes per-cluster summaries + a cross-cluster bridge node + a resonance leaderboard.llm_muse— calls an LLM (OpenRouter, OpenAI, or any OpenAI-compatible endpoint) to synthesize insights from survivors. Falls back to template if the API key is absent or the call fails.- 🟦 Proof cards — recalled memories can carry tx/term/block evidence next to claims (
/mesh/recall-proof,/mesh/answer-proof), andLLMReadersynthesizes answers from retrieved context with citations.
Live deployment (D0xedDev VPS): 198 nodes · DREAM cron every 12h with template muse · resonance_backend: rust · benchmarks re-verified.
Real cognitive type (episodic future thinking / intentions) that almost no
shipped memory engine handles: they store the PAST. Mesh.add(..., prospective_at=ts)
writes an intention; this module surfaces it before it's due.
from neural_mesh import upcoming, due_rank, snooze, expired
now = time.time()
mesh.add("Follow up with Maya about Acme", type=MemoryType.PROSPECTIVE,
prospective_at=now + 300, trust=0.9)
due = upcoming(mesh, now=now, horizon_sec=3600) # -> the follow-up
ranked = due_rank(mesh, now=now, k=5) # proximity × trust
snooze(mesh, node.id, now + 86400) # push it outMost systems treat working memory as a retrieval problem. This treats it as a budget problem: a fixed context cap, with priority eviction.
from neural_mesh import select_fit, fit_summary
kept, evicted = select_fit(nodes, budget=60) # highest-value fit
fit_summary(kept, evicted) # kept/evicted counts + tokensEviction is non-destructive — dropped memories stay in the mesh as cold memory, just out of the active window. This is the missing half of a working- memory lane.
Reproduce all six lanes:
PYTHONPATH=. python3 bench/five_lane_demo.py→runtime/five_lane_evidence.json→bench/render_five_lane_figure.py→docs/assets/five_lane_evidence.png.
| File | Role |
|---|---|
neural_mesh/node.py |
Memory-node schema: type, lane, provenance, trust, decay, links |
neural_mesh/embed.py |
Embedding abstraction + zero-dep hashed fallback |
neural_mesh/embed_real.py |
Optional real embedder (fastembed, no torch) |
neural_mesh/core.py |
Mesh orchestrator: store, auto-link, recall, sleep, version |
neural_mesh/resonance.py |
Spreading-activation retrieval (auto/rust/python backends) |
neural_mesh/pointer.py |
Big-output → mesh:// pointer protocol |
neural_mesh/dream.py |
DREAM consolidation cycle (drift/reinforce/evaluate/archive/muse) |
neural_mesh/reader.py |
Reader interface: extractive proxy + callable LLM swap-point |
neural_mesh/sharing.py |
Corroboration, consensus, PeerPolicy trust capping |
neural_mesh/demo.py |
End-to-end live demo |
neural_mesh/integrations/helixa_provenance.py |
Helixa/Aura provenance (off-chain, review-gated) |
rust_mesh/ |
Optional Rust/PyO3 accelerator (abi3 — one .so, Python ≥ 3.9) |
bench/ |
Reproducible benchmarks (versioning, locomo, sharing, distill, rust) |
docs/assets/ |
This README's animated SVGs + pixel art |
- Five-type memory + mesh auto-linking
- Resonance retrieval (seed + spread + decay)
- Hot/cold lanes + sleep (prune + reflect)
- Pointer protocol (keep big output out of context)
- Versioning /
supersedes(no stale truth) -
.meshportable interchange format - Cross-agent mesh sharing + consensus
- Real LoCoMo eval harness (full locomo10: 272 nodes / 1542 queries)
- LoRA-ready sleep distillation (consolidated-memory finetune data)
- Bulk ingest
add_many(batched embedding for big corpora) - Helixa / Agent Aura provenance scaffold (off-chain, review-gated)
- Intuition mainnet receipt ingestion — atoms/triples become high-trust recallable mesh memories
- Proof-aware recall cards — recalled memories can carry tx/term/block evidence next to claims
- Proof-aware answer mode — answers return supporting proof cards and compact citations
- Flask/API hardening — optional bearer auth, path allowlists, rate limits, JSON cap, locked CORS, safe dashboard escaping
- Ask-the-Mesh dashboard panel — local UI calls
/mesh/answer-proofand renders proof cards safely - LLM-powered answer synthesis —
LLMReadercalls OpenRouter to synthesize answers from retrieved context - Helixa on-chain attestation gateway — sign locally via injectable fn, broadcast optionally, never expose key
- npm dependency audit resolved — lodash override (4.18.1) drops 6 high vulns to 0
- LoCoMo QA evaluation — LLM judge scores mesh answers against ground truth with
/eval/qa - End-to-end LoCoMo QA (generative LLM judge via Hermes/Nous model path) — measured 2026-08-17
- Rust hot path for large meshes — exact-parity query scoring + weighted activation spread
- Subgraph-completeness benchmark under context budgets — topology_score (subgraph_recall × edge_density)
- Prospective memory lane — the "memory of the future": intentions surface before due (
upcoming/due_rank), re-future viasnooze, expired tracking - Working-memory token-budget optimizer — context as a budget problem: greedy value-density fit, non-destructive priority eviction (
select_fit) - Live Helixa signing (on-chain attestation) — gated behind human GO + key-held signer
🟦 Resonance query scoring now uses an optional Rust/PyO3 hot path while retaining
the pure-stdlib Python backend as an automatic fallback. Pin either path with
Mesh(..., resonance_backend="rust"|"python"|"auto").
🟦 The Rust extension implements the mesh's exact dot-similarity contract and weighted max-propagation activation semantics; parity tests guarantee identical ranked hits instead of trading correctness for speed.
🟦 End-to-end synthetic retrieval at 5,000 nodes / 20,000 edges / 256 dimensions:
107.9 ms Python → 66.2 ms Rust (1.63× faster) with exact top-10 parity.
Reproduce with PYTHONPATH=. python3 bench/rust_resonance_bench.py --nodes 5000 --repeats 7.
🟦 /health reports the active resonance_backend; deployments can pin it with
NEURAL_MESH_RESONANCE_BACKEND for transparent operations and rollback.
🟦 Rust extension builds with abi3 — one .so runs on any Python ≥ 3.9
(dev 3.13, prod VPS 3.12 — no rebuilds, no libpython coupling).
🟦 All retrieval modes now accept lane="hot"|"cold"|None; resonance spreading
is restricted to the selected subgraph so filtered recall cannot leak across lanes.
🟦 Bulk ingestion now defaults to the hot lane, matching single-node ingestion.
🟦 MemoryLifecycle.maintain(mode="sleep"|"dream") provides one lane-first
orchestration contract while preserving both lightweight SLEEP and enriched DREAM.
🟦 Added authenticated REST operations: /mesh/sleep, /mesh/consolidate,
/mesh/pointer, and bounded /mesh/pointer/summary. Raw pointer resolution is
intentionally not exposed over HTTP.
🟦 Added CLI commands: sleep, consolidate, pointer-put, and
pointer-summary; pointer primitives are now exported at package root.
🟦 MemoryLifecycle composes pointer-safe ingest, routed fact/associative recall,
hot/cold consolidation, and sleep into one inspectable cycle.
🟦 POST /mesh/cycle exposes the full workflow over REST and serializes compact
memory hits instead of raw payloads.
🟦 Oversized payloads are externalized automatically; searchable nodes retain a
preview, mesh:// pointer, payload size, provenance, and trust.
🟦 Fact lookup defaults to dense-heavy hybrid retrieval while associative mode uses resonance spreading, matching each primitive to the task it measures well.
🟦 Fixed /mesh/add silently ignoring the requested memory type because it passed
memory_type= into Mesh.add(**extra_meta) instead of the real type= parameter.
🚀 Cross-Agent Mesh Sharing — .mesh is now a public protocol:
export_mesh(mesh, path)→ portable JSONL file with schema versioning + embedder fingerprintimport_mesh(path, mesh)→ load from any agent, auto re-embed with local embeddermerge_peer_mesh(local, peer_file, policy)→ trust-weighted fusion: same fact from two agents = corroborated trustconsensus_rank(nodes)→ highest-trust claim wins, contradictors annotated never droppedPeerPolicy(trust, cap_trust, allow_new, allow_merge)→ per-peer trust controls- 17 new tests (meshfile + sharing) — zero new deps
📦 Package & Ship — pip install neural-mesh now works:
pyproject.tomlwith[project.optional-dependencies]for embeddings / onchainneural-meshCLI:export,import,merge,benchmark,info,rust-info- Pure-stdlib core stays pip-free;
eth-accountetc. lazy-loaded
⚡ Rust Graph Accelerator — optional rust_mesh extension (pyo3):
cosine_similarity+bulk_cosine_similarity— vector opsGraphwithbfs,associative_recall,shortest_path(Dijkstra)- Benchmarks (50K nodes / 500K edges): 16–17x speedup on resonance-critical ops
- Drop
rust_mesh.sonext toneural_mesh/to activate; zero changes to Python API
🏛️ Intuition Bridge — IntuitionDeploymentReceipt + IntuitionTripleReceipt for onchain knowledge-graph attestation.
The DREAM cycle now generates real insights via a pluggable muse engine. See
the feature deep-dive above for template_muse / llm_muse, the Flask REST
server, and hardening details.
This started as a fork-shaped idea off NousResearch/hermes-agent and the
Sibyl / Tony-Simons memory practices. PRs welcome — especially on .mesh,
cross-agent consensus, the LoCoMo eval, and the Rust hot path. Keep the core
pip-free; real embedders stay optional. If you're an agent reading this: start
with AGENTS.md.
MIT. Build the future of agent memory in the open. 🟦