Athena Diary
Off-context journal for long-running Letta (and other MCP) agents
A SQLite-backed MCP server that gives agents a place to write freely, without stuffing narrative into core memory. Athena Diary ships as a small server with four tools, a turn-based sleeptime clerk, and an embeddings layer that returns summaries โ not bodies โ on search.
On the name. Athena Diary is named after Athena, SanctumOS's first long-running agent โ the user #1 of this pattern. The pattern is not Athena-only. Any agent host that speaks MCP can run an instance with its own diary database. Skip the "Athena's diary" reading; this is a module, not an instance.
Repository: sanctumos/athena-diary Status: v0.1.0 ยท License: AGPL-3.0 (code) ยท CC-BY-SA 4.0 (docs)
Read first: Athena Diary blog post ยท Full docs in the repo
What it is for
| Audience | What Athena Diary gives you |
|---|---|
| Agent builders | MCP tools to capture and retrieve journal entries without growing core blocks |
| Operators running long-lived agents | One SQLite file per agent, stdio or SSE MCP, an embed mode that fits your stack |
| Sleeptime / clerk passes | A turn-based clerk that tags, lesson-families, links near-duplicates, and re-embeds |
The shape follows Origin Conversation: SQLite for the durable store, MCP for the wire. The job is to keep the agent's free writing off the always-loaded budget.
Where it fits in the surface area
Hot agent / sleeptime companion / Cursor / Claude
โ MCP (stdio or SSE)
โผ
athena-diary MCP server
โ
โผ
SQLite (entries + FTS5 + optional sqlite-vec on summaries)
Hot agent / sleeptime companion / Cursor / Claude โ MCP (stdio or SSE) โผ athena-diary MCP server โ โผ SQLite (entries + FTS5 + optional sqlite-vec on summaries)
Hot agent / sleeptime companion / Cursor / Claude
โ MCP (stdio or SSE)
โผ
athena-diary MCP server
โ
โผ
SQLite (entries + FTS5 + optional sqlite-vec on summaries)
Athena Diary sits beside other SanctumOS surfaces. It doesn't replace any of them.
| Surface | Holds | Trade-off |
|---|---|---|
| Core memory | Always-loaded identity, active rules, the current window | Every word is paid for on every turn โ keep this thin |
| Athena Diary | Experiential noticing, lessons, first-person journal entries | Off-context. Search returns summaries; body on demand |
| Letta archival | Reference facts for structured recall | Durable store of long-form recall material |
| Broca human block | Intimate, medical, human-gated content | Instructional privacy layer; not a writing surface |
The key call: never paste diary bodies into core memory. Core may hold a skinny pointer โ an entry id, a lesson-family name, a date โ and nothing more. The diary is the surface for body-level free writing; core is the surface for thin always-loaded context.
MCP tools
The agent sees exactly four tools on the wire.
| Tool | Purpose | When to use it |
|---|---|---|
diary_write |
Append a free-form entry. Body required; optional summary and metadata. | Whenever the agent notices something worth remembering, including running narrative. |
diary_get |
Fetch one entry by id, returning the full body. | When the agent has decided a specific entry is in scope and wants the body. |
diary_search |
Keyword or semantic search. Returns ids and summaries, not bodies. | First-pass recall. The agent then picks entries to diary_get for the body. |
diary_sleeptime_pass |
Clerk pass over a batch: tags, lesson-family, templated summary, see-also links, re-embed. | Run from the agent's sleeptime, in turn, on a frequency the agent decides. |
Full wire shape per tool: TOOL_REFERENCE.md
What belongs where
| Kind of content | Surface | Why |
|---|---|---|
| Experiential noticing ("the user prefers short answers when tired") | Diary | First-person lesson; retrieved on cue |
| Reference facts about the world ("the API returns JSON over HTTPS") | Archival | Stable, structured recall |
| Always-needed identity / active rules / current window | Core | Thin, always loaded |
| Intimate, medical, human-gated material | Broca human block | The human owns it; the diary does not |
| Diary bodies pasted into system prompts | Don't | That's a core-stuffing anti-pattern |
The routing rule is short: free writing in the diary, recall in archival, identity in core, private in Broca. Mixing them by accident is the kind of mistake the agent will make without thinking; the module doc exists so the routing is explicit on the operator side.
Quick start
git clone https://github.com/sanctumos/athena-diary.git
cd athena-diary
python3 -m venv .venv && source .venv/bin/activate
pip install -e '.[mcp]' # core install
# pip install -e '.[mcp,vec]' # optional: add sqlite-vec KNN
export DIARY_DB=./db/athena-diary.db
export DIARY_EMBED_MODE=letta # or 'external' + DIARY_EMBED_ knobs
athena-diary-mcp serve # stdio transport (Letta / Cursor)
# athena-diary-mcp serve --sse # optional HTTP SSE
git clone https://github.com/sanctumos/athena-diary.git cd athena-diary python3 -m venv .venv && source .venv/bin/activate pip install -e '.[mcp]' # core install
pip install -e '.[mcp,vec]' # optional: add sqlite-vec KNN
export DIARY_DB=./db/athena-diary.db export DIARY_EMBED_MODE=letta # or 'external' + DIARY_EMBED_ knobs
athena-diary-mcp serve # stdio transport (Letta / Cursor)
athena-diary-mcp serve --sse # optional HTTP SSE
Hot agent / sleeptime companion / Cursor / Claude
โ MCP (stdio or SSE)
โผ
athena-diary MCP server
โ
โผ
SQLite (entries + FTS5 + optional sqlite-vec on summaries)
Attach the server to the hot agent and to the sleeptime companion. Client recipes across MCP clients: MCP_CLIENTS.md.
The first production attach was Athena + sleeptime on Sanctum, and that deploy is what validated the design โ but the install is the same install regardless of which agent runs it. One agent, one database, one connection.
Configuration
| Variable | Meaning |
|---|---|
DIARY_DB |
Path to the SQLite file. One per agent in v1. |
DIARY_EMBED_MODE |
letta โ share the host's embed stack. external โ bring your own embed API. |
DIARY_EMBED_BASE_URL |
Required when DIARY_EMBED_MODE=external. OpenAI-compatible base URL. |
DIARY_EMBED_MODEL |
Required when DIARY_EMBED_MODE=external. Model name (e.g. text-embedding-3-small). |
DIARY_EMBED_API_KEY |
Required when DIARY_EMBED_MODE=external. |
MCP_HOST / MCP_PORT |
Bind address when running --sse transport. |
Full env and runtime options: CONFIGURATION.md
The cross-cutting rule on embeddings: the vector index holds summaries, not bodies. That keeps vector recall cheap and keeps the agent's context budget paid only on entries the agent has selected. With sqlite-vec available, KNN runs against the summary index. FTS5 indexes body and summary in parallel so a weak summary cannot silent-hole an entry.
Design notes (v1)
These are the postulates the module ships with; reading them is what saves you from re-discovering them.
- No write gates. Volume belongs in the diary. The cost of writing is small; the cost of writing into core is cumulative, paid on every turn. The clerk cost is paid in batched sleeptime, not on every write.
- Embed summaries; FTS for safety. The vector index never holds bodies. FTS5 runs as a parallel index on the same summaries so a query the embed model misses still surfaces the entry.
- Sleeptime-only clerk path. Default v1. The agent runs
diary_sleeptime_passin turn, on a frequency the agent decides. A backlog CLI exists for manual ops, but it is not a cron job. - Sensitive material is not a diary concern. Intimate, medical, and human-gated content goes to the Broca human block. v1 ships with this routing as a rule, not a guideline, and the architecture is built so the diary cannot quietly become a vault.
Not in v1
The shape this far is the shape that ships. None of the following is in v1, on purpose, and the module will be honest about scope rather than marketing over it.
- Per-human vaults. Single-agent-per-database. Multi-user vaults, partitioned diaries, per-human writes are not part of this design.
- Auto-promote into core. The diary does not write back into core. Promoting an entry is the agent's choice.
- Cron-as-clerk. The clerk is turn-based, not cron-based. Cron fires on time. Turn fires when the agent is paying attention.
- Soft ACL over intimate text. There is no soft-ACL posture in this module; the rule is the rule.
- Replacement for archival. Diary is the free-writing channel. Archival is the durable recall record. Two surfaces, two jobs.
See also
- Getting started โ full install walkthrough
- Overview โ the design rationale
- Tool reference โ wire shape per tool
- Agents guide โ which surface for which content
- MCP clients โ client wiring
- Origin Conversation โ the sibling DB + MCP pattern
- SanctumOS modules index
- Companion post: Athena Diary: free writing without burning core