Hermes Skills vs Memory vs Fact Store: The Storage Decision
Three storage surfaces, three jobs. Use this duration / reuse / scope rubric to put a fact in the right place, plus the bad-shape markers that tell you the rubric is failing.

The decision in one sentence
Skills are procedures loaded on demand, memory is always-loaded fact about the user, and fact_store is structured entity data the agent queries — pick by asking how long it must live, how often it is reused, and how widely it applies.
The three surfaces look interchangeable because they all hold “things the agent should know.” They are not interchangeable. Each one costs something different, loads at a different time, and breaks in a different way when misused.
This guide is the operational sequel to Hermes Agent Memory vs Skills. That one explains where things belong. This one explains how to decide when the answer is not obvious, and what the failure modes look like when the decision has gone wrong.
The three jobs, sharply
- Skills — how to do a recurring thing. A procedure with numbered steps, exact commands, a pitfalls list, and a verification step. Lives in
~/.hermes/skills/<name>/SKILL.md. Loaded only when the agent judges the task matches. Cost: paid per use, only for the relevant skill. - Memory — always-on context about you. Durable preferences, project facts, working style, names, decisions. Lives in
MEMORY.mdand is injected into every turn. Cost: paid every turn, forever. - Fact store — retrievable structured facts. Entity-shaped data with typed fields and relations. Lives in
~/.hermes/facts/<entity>/...and is queried on demand. Cost: paid per query, but cheap per fact because the structure compresses well.
The shape of what you are storing — prose vs procedure vs entity — should drive the choice, not the convenience of where you happen to be editing.
The rubric: duration, reuse, scope
When the placement is unclear, score the candidate on three axes. The intersection picks the surface.
| Axis | Skill | Memory | Fact store |
|---|---|---|---|
| Duration | Permanent until you rewrite the procedure | Permanent until you prune | Permanent until the entity changes |
| Reuse | High (every recurrence of the task) | Universal (every turn, every session) | Medium (queries when the entity comes up) |
| Scope | Narrow — one workflow, one domain | Broad — anything about the operator | Targeted — one entity and its relations |
| Loaded when? | On demand, by trigger match | Every turn, always | On demand, by query |
| Cost shape | Per-use, only the matched skill | Per-turn, the whole MEMORY.md | Per-query, only the matched entity |
| Failure shape | Stale steps, missing pitfalls | Bloated, noisy, dilutes signal | Schema rot, dangling relations |
A simple decision flow:
- If it is a procedure with steps, it is a skill. Always.
- If it is a fact about the operator (name, role, preference, project decision) that applies every turn, it is memory.
- If it is an entity with typed fields and relations that you will query by name, it is fact_store.
- If two boxes both fit, prefer the one with the lower load cost. Memory is the most expensive; reach for it last.
When each is right
Use skills for
- Recurring workflows with discrete steps (“publish a post”, “deploy a cron”, “rotate R2 credentials”).
- Hard-won procedural knowledge: pitfalls, exact commands, the failure that cost you an hour last Tuesday.
- Anything you would otherwise rewrite from scratch every time.
- Per-task context that should not bleed into other tasks.
The skill body should be action-shaped: numbered steps, code blocks ready to paste, a “pitfalls” section, a “verify” line. If you find yourself writing essays in a skill, it is probably memory wearing a costume.
Use memory for
- Operator identity and preferences (name, pronouns, timezone, working hours, communication style).
- Project-level decisions the agent should never re-derive (“we use Astro for the site”, “the VPS is on Hostinger”).
- Recurring corrections (“do not auto-tag with bare years”, “always quote numeric tags”).
- Cross-session anchors — the small set of facts every conversation depends on.
The memory body should be declarative and short. Each entry answers one question in one or two sentences. If it does not apply every turn, it does not belong here.
Use fact_store for
- Entity-heavy data with structure: customers, stores, products, servers, recurring contacts.
- Records you will query by attribute (“the NATT store with the lowest 7-day revenue”, “the cron job that failed last night”).
- Anything where a flat prose list in memory would force the agent to re-parse it every turn.
The fact_store body should be typed and relational: each entity has a schema, fields are predictable, and links between entities are explicit. Prose in a fact is a smell.
The bad-shape markers
Each surface breaks in its own way. Watch for the markers; they tell you the rubric is being misused.
Memory is wrong when
- MEMORY.md exceeds ~2,000 words. The always-on budget is small. Past that, the signal-to-noise ratio collapses and the agent starts ignoring memory entries at random. If you are past 2,000 words, you are storing skills and facts in memory.
- Entries are dated or versioned. “On 2026-07-10 I decided…” is a session log entry, not a memory entry. Promote to a skill, a fact, or a handoff document and remove from memory.
A skill is wrong when
- The skill is one or two lines. A 40-token “always remember X” is not a procedure; it is a memory entry pretending to be a skill. Skills earn their keep by being loaded only on the matching task — a one-liner has no matching trigger logic and just bloats the skill registry.
- The skill is an essay with no numbered steps. If a SKILL.md is paragraphs of prose and no code, it is documentation, not a procedure. Either rewrite it as numbered steps with commands, or move the content to memory or a doc.
A fact_store entry is wrong when
- It has no relations and no typed fields. A free-text blob in fact_store is memory wearing a structured costume. If you are not going to query by field, do not store it as a fact.
- It duplicates a recurring workflow. If a fact describes “how to do X,” it is a procedure; promote to a skill. Fact_store answers “what is X,” not “how do I do X.”
The migration path
When you spot a bad-shape marker, the fix is mechanical:
- Memory bloat → extract procedures to skills, extract entities to fact_store, keep only the cross-session anchors.
- Skill-as-memory → fold the one-liner into
MEMORY.mdand delete the skill. - Fact_store-as-skill → rewrite the SKILL.md as numbered steps and delete the fact, or keep both only if the fact is queried by field and the procedure is a workflow that touches it.
The goal is not symmetry across the three surfaces. The goal is that each surface earns its load cost.
A worked example
You want to capture: “The NATT America 250 store ships from Printify US-East, with a 4-day average fulfillment.”
- As a skill? No — it is not a procedure.
- As memory? Borderline — it applies every turn you talk about NATT. But it is one fact among many stores; memory would drown in them.
- As fact_store? Yes — typed fields (
store,supplier,region,avg_fulfillment_days), queryable by region, relational to the other NATT stores.
The same content under a different shape would land somewhere else: “When debugging Printify delays, check the fulfillment queue first” is a procedure — that is a skill. “We use Printify for all POD” is a preference that applies every turn — that is memory.
Sources
- Hermes docs: Skills, Memory, Fact Store
- Companion: Hermes Agent Memory vs Skills — the foundational “where things belong” guide
- Companion: ABS Chat with Skills and Memory — how the three surfaces behave at chat-session scope
Last verified: 2026-07-14 against the Hermes docs and the operator-rubric framing introduced alongside the storage-decision guide.


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.