Hermes Framework Adapter
Translates between Hermes's native home directory and the Agent Life Format (ALF). Hermes (Nous Research) keeps a small, prose-first memory that it injects into every prompt, plus a separate session database that records everything the agent has ever discussed. This adapter is the bridge for backing up, syncing, and migrating real Hermes agent installations — including across runtimes.
1. How Hermes Stores Memory
A Hermes agent's durable state lives in a per-agent home directory called a profile. Unlike a single workspace of Markdown files, Hermes keeps two distinct memory surfaces with opposite characteristics: a tiny curated store that is frozen into the system prompt, and a session history database that grows with every conversation. Around them sit the agent's identity, the user profile, its credentials, and its skills.
Profiles & Home Layout
Each profile is a separate home directory (HERMES_HOME). The default profile is ~/.hermes; additional named profiles live under ~/.hermes/profiles/<name>/, each with its own config, secrets, identity, memory, sessions, and skills. A profile is what a user thinks of as "an agent," so the adapter exports exactly one profile per .alf archive — and several profiles on one machine are backed up independently (see Multiple Profiles).
~/.hermes/ # HERMES_HOME (the agent = one profile)
├── SOUL.md # Agent identity / persona (prompt slot #1)
├── config.yaml # Config (personalities, system prompt, limits)
├── .env # Credentials (API keys, bot tokens) — plaintext
├── memories/
│ ├── MEMORY.md # Curated agent memory (hard char cap)
│ └── USER.md # User profile (hard char cap)
├── state.db # Session history: sessions + messages + FTS5
├── sessions/
│ ├── <SessionId>.jsonl # Raw per-session transcripts
│ └── sessions.json # Session-key → active-id index (transient)
├── skills/
│ └── <category>/<name>/SKILL.md # Skills (+ references/templates/scripts/assets)
├── skill-bundles/ # Skill bundle manifests
├── checkpoints/ state-snapshots/ # Rollback / execution state (not agent memory)
├── backups/ logs/ # Local admin data
└── profiles/<name>/ # Additional agents (each a full HERMES_HOME)
Curated Memory: MEMORY.md & USER.md
Hermes's built-in long-term memory is two small Markdown files, each with a hard character limit, loaded once at session start and rendered into the system prompt as a frozen snapshot:
| File | Purpose | Default limit |
|---|---|---|
MEMORY.md | The agent's own notes — environment, conventions, lessons learned, completed work | ~2,200 chars (~800 tokens) |
USER.md | The user profile — preferences, communication style, expectations | ~1,375 chars (~500 tokens) |
Both are a list of discrete entries separated by a § delimiter; entries may be multiline. The agent edits them through a dedicated tool (see §2). Because the limits are hard and there is no automatic compaction, the curated store is small and continuously rewritten — the agent merges and prunes entries to stay under the cap. This shapes how the adapter assigns record identities (§4).
Session History: state.db
Every conversation — from the CLI or any of Hermes's ~22 messaging sources — is persisted in two complementary places: a SQLite database and raw transcripts.
| Store | Path | Contents |
|---|---|---|
| SQLite DB | ~/.hermes/state.db | sessions, messages, and messages_fts (an FTS5 full-text index). WAL mode. |
| JSONL transcripts | ~/.hermes/sessions/ | Raw per-session transcripts plus a sessions.json index. |
The sessions table records session id, source platform, user id, model, a unique title, the system-prompt snapshot, start/end timestamps, token counts, and a parent_session_id that links compression lineage. The messages table holds the full history (role, content, tool calls, token counts). Session IDs have the form YYYYMMDD_HHMMSS_<hex> and are stable and unique. Sessions are effectively append-only — new sessions are added and old ones rarely change, except that compression forks a new lineage ("my project" → "my project #2"). This database is where the volume of a Hermes agent lives, and it is essential to a useful backup — so the adapter captures it by default.
External Memory Providers
Hermes can also run optional external memory plugins (Honcho, Mem0, and others) alongside the built-in store. These maintain their own backends — knowledge graphs, vector indexes — independent of MEMORY.md and state.db. They are out of scope for the adapter's first version; only Hermes's built-in memory is mapped.
2. How Memory Is Amended
Understanding how Hermes writes memory determines what the adapter should treat as a record and how to detect change between syncs.
The memory Tool
The agent manages curated memory through a single tool with three actions — add, replace, and remove (there is no read; the content is always already in the prompt) — and two targets, memory (its own notes) and user (the user profile). replace and remove locate an entry by a unique substring. Exact-duplicate additions are rejected. Because edits persist to disk immediately but the prompt is a frozen snapshot, a write becomes visible to the agent only on the next session.
Consolidation Under the Cap
When a write would exceed the character limit, the tool returns an error and the agent consolidates in the same turn — merging related entries, dropping stale ones — then retries. This continual merge-and-prune is the defining behavior of the curated store: it is a small, living summary rather than an append-only log.
Background Self-Improvement
After a turn, an optional background review can decide to save a memory or update a skill on the agent's behalf. An optional write-approval gate can stage these writes for confirmation. From the adapter's perspective these are still agent-authored writes; where detectable, they can be tagged as background-originated.
Security Scanning
Hermes scans memory writes and context-file loads for prompt-injection and exfiltration patterns and for invisible Unicode, rejecting suspicious content before it enters the prompt. The adapter restores an archive by writing files directly to disk and re-materializing the session database, then lets Hermes re-index on next start. One consequence is worth noting for fidelity: because identity and context files are re-scanned when Hermes loads them, restored content that happens to resemble an injection pattern (for example, a security-focused agent's own notes quoting a shell command) may be skipped at load time. The adapter keeps archives Unicode-clean and can report any entries likely to be filtered on restore.
Sessions: Append & Lineage
Session history changes by accretion: new sessions are appended, an active session gains messages until it ends, and compression occasionally forks a child session linked by parent_session_id. Ended sessions are immutable. This makes session change cheap to detect — only new and still-active sessions differ between syncs.
3. How Memory Is Indexed
Hermes indexes its two memory surfaces very differently — and one of them is not indexed at all.
Curated Memory Is Not Indexed
There is no retrieval step for MEMORY.md or USER.md. They are simply injected verbatim into the system prompt, so the agent always "has" them. There is no vector index, no ranking, no chunking — recall is just presence in the prompt.
Session Search (FTS5)
Past conversations are reached through a session-search tool backed by the messages_fts FTS5 index in state.db. This is keyword full-text search over message content — it groups matches by session and returns focused results — with no vector component in the built-in path.
No Embeddings in Built-In Memory
The practical consequence: Hermes's built-in memory carries no embeddings at all. Curated memory is never vectorized, and session recall is FTS5 keyword search. The adapter therefore exports memory records with empty embedding sets. This is fully consistent with ALF, where content is authoritative and embeddings are an optional, derivable cache: a runtime that uses vectors simply re-embeds from content on import, exactly as it would for its own new memory.
4. Mapping Hermes Memory to ALF
The adapter produces two families of MemoryRecord: semantic records from curated memory, and episodic records from session history.
Record Boundary Strategy
For curated memory, each §-delimited entry in MEMORY.md becomes one record (with a graceful fallback to splitting on Markdown headings, then to the whole file, if an installation's on-disk format differs). For session history, the natural unit is the session: one episodic record per session, carrying the full conversation. (USER.md is not a memory record — it maps to the principal layer; see §5.)
Stable Record ID Generation
Hermes gives curated entries no native identifier, and the store is constantly consolidated, so a position-based ID would change every time the agent reorders or merges notes. The adapter instead derives a content-based UUIDv5 for each curated entry: identity follows the text. A pure reorder produces no change; an edit reads as the old record being superseded and a new one created. To make those revisions legible rather than invisible, the adapter tombstones entries that disappear between syncs — marking them superseded rather than silently dropping them — so the history of what the agent learned and revised is preserved. Because the curated store is tiny, re-snapshotting it on every sync is trivial.
Session records need none of this: each uses its native session ID, which is already stable and unique, so session deltas are clean — new sessions are creates, still-active sessions are updates, and lineage is preserved.
Field Mapping: MemoryRecord
Curated memory (MEMORY.md → MemoryRecord):
| ALF field | Source | Notes |
|---|---|---|
content | entry text | verbatim |
memory_type | semantic | durable notes; procedural when an entry is clearly a rule |
source.origin / origin_file | memory_md / memories/MEMORY.md | provenance |
source.extraction_method | agent_written | tagged background-originated where detectable |
temporal.* | file modification time | per-entry timestamps are not recorded by Hermes |
status | active / superseded | tombstone on consolidation/removal |
namespace | curated | |
embeddings | [] | curated memory is never vectorized |
raw_source_format | { store, entry_index } | round-trip fidelity |
Session history (one record per session). The readable transcript goes in content for search and browsing; the complete structured session is preserved in raw_source_format so the database can be rebuilt losslessly on restore:
| ALF field | Source | Notes |
|---|---|---|
id | native session ID | stable, unique |
content | session transcript | for search / browser |
memory_type | episodic | conversation events |
source.origin | session_db | |
source.session_id | session ID | populated here |
temporal.observed_at | started_at (+ message times) | from state.db |
namespace / category | session / source platform | preserves cli/telegram/discord/… |
embeddings | [] | FTS5 only |
raw_source_format | full session + messages + lineage | lossless rebuild of state.db |
Memory Type Classification
Curated entries map to semantic (durable facts and conventions), with procedural reserved for entries that are clearly rules. Sessions map to episodic (timestamped conversation events). Hermes's agent-created skills are its procedural memory, but the adapter preserves them as workspace artifacts rather than memory records so they remain re-importable (see §5).
Namespace Assignment
Curated records are namespaced curated; session records are namespaced session (optionally session:<source>), with the source platform also carried as a tag. This keeps Hermes's multi-platform history navigable — for example, filtering memory to a single channel.
Embedding Extraction
None. As covered in §3, Hermes's built-in memory has no vectors, so the embedding set is always empty. On import into a vector-using runtime, that runtime re-embeds from content.
Partition Assignment
Records are partitioned into ALF's standard quarterly buckets by creation time. Session records spread naturally across quarters by their start time; curated records cluster near export time, since Hermes does not stamp per-entry timestamps.
5. Mapping Other Layers
Identity (ALF §3.2)
Hermes's identity is prose-only. SOUL.md — the agent's primary identity, loaded into the first system-prompt slot — maps to identity.prose.soul. Custom personalities and a base system prompt defined in config.yaml map to identity.prose.custom_blocks. Hermes has no structured identity (no IDENTITY.md or schema-based traits), so those structured fields are left empty rather than fabricated.
Operating instructions are a special case. Hermes discovers context files like AGENTS.md and .cursorrules from the working directory, not from the agent's home — so they are not part of the agent by default. When a user wants them captured, the agent records them explicitly with alf add, which can reach a designated project file; the adapter then maps the captured file to identity.prose.operating_instructions and preserves it verbatim.
Principals (ALF §3.3)
USER.md maps to the primary human principal (principals[0]), with its text in profile.prose.user_profile and any clearly sectioned details parsed into structured fields. Hermes treats USER.md as a memory target; ALF models it as relationship context about the human, consistent with the OpenClaw and ZeroClaw adapters. The per-platform user identifiers seen in sessions are conversational, not relationship profiles, and are not promoted to principals.
Credentials (ALF §3.4)
Credential backup in ALF is the agent's explicit vault, not a scrape of the runtime's keystore: the agent chooses what to back up with alf vault add, each secret is encrypted client-side (XChaCha20-Poly1305, with an optional Argon2id passphrase) before it ever leaves the machine, and it travels in the archive as ciphertext. On import, the vault key decrypts the secret and restores it into the runtime. This vault is shared across adapters, so Hermes uses it directly.
Hermes is a particularly good fit because it keeps real API keys and bot tokens in ~/.hermes/.env. On first sync the adapter detects those keys and offers to add them to the vault, turning what is otherwise plaintext-at-rest into an encrypted, restorable backup in one step. The adapter never writes "metadata-only" credential entries: a record that named a credential without backing it up would imply the secret is protected when it is not. Keys it cannot read — for example, secrets held in an external manager — are reported as not backed up rather than recorded as if they were.
Skills & Workspace Artifacts
Skills are multi-file directories under ~/.hermes/skills/. The adapter exports the agent's own skills — those the user modified, the agent created, or that were installed from a hub — and skips unmodified bundled skills, which Hermes re-seeds on update. (Hermes tracks this distinction in a bundle manifest.) SKILL.md files and small companion assets travel as portable artifacts; larger assets are catalogued by reference. As noted earlier, agent-created skills are Hermes's procedural memory — preserving them as artifacts keeps their structure and re-importability intact.
Raw Source Preservation
For lossless round-trips, the adapter preserves the agent's durable text and configuration under raw/hermes/ — SOUL.md, the curated memory files, a redacted config.yaml, non-bundled skills, and bundle manifests. Three things are deliberately excluded: .env (its secrets live encrypted in the credentials layer, never as plaintext in the archive), the state.db binary (its contents are captured as records and rebuilt on restore, so duplicating the file would only add bulk), and local administrative data — checkpoints/, state-snapshots/, backups/, and logs/ — which is execution state, not the agent's memory or identity.
Multiple Profiles
Because each profile is a self-contained home, the adapter treats it as an independent agent: you point the CLI at a profile's directory and it backs up exactly that profile. The default profile and any named profiles are synced by separate commands, each with its own -w.
alf sync -r hermes -w ~/.hermes # the default profile
alf sync -r hermes -w ~/.hermes/profiles/coder # a named profile, "coder"
Every profile carries its own agent identity — derived once and then pinned inside the profile directory, so it stays stable across syncs and never collides with another profile's. Each keeps its own local sync state and rebuilds to its own archive, and on the service each registers as a distinct agent. That is what "one .alf per profile" means in practice: a machine with three profiles produces three independent backups, each advancing on its own timeline.
Isolation is structural rather than a filter. The export is an allowlist of a profile's own durable files — SOUL.md, memories/, state.db, its skills, and config — and it never descends into the sibling profiles/ directory nested beneath the default home. Backing up ~/.hermes therefore captures only the default agent, and each named profile captures only itself; their sessions and curated memory never bleed together.
Two practical notes. Each profile is synced by its own invocation today — the CLI does not yet auto-discover every profile on a machine, so a multi-profile setup is driven by one command per profile (or a small loop over the profile directories). And because the agent identity is pinned inside the profile directory, copying a profile wholesale makes the copy inherit the original's identity; profiles created normally by Hermes each receive a distinct one, so this only matters for manual directory copies.
6. Gaps, Risks, and Design Decisions
Addressed
Session history is part of the backup. Because a Hermes agent's substance is largely in its sessions, the adapter captures state.db by default and the CLI states clearly what is and isn't included.
Lossless database rebuild. Each session record carries its full structure, so restore reconstructs state.db — sessions, messages, lineage, and the FTS index — rather than approximating it. Change between syncs is computed at the record level using stable session IDs, so only new and active sessions move.
Visible memory revisions. Content-based IDs plus tombstoning mean the browser shows when the agent consolidated or retired a note, instead of hiding it as a silent disappearance.
Real credential migration. The shared vault plus .env detection makes Hermes's plaintext keys restorable as encrypted backups.
One archive per agent. A profile maps to one .alf; a machine with several profiles produces one archive each.
Accepted Limitations
No embeddings are carried. Hermes stores none; a vector-using target re-embeds from content on import. There is no cross-runtime semantic-search benefit until then, by design.
Operating instructions are opt-in. AGENTS.md and similar files are project-local, so they are captured only when the agent adds them explicitly.
External memory providers are not exported. Honcho, Mem0, and similar plugins keep their own stores outside Hermes's built-in memory and are out of scope for the first version.
Load-time scanning may filter some restored content. Hermes re-scans identity and context files on load, so restored content resembling an injection pattern can be skipped; the adapter keeps archives clean and can flag likely cases.
Externally managed secrets are opaque. Keys held in an external secret manager cannot be read or vaulted by the adapter and are reported as not backed up.
ALF Type Fitness Assessment
| Hermes concept | ALF type | Fit |
|---|---|---|
Curated entry (MEMORY.md) | MemoryRecord (semantic) | Direct. |
Session (state.db) | MemoryRecord (episodic) + raw_source_format | Native ID plus lossless rebuild. |
| No embeddings | embeddings: [] | Optional by spec. |
SOUL.md (prose, no structured) | identity.prose.soul | Prose-only identity is supported. |
USER.md | Principal prose profile | Same as OpenClaw/ZeroClaw. |
.env secrets | Shared ALF vault (Layer 4) | Zero-knowledge Encrypted, restorable. |
| Skills (non-bundled) | Workspace artifacts | Three-tier artifact model. |
| Profiles | One archive per agent | No new concept needed. |
| Session source / entry index | category / raw_source_format | Fidelity slots exist. |
Hermes maps cleanly onto ALF's existing types: a small prose-first memory, a session database that decomposes into episodic records and rebuilds losslessly, prose identity, and credentials handled by the shared vault.
7. References
Hermes (Nous Research): Persistent Memory, Sessions, Personality & SOUL.md, Context Files, Profiles, Skills, and Secrets — in the Hermes user guide at hermes-agent.nousresearch.com/docs.
Agent Life Format: the ALF Specification, and the companion adapter guides for OpenClaw and ZeroClaw.