# Hermes — Memory and Persistence

Hermes is designed to learn and accumulate knowledge over time, not just react to point-in-time checks. This page documents how memory works, what persists, and how the agents use it.

## Memory tiers

Tier Storage Location Lifetime Purpose
————————-———-———
SHORT Redis (AOF+RDB) `/kaburudata/hermes/redis/` on ZFS 30 days TTL Fast access, current state, recent events
LONG Markdown files on ZFS `/kaburudata/hermes/memory/*.md` Permanent Incidents, resolutions, patterns — survives rebuilds
WIKI Git repo on Hetzner `/home/kaburusvr.uk/wiki/wiki/` Permanent Authoritative infrastructure documentation

## What Hermes learns

### Baselines (learned normal values) Hermes uses an exponential moving average (EMA, α=0.1) to build a learned sense of normal for each host metric. Each check cycle updates the baseline:

``` new_baseline = 0.1 × current_value + 0.9 × old_baseline ```

This means baselines shift slowly — a single spike doesn't change what “normal” means. After ~20 check cycles a baseline is well-established. After ~50 it's very stable.

Baselines are stored as `hermes:baseline:<host>:<metric>` in Redis (90 day TTL). They are injected into every health check prompt so the AI can say “load is 2.1 which is above the learned baseline of 0.4” rather than alerting on absolute values.

### Memory categories

Category What gets stored Written to ZFS?
———-—————–—————–
incidents Outages, crashes, health warnings, site downs, SNMP alerts ✅ Always
anomalies Unusual patterns worth watching over time On urgent only
resolutions What fixed a problem (manual or automated) ✅ Always
baselines Normal metric values per host (EMA) Redis only
patterns Recurring events (e.g. daily load spike at 03:00) On demand
actions Manual commands run by Steve via Telegram On demand
observations Non-critical notes from each check cycle Redis only

## Persistence architecture

``` kaburuaibox ZFS pool: kaburudata ├── kaburudata/hermes/redis/ ← Redis data dir (AOF + RDB) │ ├── dump.rdb ← RDB snapshot (every 60s if 1000+ changes) │ └── appendonlydir/ ← AOF files (fsync every second) ├── kaburudata/hermes/memory/ ← Long-term memory markdown files │ ├── incidents.md │ ├── anomalies.md │ ├── resolutions.md │ ├── baselines.md │ ├── patterns.md │ ├── actions.md │ └── observations.md └── kaburudata/hermes/logs/ ← Agent logs (hermes.log) ```

All three datasets are on ZFS with automatic snapshots (hourly x24, daily x7, weekly x4). In a disaster recovery scenario, Redis state, memory files, and logs all survive independently of the Docker containers and volumes.

## Redis configuration

``` appendonly yes ← Write-ahead log — max 1 second of data loss on crash appendfsync everysec ← fsync every second (balance between safety and performance) save 900 1 ← RDB snapshot if 1 change in 15 min save 300 10 ← RDB snapshot if 10 changes in 5 min save 60 1000 ← RDB snapshot if 1000 changes in 1 min ```

Previously Redis data lived in a Docker-managed volume on `/dev/sda2` (local disk, no ZFS). Migrated to ZFS on 2026-05-25.

## How memory is used in AI prompts

Every AI check call receives a memory context block:

``` MEMORY CONTEXT:

RECENT INCIDENTS:
  [2026-05-25 11:51] ubuntu-svr: Hard lockup — required physical reboot
  [2026-05-25 12:10] network: SNMP trap received — coldStart from OPNsense
RECENT ANOMALIES:
  (none currently)
LEARNED BASELINES (normal values):
  kaburusvr load_1min: 0.51
  kaburuaibox gpu_temp: 38.0
  ubuntu-svr mem_percent: 42.0

```

This allows the AI to: - Avoid false alerts on values that are historically normal for this infrastructure - Recognise when something is genuinely elevated vs background noise - Reference previous incidents when diagnosing recurring issues

## Chat workspace memory

The Hermes chat interface (dashboard Workspace tab) loads: 1. Current status snapshot — all 12 Redis check keys (health, security, uptime, etc.) 2. Wiki index — fetched live from kaburusvr, so Hermes knows what documentation exists 3. Memory context — recent incidents, anomalies, resolutions, and learned baselines 4. Infrastructure overview — hardcoded in system prompt with all 6 nodes, IPs, roles

Hermes can read any wiki page on demand during a chat session using the Hetzner connector.

## Weekly memory sync to wiki

Every Sunday at 08:00 (during daily report), Hermes syncs the long-term memory files to the wiki on Hetzner as `wiki/infrastructure/hermes-memory-<category>.md`. These are git-committed automatically and serve as a permanent searchable incident log.

## Backup

Long-term memory is included in the Z840 nightly backup to TrueNAS: ``` /kaburudata/hermes/ → rsync → /mnt/tank/backups/z840/ ```

Redis AOF/RDB files are also included. Full recovery possible from TrueNAS backup alone.

## History

Date Event
————-
2026-05-17 Hermes first deployed — no persistent memory, Redis on local Docker volume
2026-05-25 Memory layer added: HermesMemory class, baselines, categories
2026-05-25 Redis migrated to ZFS (kaburudata/hermes/redis), AOF enabled
2026-05-25 Memory context injected into all health check and chat prompts
2026-05-25 Weekly wiki sync of long-term memory added to daily_report