Install
openclaw skills install @xmannixx/agent-memory-2Persistent SQLite memory for Hermes and OpenClaw: Facts, snippets, lessons, entities, relations, provenance (read-only audit-chain reconstruction), finer source trust (tool/external quarantined to evidence), relation-aware plugin recall with opt-in neighbor attributes, conflict detection, Authority Lanes, a procedural lane for self-written behavioral rules (observation-only, human review-gate, rule-conflict detection), Rebound-Protection, and budgeted German-aware query retrieval.
openclaw skills install @xmannixx/agent-memory-2Persistent memory system for Hermes and OpenClaw with structured Authority Lanes, raw recall snippets, Rebound-Protection, and budgeted plugin retrieval.
Inspired by Lena OpenClaw's agent-memory-1-0-0, extended with:
tool/external quarantined to evidence; identity/authorization protected)identity, authorization) with explicit resolution; open conflicts auto-reconcile when a referenced fact becomes inactiveAGENT_MEMORY_BUDGET_ENTITY_ATTRSget_provenance() and CLI provenance (derived from the append-only audit log; no duplicate storage)Load this skill when you want persistent memory across Hermes sessions that:
HERMES=~/.hermes
# Core memory module
mkdir -p $HERMES/agent-memory/src
mkdir -p $HERMES/agent-memory/cli
mkdir -p $HERMES/agent-memory/tests
cp src/memory.py $HERMES/agent-memory/src/
cp cli/fact.py $HERMES/agent-memory/cli/
cp tests/test_memory.py $HERMES/agent-memory/tests/
cp tests/test_plugin.py $HERMES/agent-memory/tests/
mkdir -p $HERMES/plugins/agent-memory-plugin
cp plugin/__init__.py $HERMES/plugins/agent-memory-plugin/
cp plugin/plugin.yaml $HERMES/plugins/agent-memory-plugin/
plugins:
enabled:
- agent-memory-plugin
# Runs forget_stale() daily
systemctl --user enable --now hermes-memory-cleanup.timer
cd ~/.hermes/agent-memory
python3 -m pytest tests -v
# Expected: 148 passed
| Class | TTL | Min Confidence | Allowed Sources | Notes |
|---|---|---|---|---|
| identity | NEVER | 0.9 | observation, conversation | Floor — never expires |
| preference | 14d | 0.3 | observation, conversation | Tone, style, language |
| evidence | 60d | 0.5 | observation, conversation, inference, tool, external | Quarantine for lower-trust input |
| authorization | 90d | 0.9 | observation ONLY | Never from conversation/tool/external |
| procedural | 30d | 0.5 | observation ONLY | Self-written behavioral rules; own table, human review-gate, never auto-active |
Behavioral rules ("how to respond"), kept separate from facts ("what is true")
in a procedural_rules table. Observation-only writes via propose_rule();
every rule starts pending and only approve_rule() (a mandatory human gate, no
auto-approve) makes it active. Deterministic, stdlib-only conflict detection on
approval hard-blocks direct contradictions and soft-blocks interactions /
artifact bloat / budget overflow (override with ack_interactions). The plugin
injects only active, trigger-matching rules in a sanitized, budgeted
## Procedural Rules block. CLI: propose-rule, pending-rules,
active-rules, approve-rule, reject-rule, retire-rule, rule-conflicts.
After >6h idle: max 3 new facts accepted per session (except identity). Prevents memory flooding after long offline phases.
Non-identity facts expire by last access, not only by creation time. recall(),
recall_by_authority(), and get_fact() all refresh last_accessed and extend
expires_at according to the fact's authority lane. This keeps facts alive when
the auto-injection plugin actively uses them.
import sys
sys.path.insert(0, str(Path.home() / '.hermes/agent-memory/src'))
from memory import AgentMemory
mem = AgentMemory()
# Store a fact
mem.remember("User's name is Alex", authority_class="identity",
source="observation", confidence=1.0)
# Store preference
mem.remember("Prefers German language", authority_class="preference",
source="observation", confidence=0.9)
# Search
facts = mem.recall("name")
# All identity facts
identity = mem.recall_by_authority("identity")
# Record a lesson
mem.learn(action="Deployed without fallback",
context="hermes-setup", outcome="negative",
insight="Always configure a fallback provider")
# Track an entity
mem.track_entity("Alex", "person", {"username": "alex_dev", "language": "de"})
# Entity relations
mem.relate("Alex", "arbeitet_bei", "acme")
mem.get_relations("Alex", direction="both")
# Conflicts (tag single-valued lane facts)
mem.get_conflicts()
# mem.resolve_conflict(keep_id, [drop_id])
# Store raw recall separately from facts
mem.remember_snippet("Discussed query-aware retrieval", session_id="demo")
snippets = mem.search_snippets("query-aware", session_id="demo")
# Stats
print(mem.stats())
# Daily cleanup (also runs via systemd timer)
mem.forget_stale()
PYTHON=python3
CLI=~/.hermes/agent-memory/cli/fact.py
# Add fact
$PYTHON $CLI add "User name is Alex" --authority identity --source observation --confidence 1.0
# Search
$PYTHON $CLI recall "name"
# List by class
$PYTHON $CLI list --authority identity
# Stats
$PYTHON $CLI stats
# Raw recall snippets
$PYTHON $CLI snippet add "Discussed local-first retrieval" --session demo
$PYTHON $CLI snippet search retrieval --session demo
# Audit / snapshots / provenance / consolidation
$PYTHON $CLI audit --limit 10
$PYTHON $CLI snapshot --label before-change
$PYTHON $CLI provenance <fact_id>
$PYTHON $CLI consolidate --dry-run
# Cleanup
$PYTHON $CLI forget-stale
# Record lesson
$PYTHON $CLI learn "Action" "Context" positive "Insight"
# Relations and conflicts
$PYTHON $CLI relate Alex arbeitet_bei acme
$PYTHON $CLI relations Alex --direction out
$PYTHON $CLI conflicts
$PYTHON $CLI resolve-conflict <keep_id> <drop_id>
Once installed, the plugin builds memory context automatically via the pre_llm_call hook.
First turn:
Later turns:
## Related (1-hop, edge-only; opt-out via AGENT_MEMORY_RELATIONS; optional neighbor attributes via AGENT_MEMORY_BUDGET_ENTITY_ATTRS, default disabled)authorization facts are never prompt-injected. They are allowed only from
observation source and should be used by explicit code paths, not automatic
context injection.
No manual loading required.
python is not in PATH — use python3 or full venv path.:memory: loses data when connection closes. Tests use _shared_conn pattern — do not change connection logic without understanding this._check_rebound() must run after _init_db() — memory_meta must exist first.startup_skills alone is NOT enough for auto-injection. The plugin with pre_llm_call hook is required.authorization facts from conversation source are silently rejected by design.remember_snippet() and search them with search_snippets().remember()), not time-based.references/architecture.md for design rationalereferences/moltbook-discussion.md for signalfoundry pattern origin