Skip to content

Memory

Each agent profile has a persistent memory store — typed key-value rows scoped to (user, profile). The agent reads/writes via the memory MCP server (mcp__memory__memory_* tools). Memory survives across sessions, so an agent in workspace A can write something and an agent in workspace B (same profile) can read it.

This is the platform’s way of giving agents continuity. Without it, every container is amnesiac.

  • User profile — what the user does, prefers, expects. (“Amen runs a household budget; pay weeks always Friday; uses NFCU mainly.”)
  • Project state — (“Currently refactoring the auth middleware; PR #157 reverted; rollout on hold.”)
  • Reference pointers — (“Bug reports live in Linear project INGEST. Dashboard at grafana.internal/d/api-latency.”)
  • Feedback / guidance — corrections the user gave that should stick. (“Don’t auto-merge SDK bumps. Always patch bump unless told otherwise.”)

What it’s NOT good for: high-volume / structured data. Memory is sparse + narrative-style. Put your transactions in Supabase, not in memory.

Each row:

FieldNotes
idmem_<nanoid>.
user_id, profile_idOwner. profile_id can be null for “global” memory across all profiles.
typeuser / feedback / project / reference. Helps the agent pick what to recall.
nameSlug-style identifier (user_profile, feedback_no_db_mocking, project_q3_outage).
descriptionOne-line summary the agent surfaces during memory_list.
bodyThe actual content (markdown).
importanceInteger ordering hint.
created_at, updated_at, last_accessed_atTimestamps.

Two profiles owned by the same user have separate memory. This is intentional — your coding agent shouldn’t be coloring its responses by what your finance agent has learned about your bank balances.

If you want shared memory, set profile_id = null on a memory row (admin-only currently — use the REST API).

The orchestrator pre-builds a “memory section” at session start: a list of all memory row descriptions, prefixed to the system prompt. The agent sees this on every turn and can decide which to read in full via memory_read.

When the agent writes new memory (via memory_write), the row is appended to Postgres and surfaces in the next session’s prompt.

Memory has its own REST surface for power users and migrations:

EndpointPurpose
GET /v1/memoriesList your memory rows (across all profiles).
POST /v1/memoriesCreate a row.
GET /v1/memories/:idRead one.
PATCH /v1/memories/:idUpdate.
DELETE /v1/memories/:idDelete.

The dashboard’s Memories tab is a CRUD view over these endpoints.

Best practices for claude_md-encoded memory rules

Section titled “Best practices for claude_md-encoded memory rules”

Tell the agent in its claude_md how to use memory. For example:

Memory protocol:
- Read user_profile + relevant project memories on every turn (already in the
system prompt; act on them).
- After ANY user instruction that changes how I should work in future, write
a `feedback` memory with the rule + reason.
- Don't write throwaway memories (per-turn state). Use them for things that
matter across sessions.