hermes - 💡(How to fix) Fix Feature Idea: SQLite FTS5 + Obsidian Wiki Memory Tree (inspired by OpenHuman)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

Result: With 100+ facts, the context window gets polluted, and the model "forgets" older topics after a few turns. We traced this to the root cause — full dump, no retrieval.

Code Example

Layer 1: SQLite FTS5 (sticky notes)
  ↕  lightweight pointers only,100 chars each
Layer 2: Obsidian Wiki (the notebook)
  ↕  detailed notes, auto-synced from fact_store
Layer 3: Session History (the diary)
  ↕  date-indexed, retrieved by session_search

---

# ~/.hermes/scripts/memory_retrieve.py
import sqlite3, sys
DB = Path.home() / ".hermes" / "memory_store.db"

def search(query: str, limit: int = 5):
    conn = sqlite3.connect(str(DB))
    results = conn.execute("""
        SELECT f.fact_id, f.content, f.trust_score, ff.rank
        FROM facts f
        JOIN facts_fts ff ON f.fact_id = ff.rowid
        WHERE facts_fts MATCH ? AND f.trust_score >= 0.2
        ORDER BY ff.rank, f.trust_score DESC
        LIMIT ?
    """, (query, limit)).fetchall()
    return results

---

# ~/.hermes/scripts/sync_to_obsidian.py
# Reads memory_store.db → writes markdown to Obsidian Vault
# Organized by category: 项目知识/ 老板偏好/ 工具技巧/ 综合记忆
# Cron: daily at 09:00 UTC

---

# ~/.hermes/scripts/memory_lifecycle.py
# Runs daily at 03:00 UTC
# - 7 days unused → trust_score -5%/day
# - 30 days unused → archive to Obsidian, delete from SQLite
# - Over 100 facts → remove lowest trust_score
# - Topic mentioned → boost trust +15%
RAW_BUFFERClick to expand / collapse

Feature Idea: SQLite + Obsidian Wiki Memory Tree (Inspired by OpenHuman)

by Jordi Nor & 小青 | 2026-05-25

The Problem

Hermes Agent has two memory layers:

LayerCapacityLimitation
fact_storeUnlimited❌ ALL facts injected into context every turn → attention pollution
MEMORY.md2,200 chars❌ Tiny, forces constant consolidation

Result: With 100+ facts, the context window gets polluted, and the model "forgets" older topics after a few turns. We traced this to the root cause — full dump, no retrieval.

What We Built (Inspired by OpenHuman's Memory Tree)

A three-layer architecture that mirrors how humans use sticky notes:

Layer 1: SQLite FTS5 (sticky notes)
  ↕  lightweight pointers only, ≤100 chars each
Layer 2: Obsidian Wiki (the notebook)
  ↕  detailed notes, auto-synced from fact_store
Layer 3: Session History (the diary)
  ↕  date-indexed, retrieved by session_search

Layer 1 — SQLite FTS5 Retrieval Engine

Instead of dumping all facts into context, we query SQLite on-demand:

# ~/.hermes/scripts/memory_retrieve.py
import sqlite3, sys
DB = Path.home() / ".hermes" / "memory_store.db"

def search(query: str, limit: int = 5):
    conn = sqlite3.connect(str(DB))
    results = conn.execute("""
        SELECT f.fact_id, f.content, f.trust_score, ff.rank
        FROM facts f
        JOIN facts_fts ff ON f.fact_id = ff.rowid
        WHERE facts_fts MATCH ? AND f.trust_score >= 0.2
        ORDER BY ff.rank, f.trust_score DESC
        LIMIT ?
    """, (query, limit)).fetchall()
    return results

Result: "YOLLGO" → 1 hit (trust 0.8), not 139 dumped. Context stays clean.

Layer 2 — Obsidian Wiki (Daily Auto-Sync)

# ~/.hermes/scripts/sync_to_obsidian.py
# Reads memory_store.db → writes markdown to Obsidian Vault
# Organized by category: 项目知识/ 老板偏好/ 工具技巧/ 综合记忆
# Cron: daily at 09:00 UTC

All facts are human-readable, searchable, and editable in Obsidian. No more black-box SQLite.

Layer 3 — Date-Indexed Session Diary

fact_store sticky note only stores: 📌 YOLLGO — 讨论于 2026-05-22~25

When the topic resurfaces → search SQLite → find date → session_search by date → full chat history restored.

The Cleanup: Automatic Memory Decay

# ~/.hermes/scripts/memory_lifecycle.py
# Runs daily at 03:00 UTC
# - 7 days unused → trust_score -5%/day
# - 30 days unused → archive to Obsidian, delete from SQLite
# - Over 100 facts → remove lowest trust_score
# - Topic mentioned → boost trust +15%

This mimics human memory: things you use stay fresh, things you forget fade away.

Real Results

MetricBeforeAfter
Facts in context139 (full dump)~5 (on-demand)
Bloated facts (>150 chars)69 (50%)0
Lightweight pointers42 (30%)111 (80%)
Retrieval precisionN/A (dump)FTS5 exact match
Context freed0%~90% for actual conversation

Integration Ideas for Hermes Core

  1. Add FTS5 retrieval as a fact_store optionfact_store(action="search", query="keyword") already exists but isn't the default behavior. Making on-demand retrieval the default would fix the context pollution at the framework level.

  2. Obsidian sync as a built-in feature — Hermes could ship with an optional Obsidian Vault sync, turning the memory store into a human-readable knowledge base.

  3. Memory decay as native behavior — Automatic trust decay + archiving would keep fact_store lean without manual cleanup.


Built by Jordi Nor & 小青 — Hermes Agent power users. Happy to contribute code if there's interest!

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix Feature Idea: SQLite FTS5 + Obsidian Wiki Memory Tree (inspired by OpenHuman)