guide · ai

Hermes Memory: What to Save and What Not To

Eight-category rule for Hermes MEMORY.md and USER.md: four always-save kinds, four never-save kinds, the 2k-char ceiling, and the Johnny5 routing gate.

July 15, 2026 · By Alastair Fraser

A retro robot at a control panel with two parallel conveyor belts: a green ACCEPT belt carrying small labelled tiles (PREFERENCE, ENV FACT, TOOL QUIRK, CONVENTION), and a red REJECT belt carrying tiles (PROCEDURE, DATE, TODO, SECRET) that drop off into a bin marked MEMORY.MD with a 2,000-char label.

Memory in Hermes is the most expensive real estate you operate: every byte you write is paid for on every future turn. MEMORY.md and USER.md load once at session start and stay in the system prompt until the conversation ends. The cost floor is paid whether the entry is high-signal or noise. New operators treat memory as a journal; the year-in mistake is treating it as a CRM. Both fail the same way: the file grows, signal-to-noise drops, and the agent recycles hallucinated preferences confidently.

This guide gives you the eight-category rule, the 2,000-char ceiling, and the Johnny5 routing gate. Load it before every end-of-session review when you are tempted to dump it all into MEMORY.md.

The four kinds of fact that always belong in memory

A fact goes into MEMORY.md or USER.md only if it passes all three memory-hygiene questions (needed at session start? forgetting would cause a wrong decision? is it a rule, environment fact, or stable preference?) AND falls into one of the four kinds below.

1. Operator preferences

Stable preferences about how the operator wants decisions made, communicated, or styled. USER.md is for identity and decision style; MEMORY.md is for operational preferences (release gates, deployment cadence, approval thresholds). Litmus test: would the operator still want this on a fresh project with no context?

Examples: “Alastair prefers surgical execution.” “Release preference: run regression coverage before an explicitly authorized GitHub push.” “Amazon Associates tracking ID agenticbotsit-20.” “Voice-message stop phrase: ‘Nothing to save.‘“

2. Environment facts

Durable runtime facts the agent needs at session start and would otherwise have to rediscover every time. Without them, every session re-probes the filesystem, network, and service registry. Examples: “ATS RD runs on uvicorn :18071, DB at /var/lib/atsrd/atsrd.db.” “Cloudflared loads config from CF edge; local YAML is decorative.” “ABS site image assets live at /srv/abs-site/public/images/.”

3. Tool quirks

Recurring failure modes, silent behaviors, or contract subtleties of tools the agent uses daily. Each entry should be one short line naming the tool, failure mode, and defense — not a procedure, a warning the procedure-loader reads first. Examples: “memory_audit.sh uses wc -c (bytes) for char-limit comparison — 2,200 CJK chars = 6,600 bytes, mis-fires as 300 percent full.” “memory-governor counter increments BEFORE event write; write failure is silently swallowed.” “fact_store and fact_feedback tools are not registered in this build — drift-defense instructions degrade gracefully.”

4. Cross-cutting stable conventions

Rules that apply in every project, on every machine, across every session — the highest-leverage entries in MEMORY.md. The easiest to over-grow: project-specific conventions belong in project docs or the relevant skill, not here. Examples: “Site down = diagnose completely THEN act.” “Memory is for state I need every day, not for history/versioning records.” “Cron-ID and file-path literals in posts must be verified live against disk before publishing.”

The four kinds of fact that never belong in memory

The memory-hygiene skill calls these “records of past work” and routes them to files. Each one is high-signal for the moment it is true but rots within weeks.

1. Procedural that became a skill

Anything with a known shape that recurs and can be expressed as a recipe belongs in a skill, not in memory. Test: “is there a step-by-step?” If yes, write a SKILL.md and reference it. Memory holds the pointer; the skill holds the procedure. Examples: “How to publish an ABS guide” → site-hosting/abs-concepts-guide-post-authoring; “How to gate memory writes” → memory-hygiene; “How to deploy an Astro static site” → site-hosting-library. Each is now a SKILL.md file the agent loads on demand; in memory it would have been a 300-word entry.

2. Dated events

Anything that names a specific date, hour, or session. “Fixed parser V1.3.9 on 2026-06-30,” “site was down 2026-06-25 due to missing watchdog,” “shipped Meta ads last week and got 50 signups.” These are records, not state — git log, campaign report, or postmortem is the right home. Sub-rule: if the line starts with “yesterday,” “today I,” “we just,” or names a commit SHA, it is not a memory candidate. The exception is when a date grounds a durable rule (“ATS RD killed 2026-06-25T16:28” as evidence for “every service needs a watchdog”) — then the rule is the memory and the date is optional.

3. Ephemeral todos

Anything that is a next step, a current task, or a one-time action. Belongs in the session todo list, project kanban, or daily handoff file. A todo left in memory for six months is a todo the agent will either forget (best case) or act on stale context (worst case).

4. Secrets

API tokens, account passwords, recovery codes, OAuth client secrets, database credentials, private keys. These never belong in any memory tier — full stop. The right home is a secrets manager (~/.hermes/.env, 1Password, AWS Secrets Manager) loaded at runtime. A secret in MEMORY.md is a secret in every system prompt, log dump, and tool output that includes the prompt.

The 2,000-char ceiling

Every byte of memory competes with tools and history for context, and a long MEMORY.md is harder to audit, harder to keep honest, and more likely to harbor stale entries the agent recycles confidently. The soft caps on this profile:

FileSoft capHard capTrigger
MEMORY.md2,0002,20080% of soft cap
USER.md1,0001,37580% of soft cap

The audit cron fires daily at 00:30 UTC and flags entries over 400 chars, date stamps, or version mentions. The alert-without-shrink loop is a known failure mode on this profile (cron 81c7c004205e ran 10 consecutive days with no shrink action). When MEMORY.md hits 80%, run the 3-question filter in reverse on every entry and move failing entries to files.

The Johnny5 routing gate (high-level)

The routing gate is a save-gate and a trim-gate applied to every memory write (full reference: devops/harness-self-maintenance/references/memory-routing.md):

Save gate — answer in order before every durable write:

  1. Must it be available at the start of every session? If no, do not save it.
  2. Stable operator preference? → USER.md.
  3. Cross-cutting operator/environment fact? → MEMORY.md, one short line.
  4. Reusable procedure, recurring fix, or pitfall? → SKILL.md.
  5. Troubleshooting, completed-work history, or project state? → project docs.
  6. Curated long reference used across projects? → memory-bank topic.
  7. Raw data or visible artifact? → local artifact; canonical → R2 with verification.
  8. Current task or next step? → todo list or session handoff.

If no route fits, do not save it.

Trim gate — when memory is over 80%, four steps in order: KEEP (entries that still belong in T1 and need every-session injection), TRIM (verbose entries to the shortest rule that preserves meaning), MOVE (useful detail to the correct tier first, then remove from T1 only after approval), REMOVE (stale, duplicated, reconstructable, or already-covered entries after approval). Trim requests are proposal-only — the proposal turn lists every entry verbatim with KEEP / TRIM / MOVE / REMOVE and the per-entry char delta; the apply turn only happens after explicit operator approval. Hard rules: never use MEMORY/USER as logs, diaries, changelogs, troubleshooting records, or skill inventories; dates and versions in T1 require durable justification; never store secrets; prefer moving detail down-tier; use the memory tool for T1 edits, never patch MEMORY.md or USER.md directly.

Verification checklist

#CheckHow
1MEMORY.md < 2,000 charspython3 -c "import sys; print(len(open('/opt/data/memories/MEMORY.md', encoding='utf-8').read()))"
2USER.md < 1,000 charssame recipe against USER.md
3No secrets in memorygrep -niE 'token|password|secret|api[_-]?key|client[_-]?secret' /opt/data/memories/*.md returns no hits
4No date stampsgrep -nE '20[0-9]{2}-[0-9]{2}-[0-9]{2}' /opt/data/memories/MEMORY.md — any hit must ground a durable rule
5Every entry passes the 3-question filterwalk each: needed at session start? forgetting causes wrong decision? rule/env fact/stable preference?
6Every recurring procedure is in a SKILL.mdls /opt/data/skills/ and verify each procedure exists there
7Daily audit cron acted onls /opt/data/cron/output/81c7c004205e/ — most recent output < 36h old

The cost of a bloated memory file compounds across every future turn.

Sources

Last verified: 2026-07-15 against Hermes v0.18.2 (2026.7.7.2). Soft caps and cron ID verified against /opt/data/scripts/memory_audit.sh and /opt/data/cron/output/81c7c004205e/.

Sources

#hermes#memory#discipline#hygiene#routing-gate#2,000#mental-model

Submit a take

Have a different read on this? Drop a comment below — your email isn't published, and I read every one. Nothing leaves the site until I approve it.

Your email address will not be published. Required fields are marked.