Its been a while since I wrote a blog post. The catch-up post for the last three weeks just went up here. This one is the deep-dive on the headline: v3.10 ships the L3 persona layer, and v3.9 right before it shipped the bidirectional sync engine. Both released the same day (June 18). Different shapes, both worth their own paragraph.
Why Persona
Working memory in Mnemosyne had a 24-hour TTL until v3.7.0 bumped it to 168 hours with usage-driven decay. Episodic memory and canonical facts both survive longer than that. But none of those layers are about behavior: how the agent should respond to a frustrated user, what formatting style they prefer, which opinions to hold with what strength. That information lives in conversation context for a day and then evaporates.
The persona layer fixes that. It is an L3 tier above working memory, above episodic memory, above canonical facts. Its job is to capture the behavioral rules a user has demonstrated over time and keep them active in the system prompt across sessions.
Not "what we remembered about the user." Not "what facts we know." "How this agent should show up, every time, regardless of session."
How It Works
Three pieces. The schema, the extractor, and the injection.
1. The schema: tiered retention
New SQLite table,
memoria_persona,
with three retention tiers:
- permanent: rules the agent should never forget (communication style, ethical constraints, identity-defining preferences)
- long_term: rules that should persist across many sessions but can be revised (current project focus, active domains of interest)
- working: rules that ride along with active context (this week's debugging style, current feature's naming convention)
Each tier has different decay semantics. Permanent rules have no decay. Long-term rules decay on the order of months. Working rules behave like working memory (24h TTL by default, usage-bumped).
2. The extractor: rule-based, no LLM by default
The extractor reads working memory and episodic memory, filters by source and importance, deduplicates by topic, and renders the result as Markdown grouped by topic. No LLM call. Deterministic. Zero cost.
Five trigger conditions regenerate the persona file, matching the Hy-Memory PersonaTrigger pattern:
- Explicit request: user or code asks for persona refresh
- Cold start: first session, no persona.md exists yet
- Recovery: after a crash or interrupted sleep pass
- Threshold: every N new memories (default 50)
- Daily sync window: once per day during sleep if other triggers have not fired
3. The injection: persona.md into the system prompt
The extractor writes
~/.hermes/memory/persona.md.
The Hermes provider reads it inside
system_prompt_block()
and includes it in the system prompt. Mtime-cached: if the file has
not changed since the last read, no file I/O on the hot path.
Token cap enforced via
MNEMOSYNE_PERSONA_TOKEN_CAP
(default 1500). Past the cap, the persona is truncated with a
marker, not silently dropped.
The Four Tools
Total tool count: 28 to 32 with the persona layer.
| Tool | Purpose |
|---|---|
| mnemosyne_persona_promote | Move a working-memory item into the persona layer at a chosen tier |
| mnemosyne_persona_demote | Remove an item from the persona layer (optionally archive it elsewhere) |
| mnemosyne_persona_list | List active persona rules, optionally filtered by tier |
| mnemosyne_persona_reinforce | Bump confidence on an existing persona rule after another observed instance |
Promote is the entry point: an agent recognizes "this user really hates bullet points" or "this user always wants error messages in Spanish" and promotes that observation to a persona rule. Demote is the exit when context shifts. List is the inspection path. Reinforce handles the case where the same rule gets observed again later: confidence bumps, no duplicate row.
v3.9.0: The Sync Engine (Same Day)
v3.10.0 shipped on June 18, 2026. v3.9.0 shipped the same day with the production hardening for the bidirectional sync engine that v3.8.0 had introduced. Both releases belong in the same breath.
Sync is event-log-based: each Mnemosyne instance appends to a
memory_events
table, and delta sync between instances uses that log with conflict
detection. Stdlib-only HTTP sync server (no FastAPI dependency). CLI:
mnemosyne sync,
sync-serve,
sync-status,
sync-generate-key.
Optional client-side encryption via Fernet/XSalsa20, with passphrase
or key-manager key sources. Causal version chains resolve conflicts
deterministically.
v3.9.0 specifically added:
- Hermes plugin upgrade path:
mnemosyne-hermes upgradewith install-method detection (pipx / uv-tool / pip), version comparison, auto re-register (PR #319) - Hermes plugin cleanup:
mnemosyne-hermes cleanupremoves plugin + old hermes-mnemosyne directory + resets config, with--dry-runsafe (PR #317) - Hermes status diagnostic: shows Hermes Python version with mismatch warning (PR #316)
- Sync tool schemas: SYNC_PUSH, SYNC_PULL, SYNC_STATUS added to both Hermes provider and standalone plugin copies (tool count 25 to 28)
- fact_recall relevance scoring: FTS rank order preserved, scoring switched to
relevance * confidence, full subject-predicate-object triples returned as content. Opt-in viaMNEMOSYNE_FACT_RECALL_ENABLED - Audit log table rename:
memory_eventswas being claimed by both the sync engine and the audit log. Audit log is nowaudit_log. Sync keepsmemory_events. Different concerns, different tables.
Full sync tutorial, troubleshooting guide, and deploy configs (Docker, Caddy, Fly.io) ship with v3.9.0.
How to Turn It On
v3.10.0 ships with persona default OFF. The opt-in story is a single env var:
{`export MNEMOSYNE_PERSONA_ENABLED=true
export MNEMOSYNE_PERSONA_TOKEN_CAP=1500 # default if unset
pipx install --upgrade mnemosyne-memory
pipx runpip mnemosyne-memory install hermes-agent # if using the plugin`}
Restart Hermes. The persona file at
~/.hermes/memory/persona.md
gets generated on the first cold start trigger, then maintained
automatically as you accumulate working memory.
To pre-seed persona rules from existing memory, run the cold-start trigger manually by deleting the persona file. The extractor will rebuild from your working and episodic memory on next init.
What This Does Not Change
Honest notes so you can plan the upgrade:
- Schema migration is additive. Existing tables are untouched. No re-init, no data migration, no backup required.
- No breaking changes to
mnemosyne_rememberormnemosyne_recall. Existing prompts and tool flows work exactly as before. - Default OFF. The persona layer does not touch your prompt until you opt in.
- No new dependency. Pure SQLite + stdlib, like the rest of Mnemosyne.
- No LLM cost for the default extractor. Rule-based, deterministic, runs at memory write time.
What I Think This Means
Long-running agents have a personality problem that does not exist for short-running ones. A coding assistant that has worked with you for three months should know you hate verbose explanations, prefer Python over JavaScript, and always want tests in the same place. None of that is "fact" in the canonical-facts sense. None of it fits in working memory. All of it makes the agent better.
Persona is the layer for that. It is small right now: four tools, one table, one env var. The shape of what it grows into is up to whoever uses it. That is the right starting point.
Install with pipx install mnemosyne-memory.
Try it on a long-running assistant. Tell me what is missing. The
persona layer is meant to grow from real usage, not from a spec.
Same Discord, same repo. More posts going forward. Promise again.

