| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Hermes current-turn memory provider with permanent semantic recall, nightly workflow digest, SQLite truth storage, and a LanceDB vector companion
Give Hermes durable memory that can follow the same user across windows/chats while keeping local scratch context from bleeding into the wrong place.
Current-turn recall · Permanent shared memory · Nightly workflow digest · Local scratch scopes · SQLite truth · LanceDB companion · Hybrid retrieval
scope-recall is a Hermes local memory provider built for current-turn recall and permanent semantic memory. Durable user/project/ops/memory facts are shared across windows/chats for the same user + agent identity; raw general turn captures stay local to the current chat/thread/session.
Version 1.0.8 continues the first stable V1 release line for the documented interfaces, packaged as a public release candidate for broader field testing. It keeps the V1 compatibility contract in docs/stability.md while adding a deterministic Chinese entity fallback for no-Jieba CI/runtime environments and documenting the external shared-memory integration boundary without storing raw system/tool output.
It uses a two-layer design:
This replaces the old lancepro naming, which was misleading because the earlier implementation was SQLite-only.
scope-recall is the local per-Hermes recall layer. In multi-agent deployments that already run a central shared backend such as PostgreSQL, keep that backend as the cross-agent source of truth and connect it to scope-recall through explicit import/export/tool boundaries.
The V1 shape is intentionally simple:
For external shared-memory bridge guidance, see docs/external-shared-memory.md.
Most agent memory pain is not just "wrong memory was recalled". The bigger user-facing failure is often "the agent forgot everything when I opened a new window." scope-recall therefore separates durable facts from local scratch context:
scope-recall is built around a simple rule:
Recall the relevant durable memory for the current query, while keeping local scratch context inside the current runtime scope.
You: "For this memory-provider project, SQLite is the source of truth."
(later, in another window/chat)
Agent: "I don't have that context here." ❌
You: "What did we decide for this Hermes memory provider?"
Agent: recalls the durable project memory from SQLite truth/LanceDB companion and answers from the relevant context. ✅
Group A: "Temporary note: restart this group's test bot only."
(later, in Group B)
Agent: applies Group A's temporary note in Group B. ❌
scope-recall keeps that temporary general scratch row local while still sharing durable user/memory/project/ops facts.
| Area | What scope-recall V1 provides |
|---|---|
| Current-turn recall | prefetch(query) retrieves against the active user query; queue_prefetch() is intentionally a no-op |
| Storage authority | SQLite is the durable truth; LanceDB is rebuildable companion state |
| Hybrid retrieval | SQLite lexical/FTS candidates + LanceDB semantic candidates + bounded prompt rendering |
| Entity/context layer | SQLite entity index, entity probe/related tools, compact query context, trust feedback |
| Nightly digest | Profile-scoped daily consolidation for durable facts, workflow summaries, and sanitized tool-chain evidence |
| Memory scope model | shared durable scope for user/project/ops/memory facts; local scope for general scratch captures |
| Built-in memory integration | Hermes curated USER.md / MEMORY.md are live-read, not mirrored into SQLite. In gateway contexts with an explicit user_id, curated-file recall is opt-in/allowlisted to avoid cross-user leakage from global profile files. |
| Governance | deterministic exact dedupe, conservative near-duplicate merge, filtering, metadata, decay review |
| Migration | local lancepro auto-migration; OpenClaw memory-lancedb-pro import is explicit |
| Offline bootstrap | deterministic local-hash fallback when hosted embeddings are unavailable |
scope-recall works as a standalone Hermes memory provider. You can install only this plugin and get scoped current-turn recall, SQLite truth storage, LanceDB companion retrieval, and local scratch isolation.
For stricter post-turn knowledge governance, pair it with turn-closure-audit.
The two plugins solve adjacent problems:
| Plugin | Role |
|---|---|
| scope-recall | decides what memory should be recalled for the current turn |
| turn-closure-audit | audits a completed turn and writes redacted review candidates when important knowledge may not have been retained |
This pairing is useful for long-lived Hermes agents where you want both scoped recall during a conversation and conservative review after the turn ends. It is optional, not a runtime dependency.
cd "$HERMES_HOME/plugins"
git clone https://github.com/410979729/scope-recall.git scope-recall
cd scope-recall
python -m pip install -e .Then configure Hermes to use the provider name:
memory:
provider: scope-recallFor a local smoke check after installation:
hermes memory statusCurrent Hermes plugin discovery expects an unpacked plugin directory. scope-recall V1 targets the current Hermes runtime line, which requires Python 3.11 or newer. If you download a release archive instead of cloning:
Important boundary:
The shipped config.json defaults to hybrid retrieval with a hosted OpenAI-compatible Gemini embedding path and a deterministic offline fallback.
Minimal default shape:
{
"auto_recall": true,
"auto_capture": true,
"enable_tools": true,
"maintenance_tools_enabled": false,
"retrieval": {
"mode": "hybrid",
"lexical_weight": 0.45,
"vector_weight": 0.55,
"candidate_pool": 12
},
"vector": {
"enabled": true,
"backend": "lancedb",
"sync_mode": "incremental",
"embedder": {
"provider": "openai-compatible",
"model": "gemini-embedding-001",
"dimensions": 3072,
"api_key_env": ["SCOPE_RECALL_GEMINI_EMBEDDING_API_KEY"],
"base_url": "https://generativelanguage.googleapis.com/v1beta/openai"
},
"fallback_embedder": {
"provider": "local-hash",
"dimensions": 256,
"model": "hash-v1"
}
}
}Credential rule:
Currently implemented:
| Provider | Use case | Notes |
|---|---|---|
| openai-compatible | Gemini/OpenAI-compatible embedding APIs | Default configured path; supports env-based API key lookup |
| openai | Direct OpenAI embeddings | Useful when you do not need a custom compatible endpoint |
| sentence-transformers | Local Hugging Face / SentenceTransformers models | Good for local semantic embeddings when installed |
| local-hash | Offline fallback | Deterministic degraded fallback, not a true semantic model |
| local-debug | Tests/debugging | Tiny deterministic test embedder |
Provider aliases local-model, local-embedding, and huggingface resolve to the sentence-transformers backend.
scope-recall does not split all memory by every group or tiny window. It uses two provider-owned scopes:
This aims at the common expectation: "if I gave the agent durable information before, it should remember it later," without making every scratch line globally visible forever.
When scope-recall is active, Hermes memory has two intentional authority zones:
| Layer | Storage | Purpose | How recall sees it |
|---|---|---|---|
| Hermes curated memory | $HERMES_HOME/memories/USER.md, $HERMES_HOME/memories/MEMORY.md | User profile and durable hand-curated notes managed by Hermes built-in memory | Live-read during recall; not mirrored into SQLite; gateway user_id contexts require curated-memory opt-in/allowlist |
| Scope Recall provider memory | $HERMES_HOME/scope-recall/memory.sqlite3 + $HERMES_HOME/scope-recall/lancedb/ | Provider-owned shared durable memories plus local scratch captures, scope metadata, lexical/vector retrieval | SQLite truth + optional LanceDB companion ranking |
Key principle:
SQLite is the truth source for provider-owned rows. Hermes curated memory files remain their own truth source. LanceDB is a rebuildable retrieval companion, not the authority.
This is deliberate. Mirroring curated memory writes into SQLite can leave stale duplicates after replace/remove operations. Live-reading curated memory keeps Scope Recall aligned with Hermes native memory behavior. Because those curated files are profile-global, live-read recall defaults to single-user: it is active for single-user/no-user_id runtimes and disabled for explicit gateway user_id contexts unless curated_memory.mode is set to profile-global or explicit-users with matching allowed_user_ids.
Under the active Hermes profile:
Legacy lancepro storage is migrated forward on first initialization when present.
Hermes turn
|
| current query
v
prefetch(query)
|
+--> live curated memory read
| - $HERMES_HOME/memories/USER.md
| - $HERMES_HOME/memories/MEMORY.md
|
+--> SQLite truth lookup / FTS
| - provider-owned memory rows
| - scope metadata
| - timestamps and governance metadata
|
+--> LanceDB vector companion
| - semantic candidate retrieval
| - rebuildable from SQLite truth
|
v
hybrid scoring + recency-aware ranking + bounded prompt block
| File | Purpose |
|---|---|
| __init__.py | Hermes plugin entrypoint; exposes register() lazily |
| provider.py | Provider lifecycle and Hermes hook integration |
| config.py | Runtime config loading/defaults |
| scope.py | Runtime scope construction and isolation keys |
| sql_store.py | SQLite schema, migrations, truth-row CRUD, FTS |
| vector_store.py | LanceDB companion table sync/search/repair primitives |
| vector_runtime.py | Vector runtime status and degradation handling |
| recall.py | Lexical/vector/hybrid recall orchestration |
| scoring.py | Score fusion, freshness boosts, capping logic |
| gating.py | Recall/capture gating and noise filtering |
| capture.py | Auto-capture pipeline |
| governance.py | Deterministic dedupe, metadata, decay/governance review |
| memory_ops.py | Store/search/forget/update/dedupe/merge/export/govern operations |
| tooling.py | Provider tool dispatch |
| schemas.py | Hermes tool schemas |
| migration.py | Legacy lancepro migration helpers |
| nightly_digest.py | Daily conversation digest pipeline, LLM/heuristic extraction, semantic write decisions |
| scripts/import.openclaw.memory_lancedb_pro.py | Explicit OpenClaw history importer |
| scripts/nightly-digest.py | CLI wrapper for the profile-scoped daily digest |
| scripts/repair.vector_index.py | Rebuild/repair LanceDB from SQLite truth |
| scripts/check.release.py | Full V1 release gate used locally and by CI |
SQLite is the authoritative provider-owned store.
It keeps:
Why SQLite stays authoritative:
LanceDB is a companion retrieval index, not the truth source.
It stores retrieval-ready fields copied from SQLite plus a vector column:
Configured default embedder targets the Gemini OpenAI-compatible embeddings API:
Runtime fallback remains available:
scripts/nightly-digest.py is a plugin-owned batch path for daily memory consolidation. It reads the profile's active Hermes state.db first, falls back to legacy lcm.db, and scans the selected local date by message timestamps. Raw system rows and raw tool outputs are not stored. For task sessions, the digest keeps a sanitized tool-chain summary so repeated engineering workflows can be recalled later as workflow memory.
Typical smoke run:
python scripts/nightly-digest.py --hermes-home "$HERMES_HOME" --date 2026-06-01 --dry-run --extractor heuristic --verboseProduction runs default to the LLM extractor. The script reads model/base URL/API key information from the Hermes profile config and .env, with SCOPE_RECALL_DIGEST_API_KEY available as an explicit override. If the LLM path returns no usable candidates for a session, the digest falls back to heuristic candidates for that session. Actual writes use SQLite truth rows, FTS/entity sync, digest run/source ledgers, semantic skip/update/insert decisions, exact duplicate cleanup, and LanceDB companion upsert when vector indexing is enabled.
current query
├─> SQLite lexical / FTS candidates
└─> LanceDB vector candidates
↓
score fusion + freshness hints + prompt budget
Supported retrieval modes:
Default hybrid weights:
Guardrail: if only one side has a score, that side is used directly instead of being unfairly damped by a missing partner score.
Scope is built from:
This prevents raw identifiers containing delimiters from colliding with split scope fields, and preserves the intended split: durable facts can move with the same user + agent identity, while local scratch rows do not leak across different groups, chats, sessions, or topics.
SQLite is the cardinality authority. During vector sync, the provider compares SQLite ids with LanceDB ids, deletes stale vector rows, collapses duplicate physical rows by id, and embeds missing/changed rows. If LanceDB delete/upsert fails, the SQLite write is preserved and vector state becomes needs_repair instead of surfacing the truth-row write as failed.
scope_recall_stats reports:
When vector.index_general=false (the default), local general scratch rows are not expected in LanceDB. A healthy synced companion should have vector.unique_id_count == vector.row_count, vector.duplicate_row_count == 0, and vector ids matching the configured vector-indexed provider rows.
For deeper maintenance:
python scripts/repair.vector_index.py --hermes-home "$HERMES_HOME" --dry-run
python scripts/repair.vector_index.py --hermes-home "$HERMES_HOME"Provider-owned captures apply a deterministic first line of governance before SQLite writes:
This is a local deterministic governance layer, not a remote LLM extraction pipeline. It intentionally stays conservative so SQLite remains auditable truth and conflicting memories are preserved rather than silently overwritten.
Primary-agent default tools:
scope_recall_store
scope_recall_search
scope_recall_context
scope_recall_probe
scope_recall_related
scope_recall_feedback
scope_recall_forget
scope_recall_update
scope_recall_merge
scope_recall_export
scope_recall_stats
scope_recall_inspect
scope_recall_explain
scope_recall_benchmark
Operator-only maintenance tools are hidden from the default schema and require maintenance_tools_enabled=true:
scope_recall_dedupe
scope_recall_govern
scope_recall_hygiene
scope_recall_repair
scope_recall_hygiene is read-only. It reports runtime-wrapper noise, assistant scratch prose, duplicate dedupe keys, very short/long rows, general rows present in the vector companion, likely promotion candidates, and likely delete candidates. It does not delete, merge, promote, or rewrite rows.
For an offline SQLite report without exposing the maintenance tool to agents:
python scripts/report.hygiene.py --db "$HERMES_HOME/scope-recall/memory.sqlite3" --format markdownDestructive cleanup is intentionally out-of-band: use the hygiene report first, then require an explicit operator decision before running any separate delete/merge/dedupe action. The shipped hygiene path is dry-run/report-only.
scope_recall_export defaults to the current accessible scope set: local scratch scope plus shared durable scope. Passing scope_only=false is an operator maintenance action and fails closed unless maintenance_tools_enabled=true.
Backward-compatible aliases are still accepted internally for old lancepro_* tool names during transition.
Example primary-agent tool calls:
# Store provider-owned memory. ops/user/memory/project become shared durable rows; general stays local scratch.
store = scope_recall_store(
content="This project deploys with uv run app.",
target="ops",
)
# Search the current accessible scope set: local scratch plus shared durable memory.
results = scope_recall_search(
query="How does this project deploy?",
limit=3,
)
# Inspect truth/vector health.
stats = scope_recall_stats()Example scope_recall_stats shape:
{
"provider": "scope-recall",
"total_memories": 42,
"scope_memories": 7,
"local_scope_memories": 3,
"shared_scope_memories": 4,
"vector": {
"enabled": true,
"ready": true,
"status": "ready",
"row_count": 42,
"unique_id_count": 42,
"duplicate_row_count": 0
}
}| Tool | Purpose |
|---|---|
| scope_recall_store | Store a provider-owned memory row after deterministic governance checks |
| scope_recall_search | Search the current local scratch scope plus shared durable scope with lexical/vector/hybrid retrieval |
| scope_recall_context | Render a compact task-relevant memory context block plus structured evidence for a query |
| scope_recall_probe | Inspect accessible memories attached to a specific entity |
| scope_recall_related | List entities that co-occur with a given entity in accessible memories |
| scope_recall_feedback | Mark a memory as helpful or unhelpful so trust scoring can adjust future recall |
| scope_recall_forget | Delete memories matching a query within the current accessible scope set |
| scope_recall_update | Replace content/category within the current accessible scope set; shared/local target-mode changes are rejected |
| scope_recall_dedupe | Operator-only: inspect or collapse exact duplicate rows |
| scope_recall_merge | Merge same-scope memories into a target row; shared/local mixing is rejected |
| scope_recall_export | Export SQLite truth rows as JSON or JSONL; defaults to current accessible scope set |
| scope_recall_govern | Operator-only: review tier distribution and decay/archive candidates |
| scope_recall_hygiene | Operator-only, read-only: report memory-quality cleanup/promotion candidates without modifying rows |
| scope_recall_repair | Operator-only: repair/rebuild the LanceDB companion from SQLite truth |
| scope_recall_stats | Inspect storage, retrieval, scope, and vector health |
On first boot, if $HERMES_HOME/lancepro/ exists and $HERMES_HOME/scope-recall/ does not yet contain the new DB/config, the provider:
OpenClaw memory-lancedb-pro history is handled separately as an explicit import problem, not automatic compatibility.
See:
Do not point scope-recall directly at an OpenClaw .lance directory and call it done. Old vector stores must be transformed into SQLite truth rows before the companion vector index is rebuilt.
scope-recall was inspired by good public ideas in OpenClaw memory-lancedb-pro, especially current-turn recall, scoped memory boundaries, hybrid retrieval, and memory hygiene. It is not a line-for-line port and it does not claim feature parity.
| Area | OpenClaw memory-lancedb-pro | scope-recall V1 |
|---|---|---|
| Host agent | OpenClaw | Hermes |
| Truth model | LanceDB-centric OpenClaw memory pipeline | SQLite truth + LanceDB companion index |
| Recall timing | OpenClaw auto-recall hook model | Hermes prefetch(query) current-turn recall; no queued next-turn recall |
| Curated memory | Separate OpenClaw markdown/journal behavior | Hermes USER.md / MEMORY.md live-read and kept authoritative |
| Smart extraction | LLM-backed created/merged/skipped style in upstream beta line | deterministic/rules-based extraction and conservative merge |
| Lifecycle | Weibull decay / tier promotion concepts upstream | deterministic metadata classification and decay/governance review; no full LLM summarization tier pipeline |
| Migration | OpenClaw-native data path | explicit importer from OpenClaw LanceDB shape into SQLite truth |
Honest claim boundary:
scope-recall is a Hermes local memory provider for current-turn recall with SQLite truth storage, LanceDB vector companion retrieval, strong runtime scope isolation, deterministic write-time governance, and explicit migration boundaries.
It should not be described as:
Check that the running provider is scope-recall, not the deprecated lancepro name, and remember that live Hermes runtime freshness requires a process restart/reload after code changes.
hermes memory statusRun the repair script. SQLite remains truth; the vector layer is rebuildable companion state.
python scripts/repair.vector_index.py --hermes-home "$HERMES_HOME" --dry-run
python scripts/repair.vector_index.py --hermes-home "$HERMES_HOME"The provider should degrade to local-hash. That keeps the system usable but lowers semantic quality. Set SCOPE_RECALL_GEMINI_EMBEDDING_API_KEY in your private environment to use the configured hosted path.
That is expected. OpenClaw history must be explicitly imported into SQLite truth rows before the companion vector index is rebuilt.
Release checks prove the source tree and artifact. They do not prove a running Hermes gateway has loaded the new plugin. Restart/reload the target Hermes process and verify with a real runtime smoke test before claiming live-runtime freshness.
See docs/stability.md for the exact V1 compatibility and non-goal boundaries.
| Document | Description |
|---|---|
| DESIGN.md | Architecture, layer split, retrieval model, migration plan, and release expectations |
| docs/stability.md | Stable V1 compatibility contract and non-goals |
| docs/migration.md | Local lancepro migration and explicit OpenClaw import guidance |
| docs/differences-from-memory-lancedb-pro.md | Honest comparison with OpenClaw memory-lancedb-pro |
| CHANGELOG.md | Release history |
| CONTRIBUTING.md | Contribution and development notes |
The public release gate is intentionally the same script used by GitHub Actions. Run it from a Hermes-compatible Python environment so plugin-loader imports and LanceDB/pyarrow dependencies match the runtime:
cd /path/to/scope-recall
PYTHONPATH=/path/to/hermes-agent:/path/to/scope-recall \
/path/to/hermes-agent/venv/bin/python -m pytest -q
PYTHONPATH=/path/to/hermes-agent:/path/to/scope-recall \
/path/to/hermes-agent/venv/bin/python scripts/check.release.py
/path/to/hermes-agent/venv/bin/python scripts/doctor.py --source-root /path/to/scope-recall --hermes-home "$HERMES_HOME"
/path/to/hermes-agent/venv/bin/python scripts/repair.vector_index.py --hermes-home "$HERMES_HOME" --dry-runPlain pytest from an unrelated Python environment is not a valid release signal: it can miss Hermes' plugins.memory loader path or the vector dependencies (lancedb, pyarrow) even when the checked-in plugin is healthy.
Release publishing is tag-driven: .github/workflows/release.yml can create a GitHub Release for a v* tag and populate notes from the matching CHANGELOG.md entry.
scripts/check.release.py verifies:
Current focused regression coverage includes:
| Package | Purpose |
|---|---|
| lancedb>=0.30.2 | LanceDB companion vector index |
| pyarrow>=24,<25 | Arrow data interchange used by LanceDB |
| sentence-transformers (optional) | Local semantic embedding models when using the sentence-transformers backend |
| Hermes Agent | Host runtime and memory-provider/plugin loading |
MIT. See LICENSE.
| Back | FazBrowse Home | New Git URL |