Files
hermes-skills/devops/rke2-cluster-administration/references/hermes-memory-system-architecture.md
T
Debian 01bd921ced feat: add home-assistant-dashboard-conventions skill + update multiple skills
- New: smart-home/home-assistant-dashboard-conventions (Mushroom cards, view tabs, no Bubble Cards)
- Updated: rke2, ceph, galera, proxmox, brainstorming, compound-learning, 1password-cli, smart-home-automation skills
- New references: ceph-cluster-administration, docker-volume-forensics, ceph-crush-weight, ceph-ec-mixed-size
2026-07-14 18:35:16 +00:00

152 lines
5.0 KiB
Markdown

# Hermes Memory System Architecture (2026-07-14)
## Overview
Hermes has two persistent memory stores injected into the system prompt:
- **MEMORY.md** — agent's personal notes (environment facts, infrastructure
topology, tool quirks). Default limit: 2,200 chars.
- **USER.md** — what the agent knows about the user (preferences, style,
communication rules). Default limit: 1,375 chars.
Both files live at `~/.hermes/memories/` and use `§` (section sign) as
entry delimiter: `\n§\n` between entries.
## Config
```yaml
# ~/.hermes/config.yaml
memory:
memory_enabled: true
user_profile_enabled: true
memory_char_limit: 2200
user_char_limit: 1375
nudge_interval: 10
```
Adjust limits:
```bash
hermes config set memory.user_char_limit 3000
hermes config set memory.memory_char_limit 4000
# Takes effect on next /reset or gateway restart
```
## System Prompt Injection Pipeline
### 1. Loading (once per session)
`agent_init.py` creates a `MemoryStore` instance and calls
`load_from_disk()`. This reads both `.md` files, splits on `§`, deduplicates
entries, and creates a **frozen snapshot**.
### 2. Frozen Snapshot (prefix-cache invariant)
```python
self._system_prompt_snapshot = {
"memory": self._render_block("memory", sanitized_memory),
"user": self._render_block("user", sanitized_user),
}
```
The snapshot is **never mutated mid-session** — even when `memory()` tool
calls write new entries to disk. This keeps the system prompt byte-stable,
preserving the LLM prefix cache across all turns.
### 3. Injection Point
`system_prompt.py` injects both blocks into the **volatile tier** of the
system prompt (alongside date, model, provider):
```python
if agent._memory_enabled:
mem_block = agent._memory_store.format_for_system_prompt("memory")
volatile_parts.append(mem_block)
if agent._user_profile_enabled:
user_block = agent._memory_store.format_for_system_prompt("user")
volatile_parts.append(user_block)
```
### 4. Rendered Format
```
════════════════════════════════════════════
MEMORY (your personal notes) [100% — 2,217/2,200 chars]
════════════════════════════════════════════
entry1
§
entry2
§
...
════════════════════════════════════════════
USER PROFILE (who the user is) [86% — 1,184/1,375 chars]
════════════════════════════════════════════
entry1
§
entry2
...
```
### 5. Threat Scanning
Each entry is scanned for prompt-injection patterns at load time
(`_sanitize_entries_for_snapshot`). Matches are replaced with
`[BLOCKED: ...]` in the snapshot, but the original text remains in the
live file so the user can inspect and delete it.
## System Prompt Tiers
```
STABLE (byte-stable, cached for entire session)
1. SOUL.md — identity ("You are Hermes Agent...")
2. Tool schemas, platform hints, guardrails
CONTEXT (cwd-dependent, changes between sessions)
3. .hermes.md / HERMES.md (walks to git root)
4. AGENTS.md (cwd only)
5. CLAUDE.md (cwd only)
6. .cursorrules (cwd only)
(first match wins — only ONE loaded, ~20K char cap)
VOLATILE (per-session, not cached)
7. MEMORY.md snapshot (memory_char_limit)
8. USER.md snapshot (user_char_limit)
9. External memory provider (optional, e.g. Hindsight)
10. Date, model, provider, session ID
```
## Alternative Context Injection Points
Beyond MEMORY.md/USER.md, additional context can be injected via:
- **SOUL.md** (`~/.hermes/SOUL.md`) — global identity/personality, always
loaded, no char limit
- **AGENTS.md** (in repo root) — project conventions, ~20K char cap,
loaded when cwd is the repo
- **CLAUDE.md / .cursorrules** — same as AGENTS.md, first-match-wins
- **.hermes.md** — walks up to git root, highest priority among context files
## Live State vs Snapshot
| Aspect | Snapshot (System Prompt) | Live State (Tool Calls) |
|--------|--------------------------|--------------------------|
| When read | Once at session start | Every `memory()` call |
| When written | Never (read-only) | Every `memory()` call → disk |
| Prefix cache | Byte-stable for session | N/A (not in prompt) |
| Changes visible | Next `/reset` or restart | Immediately in tool response |
## Key Insight
Memory writes via the `memory()` tool are **not visible in the current
session's system prompt** — they persist to disk but the snapshot was
already frozen. This is by design: mutating the system prompt mid-session
would invalidate the prefix cache and multiply API costs.
## Source Files
- `tools/memory_tool.py``MemoryStore` class, file I/O, rendering
- `agent/agent_init.py` lines 1199-1218 — initialization
- `agent/system_prompt.py` lines 426-435 — injection into volatile tier
- `agent/prompt_builder.py` lines 1921-1968 — context files (AGENTS.md etc.)
- `agent/coding_context.py` — project detection, context file discovery