๐ luminary-memory
A lightweight, self-hosted memory layer for AI agents.
Self-hosted ยท Private ยท Budget-aware ยท Self-maintaining
What your agent remembers is what it becomes.
Agents are only as good as what they remember. A stateless agent re-learns the same context every session, paying the same tokens, making the same mistakes. luminary-memory closes that gap with a local memory store that persists between runs, retrieves the right context on demand, and keeps itself tidy over time.
Four retrieval strategies. One fused answer. Zero cloud.
- Semantic, ONNX embeddings (384-dim, CPU, no GPU needed)
- Keyword, FTS5 BM25 (SQLite, zero config)
- Temporal, recency decay ร access count
- Graph, entity co-occurrence with automatic curation
Strategies run in parallel and fuse via weighted RRF (semantic 0.4, keyword 0.3, graph 0.2, temporal 0.1) โ adaptive cutoff (cliff detection) โ Jaccard deduplication (0.85) โ token budget (4096). Short queries are expanded with graph entities before embedding, so "deploy?" still finds "production cluster".
Important rules always in context. In the Hermes provider, the top-N most important memories are injected every turn (persistent context) and merged with query recall under anti-duplication โ so the agent never forgets a rule that exists in the store. Rules are pinned (never pruned), and similar rule ingests auto-replace the old one instead of stacking contradictions. Core memory (tagged core) is auto-loaded into the system prompt every session โ the DB-backed equivalent of MEMORY.md โ so durable rules are present from the very first prompt, no query needed.
Quickstart
pip install luminary-memory
from luminary_memory import MemoryClient
client = MemoryClient(db_path="memory.db")
# store a durable fact
client.ingest("The deploy target is the staging cluster", tags=["deploy", "infra"])
# recall, four strategies fused into one ranked answer
result = client.recall("where do we deploy?")
for memory, score in zip(result.memories, result.scores):
print(f"{score:.3f} {memory.content}")
# โ 0.942 The deploy target is the staging cluster
# CLI
luminary-memory add "deploy target is staging" --tags deploy
luminary-memory recall "where do we deploy?" --json
luminary-memory list
luminary-memory lifecycle
luminary-memory stats
Hermes Agent, first-class memory provider
Drop-in. Install the provider with pip install "luminary-memory[hermes]", then add
memory.provider: luminary to your Hermes config. That's it.
From the next session: auto-recall injects relevant memories every turn,
auto-save persists completed turns, and the model can call
luminary_recall / luminary_ingest / luminary_list on demand.
Two optional LLM-powered features keep the store sharp:
ingest_llm, evaluates every turn before saving: drops chit-chat, stores factual summaries instead of raw transcripts.auto_maintain, reviews the store at session end: keeps current facts, updates changed ones, deletes stale or duplicate ones.
22 settings are exposed in the Hermes dashboard for zero-hassle tuning. See hermes/README.md for the one-shot installer and full configuration.
Configuration
Every setting has a LUMINARY_* env var or a Settings object.
| Setting | Env var | Default |
|---|---|---|
backend |
LUMINARY_BACKEND |
sqlite |
db_path |
LUMINARY_DB_PATH |
luminary_memory.db |
pg_dsn |
LUMINARY_PG_DSN |
postgresql://localhost/luminary_memory (pgvector only) |
pg_hnsw_index |
LUMINARY_PG_HNSW_INDEX |
false |
pg_hnsw_m |
LUMINARY_PG_HNSW_M |
16 |
pg_hnsw_ef_construction |
LUMINARY_PG_HNSW_EF_CONSTRUCTION |
64 |
embedding_model |
LUMINARY_EMBEDDING_MODEL |
BAAI/bge-small-en-v1.5 |
embedding_dim |
LUMINARY_EMBEDDING_DIM |
384 |
ingest_llm |
LUMINARY_INGEST_LLM |
false |
rrf_k |
LUMINARY_RRF_K |
60 |
strategy_weights |
LUMINARY_WEIGHT_{SEMANTIC,KEYWORD,GRAPH,TEMPORAL} |
0.4 / 0.3 / 0.2 / 0.1 |
recall_cliff_threshold |
LUMINARY_RECALL_CLIFF_THRESHOLD |
0.45 |
dedup_jaccard_threshold |
LUMINARY_DEDUP_JACCARD_THRESHOLD |
0.85 |
token_budget |
LUMINARY_TOKEN_BUDGET |
4096 |
max_memories |
LUMINARY_MAX_MEMORIES |
1000 |
ttl_default_seconds |
LUMINARY_TTL_DEFAULT_SECONDS |
null |
prune_min_importance |
LUMINARY_PRUNE_MIN_IMPORTANCE |
0.2 |
consolidate_jaccard_threshold |
LUMINARY_CONSOLIDATE_JACCARD_THRESHOLD |
0.9 |
consolidate_semantic |
LUMINARY_CONSOLIDATE_SEMANTIC |
true |
importance_auto |
LUMINARY_IMPORTANCE_AUTO |
true |
importance_recall_boost |
LUMINARY_IMPORTANCE_RECALL_BOOST |
1.0 |
rule_auto_replace |
LUMINARY_RULE_AUTO_REPLACE |
true |
rule_auto_replace_threshold |
LUMINARY_RULE_AUTO_REPLACE_THRESHOLD |
0.85 |
rule_importance |
LUMINARY_RULE_IMPORTANCE |
0.9 |
context_top_n |
LUMINARY_CONTEXT_TOP_N |
8 |
context_budget |
LUMINARY_CONTEXT_BUDGET |
2000 |
context_min_importance |
LUMINARY_CONTEXT_MIN_IMPORTANCE |
0.0 |
core_tag |
LUMINARY_CORE_TAG |
core |
core_top_n |
LUMINARY_CORE_TOP_N |
12 |
core_budget |
LUMINARY_CORE_BUDGET |
8000 |
query_planner |
LUMINARY_QUERY_PLANNER |
true |
query_planner_keyword_threshold |
LUMINARY_QUERY_PLANNER_KEYWORD_THRESHOLD |
0.9 |
ingest_whitelist |
LUMINARY_INGEST_WHITELIST |
[] |
llm_base_url |
LUMINARY_LLM_BASE_URL |
"" |
llm_api_key |
LUMINARY_LLM_API_KEY |
"" |
llm_model |
LUMINARY_LLM_MODEL |
gpt-4o-mini |
llm_timeout |
LUMINARY_LLM_TIMEOUT |
10 |
llm_max_tokens |
LUMINARY_LLM_MAX_TOKENS |
512 |
rule_keywords |
LUMINARY_RULE_KEYWORDS |
NEVER,ALWAYS,MUST,... |
Provider-specific settings (Hermes dashboard):
max_memories,context_*,mode,recall_limit,auto_recall,recall_sync,auto_retain,retain_every_n_turns,retain_user_prefix/retain_assistant_prefix,ingest_llm,auto_maintain,consolidate_semantic,importance_auto,recall_indicator,retain_indicatorโ live in~/.hermes/luminary/config.json. See hermes/SKILL.md for the full provider config table.
Architecture
Memory is a loop, not a pipeline you run once. Every turn, luminary recalls what is relevant before the agent answers, then ingests what mattered after, and a background lifecycle keeps the store lean.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ LOOP โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
recall(query) โโโบ 4 strategies in parallel โโโบ weighted RRF โโโบ adaptive cutoff โโโบ ranked results
โฒ semantic โ keyword โ temporal โ graph (per-strategy weights) (cliff detection)
โ โ
โโโ inject into agent context โโโ token budget (4096) โโโ dedup (Jaccard 0.85)
โ โ
persistent context โโโบ top-N by importance every turn โโโ (merged, anti-duplicated)
โ
ingest(text) โโโบ whitelist โโโบ (LLM curation) โโโบ embed (ONNX 384-d) โโ
โ
lifecycle() โโโบ cleanup (TTL) โโโบ consolidate (semantic + Jaccard, pinned exempt) โโโบ prune (importance, pinned exempt)
maintenance() โโโบ LLM reviews store โโโบ keep โ update โ delete stale facts
Why it is accurate:
| Stage | Mechanism |
|---|---|
| 4 strategies | Semantic (ONNX cosine, vectorized matmul) + keyword (FTS5 BM25) + temporal (recency ร access, batched fetch) + graph (entity co-occurrence, SQL aggregation), all in parallel |
| Persistent context | Top-N important memories injected every turn (not just at session start), so rules never fall out of context |
| Weighted fusion | Each strategy carries a tunable weight (semantic 0.4, keyword 0.3, graph 0.2, temporal 0.1), so high-signal strategies dominate the ranking |
| Query expansion | Short queries are expanded with co-occurring graph entities before embedding; when the graph is empty, keywords from a durable rule on the same topic are appended (v0.2.15). A bare "deploy?" still finds "production cluster" |
| Importance boost | Memories at importance โฅ 0.8 get a ranking bonus, lifting durable rules above weak-but-recent noise |
| Adaptive cutoff | Cliff detection keeps only the relevant cluster: a sparse store returns 3 strong matches instead of padding to 20, while a dense relevant store keeps everything (no over-filtering) |
| Token budget | Hard cap so memory injection never blows up the context window |
Why it stays clean:
| Stage | Mechanism |
|---|---|
| Lifecycle | TTL cleanup, semantic consolidation (embedding cosine, fallback Jaccard), importance-based pruning โ all batched at the backend level |
| Rule pinning | Memories at importance โฅ 0.9 are pinned: never pruned, never deleted by consolidation |
| Rule auto-replace | Similar rule ingests replace the old one (anti-contradiction), so "never use tables" never coexists with "always use tables" |
| Store hygiene | Rule keywords are checked only against the LLM-curated summary (raw transcripts are never pinned); turns without a curated summary are dropped when ingest_llm is on |
| Auto importance | Every memory is scored by recency + access + graph centrality; prune and health use live values. On recall, frequently-used memories are re-estimated immediately so they climb into the next turn's persistent context (v0.2.15, LUMINARY_IMPORTANCE_AUTO) |
| Max memories cap | max_memories (default 1000) prunes the oldest/lowest-importance when the store exceeds it |
| LLM maintenance | Optional auto_maintain reviews the store at session end: keep, update, or delete stale facts |
| Health score | health_score() gives a 0-100 checkup with actionable recommendations |
| Content-level anti-dup | Core, persistent context, and recall share one dedup set (ids + content hashes), so a rule stored both as core and as a plain memory appears exactly once per turn (v0.2.15) |
health_score() gives you a 0-100 checkup with actionable recommendations.
Documentation
| Section | |
|---|---|
| Quickstart | Install and first use |
| Architecture | Pipelines and data flow |
| Python API | MemoryClient reference |
| CLI | All subcommands |
| Recall | Four strategies + fusion |
| Lifecycle | Cleanup, consolidation, pruning, LLM maintenance |
| Backends | SQLite vs pgvector |
| Hermes integration | Provider, config, installer |
| Roadmap | v0.2.15 โ v1.0.0 |
| Benchmarks | ~77 ms recall @ 5k (p50), 0 LLM tokens |
License
Apache-2.0 ยฉ 2026 Dwiky Candra
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file luminary_memory-0.2.15.tar.gz.
File metadata
- Download URL: luminary_memory-0.2.15.tar.gz
- Upload date:
- Size: 187.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81467073a5f95059e62dc13d9930a462b06136ff7ecc2364444d8b90edd1a983
|
|
| MD5 |
67271afc4c99d96d23e270d4dfca3eae
|
|
| BLAKE2b-256 |
b33e561351dd5f9fcc36ae666ea48abaa7307e79ee99b4f6c0acb5eac360f951
|
Provenance
The following attestation bundles were made for luminary_memory-0.2.15.tar.gz:
Publisher:
publish.yml on alertxsto/luminary-memory
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
luminary_memory-0.2.15.tar.gz -
Subject digest:
81467073a5f95059e62dc13d9930a462b06136ff7ecc2364444d8b90edd1a983 - Sigstore transparency entry: 2507310714
- Sigstore integration time:
-
Permalink:
alertxsto/luminary-memory@9926b722774d20697264ba0fa8ab5247df45f9b5 -
Branch / Tag:
refs/tags/v0.2.15 - Owner: https://github.com/alertxsto
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9926b722774d20697264ba0fa8ab5247df45f9b5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file luminary_memory-0.2.15-py3-none-any.whl.
File metadata
- Download URL: luminary_memory-0.2.15-py3-none-any.whl
- Upload date:
- Size: 75.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1714c3edadeadf151a8006d4188a017c9f47d6dac147af91478d3b8b5bfb2bd
|
|
| MD5 |
3c3ad758fd5dfcc7d6f705a23e9b3f8e
|
|
| BLAKE2b-256 |
75b9fcd2a312ba9d0b179d6bbe0deb558464da3488efcbf5b79cdf2d308b21a9
|
Provenance
The following attestation bundles were made for luminary_memory-0.2.15-py3-none-any.whl:
Publisher:
publish.yml on alertxsto/luminary-memory
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
luminary_memory-0.2.15-py3-none-any.whl -
Subject digest:
a1714c3edadeadf151a8006d4188a017c9f47d6dac147af91478d3b8b5bfb2bd - Sigstore transparency entry: 2507310851
- Sigstore integration time:
-
Permalink:
alertxsto/luminary-memory@9926b722774d20697264ba0fa8ab5247df45f9b5 -
Branch / Tag:
refs/tags/v0.2.15 - Owner: https://github.com/alertxsto
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9926b722774d20697264ba0fa8ab5247df45f9b5 -
Trigger Event:
push
-
Statement type: