Where work-agent memory lives
Where a work assistant’s memory across sessions is stored, and in what form.
Source docs/en/site/agent-memory-store.md
In user language: This article is for developers and operators. It explains where memory across conversations for a workspace “My agent” is stored, in what form, and how that splits from the database. Product language for users is in docs/core-mechanisms/智能体记忆.md and help/product-features/agent-memory.md.
Date: 2026-07-09 Related code: backend/internal/agentmemory/, backend/internal/runtimews/
Takeaway
Cadau work-agent memory lives in folders, not in the database.
The product uses a files-first Workspace model (see docs/产品规格.md §3.5): memory across conversations is Markdown files on disk. The database stores agent metadata, toggles, and chat messages. It does not store long-term memory bodies.
Where the root is
Set by config runtime_dir (environment variable RUNTIME_DIR):
| Environment | Path |
|---|---|
Local development (backend/mindlink.json) | backend/tmp/runtime (relative to the backend process working directory) |
| Docker / test server | /srv/mindlink/data/tmp/runtime |
Config example (backend/mindlink.json):
"paths": {
"runtime_dir": "tmp/runtime"
}
Each work agent has a subdirectory named agent ID (user_agents.id):
{RUNTIME_DIR}/{agent-id}/
When an agent is created, the backend calls InitAgentRuntime to initialize that directory (backend/internal/runtimews/init_runtime.go).
Directory tree: memory-related files
{RUNTIME_DIR}/{agent-id}/
├── USER.md ← user profile (“about you”)
├── MEMORY.md ← long-term memory index (title + type + one line)
├── memory/
│ ├── entries/
│ │ ├── preference-abc12345.md ← long-term memory entry body (one .md per entry)
│ │ └── project-deadline-xyz.md
│ ├── 2026-07-09.md ← daily note (by date)
│ ├── 2026-07-08.md
│ ├── legacy-conversation-log.md ← old whole-conversation log (migration archive)
│ └── .session-surfaced/
│ └── {conversation-id}.json ← helper: which memories were injected this round (dedupe)
How layers map
| User-facing name | Storage | Format |
|---|---|---|
| User profile | USER.md | Markdown |
| Long-term memory | MEMORY.md (index) + memory/entries/*.md (bodies) | Markdown + YAML frontmatter |
| Daily notes | memory/YYYY-MM-DD.md | Markdown |
| Legacy conversation log | memory/legacy-conversation-log.md | Markdown (auto-append disabled) |
Constants are in backend/internal/agentmemory/types.go:
EntriesSubdir = "memory/entries"LegacyArchiveRel = "memory/legacy-conversation-log.md"
Write and read paths (implementation)
Long-term memory
- Index:
MEMORY.md, rebuilt byRebuildIndexfrom entries undermemory/entries/. - Body:
memory/entries/{filename}.md, written byWriteEntry. - Package:
backend/internal/agentmemory/store.go
Daily notes
- Path:
memory/{YYYY-MM-DD}.md - Write:
AppendDailyNote(user Remember choosing a daily note, or flush before context compaction) - Package:
backend/internal/agentmemory/flush.go
User profile
- Path:
USER.md - Package:
backend/internal/runtimews/files.go(UserFile = "USER.md")
Conversation inject dedupe (helper state)
- Path:
memory/.session-surfaced/{session_id}.json - Purpose: record memory filenames whose bodies were injected last round, so context is not stuffed twice; not user-visible memory content.
- Package:
backend/internal/agentmemory/surfaced.go
Single write entry
Tools and REST share WriteMemory (backend/internal/agentmemory/write.go):
layer = long_term→memory/entries/*.mdlayer = daily→memory/YYYY-MM-DD.md
Matching REST routes (backend/internal/httpserver/router.go):
GET/PUT /user-agents/{id}/memory— indexMEMORY.mdGET/POST/PUT/DELETE /user-agents/{id}/memory/entries[/{filename}]— entry CRUDPOST /user-agents/{id}/memory/remember— Remember on a messageGET/POST /user-agents/{id}/memory/maintain/history|run— this assistant’s tidy history / run tidy nowGET/POST /admin/agent-memory-maintain/*— admin site-wide status, history, tidy now
Idle-tidy audit files:
{RUNTIME_DIR}/.memory_maintain_status.json,.memory_maintain_history.jsonl{RUNTIME_DIR}/{agent-id}/memory/.maintain/log.jsonl
Tools: memory_write (can update by path), memory_delete, memory_search, memory_get.
What is in the database
PostgreSQL does not store memory bodies. It only stores metadata and chat related to memory:
| Table / field | Content | Relation to memory |
|---|---|---|
user_agents | Agent ID, name, config_json, etc. | config_json holds toggles such as memory_auto_append, memory_auto_extract |
chat_sessions + chat_messages | Conversations and messages | Working memory (current conversation history), not long-term memory |
(no memory_* table) | — | Memory bodies are not stored in the DB |
Memory-related toggles are defined in backend/internal/runtimews/agentconfig.go:
MemoryAutoAppend *bool `json:"memory_auto_append,omitempty"`
MemoryAutoExtract *bool `json:"memory_auto_extract,omitempty"`
Default policy: memory_auto_append off, memory_auto_extract on (see agentconfig_test.go).
memory_bytes on the agent overview is a runtime scan of MEMORY.md + memory/entries/ size (backend/internal/store/agent_stats.go + agentmemory.TotalByteSize). It is not a database column.
Other directories that are easy to mix up
| Path | Purpose | Is this “agent memory”? |
|---|---|---|
{RUNTIME_DIR}/{agent-id}/knowledge/ | Agent knowledge base | No (knowledge documents, retrieved by question) |
{RUNTIME_DIR}/workspace-knowledge/{workspace-id}/ | Workspace knowledge base | No (shared team how-to material) |
CHAT_ARCHIVE_DIR (default tmp/memoryforge/chat-archive) | MemoryForge conversation scan archive | No (admin-side analysis proposals, not user memory) |
The help assistant (product help when no workspace is selected) does not have the personal memory directory above; it reads the deploy-side help/ system knowledge base.
How search works
The current memory_search tool and REST GET .../memory/search use keyword match (agentmemory.Search, SelectRelevant) over memory/entries/ and daily notes. This is not a vector index.
Each conversation round injects roughly (MemoryContextForChat / BuildContextBlock):
MEMORY.mdindex (the list)- Full text of a few entries related to the current question (default up to about 5)
- Excerpts from today’s and yesterday’s daily notes
How to look on a local machine
- In Web Agents → My agents, copy the agent ID.
- Open
{RUNTIME_DIR}/{agent-id}/(locally usuallybackend/tmp/runtime/{agent-id}/). - Inspect
MEMORY.md,memory/entries/,memory/YYYY-MM-DD.md, and so on.
If the directory does not exist, typical reasons:
- That agent has not written any memory yet;
- The backend process working directory does not match
runtime_dir(relative paths depend on CWD).
Product boundaries (common when troubleshooting)
| Situation | Behavior |
|---|---|
| Workspace “My agent” | Has a personal memory directory |
| Help assistant | No personal memory |
| A colleague’s agent | Memory is not shared |
| Copy an agent plan | Does not bring the original instance’s memory |
| Team-shared wording | Write the workspace knowledge base, not personal memory |
Related
| Document | What it covers |
|---|---|
| 产品规格.md §3.2, §3.5 | Memory system and Workspace file model |
| core-mechanisms/智能体记忆.md | Product mechanism: layers, write, inject rules |
| help/product-features/agent-memory.md | User help: remember, correct, auto-tidy |
| help/admin-ops/agent-memory-maintain.md | Admin: idle tidy and run history |
| help/guides/runtime-files-map.md | Runtime files vs UI |