All posts
Updated

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):

EnvironmentPath
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 nameStorageFormat
User profileUSER.mdMarkdown
Long-term memoryMEMORY.md (index) + memory/entries/*.md (bodies)Markdown + YAML frontmatter
Daily notesmemory/YYYY-MM-DD.mdMarkdown
Legacy conversation logmemory/legacy-conversation-log.mdMarkdown (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 by RebuildIndex from entries under memory/entries/.
  • Body: memory/entries/{filename}.md, written by WriteEntry.
  • 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_termmemory/entries/*.md
  • layer = dailymemory/YYYY-MM-DD.md

Matching REST routes (backend/internal/httpserver/router.go):

  • GET/PUT /user-agents/{id}/memory — index MEMORY.md
  • GET/POST/PUT/DELETE /user-agents/{id}/memory/entries[/{filename}] — entry CRUD
  • POST /user-agents/{id}/memory/rememberRemember on a message
  • GET/POST /user-agents/{id}/memory/maintain/history|run — this assistant’s tidy history / run tidy now
  • GET/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 / fieldContentRelation to memory
user_agentsAgent ID, name, config_json, etc.config_json holds toggles such as memory_auto_append, memory_auto_extract
chat_sessions + chat_messagesConversations and messagesWorking 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

PathPurposeIs this “agent memory”?
{RUNTIME_DIR}/{agent-id}/knowledge/Agent knowledge baseNo (knowledge documents, retrieved by question)
{RUNTIME_DIR}/workspace-knowledge/{workspace-id}/Workspace knowledge baseNo (shared team how-to material)
CHAT_ARCHIVE_DIR (default tmp/memoryforge/chat-archive)MemoryForge conversation scan archiveNo (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):

  1. MEMORY.md index (the list)
  2. Full text of a few entries related to the current question (default up to about 5)
  3. Excerpts from today’s and yesterday’s daily notes

How to look on a local machine

  1. In Web Agents → My agents, copy the agent ID.
  2. Open {RUNTIME_DIR}/{agent-id}/ (locally usually backend/tmp/runtime/{agent-id}/).
  3. 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)

SituationBehavior
Workspace “My agent”Has a personal memory directory
Help assistantNo personal memory
A colleague’s agentMemory is not shared
Copy an agent planDoes not bring the original instance’s memory
Team-shared wordingWrite the workspace knowledge base, not personal memory

Related

DocumentWhat it covers
产品规格.md §3.2, §3.5Memory system and Workspace file model
core-mechanisms/智能体记忆.mdProduct mechanism: layers, write, inject rules
help/product-features/agent-memory.mdUser help: remember, correct, auto-tidy
help/admin-ops/agent-memory-maintain.mdAdmin: idle tidy and run history
help/guides/runtime-files-map.mdRuntime files vs UI