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.
What memory is good for
Section titled “What memory is good for”- 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.
Memory shape
Section titled “Memory shape”Each row:
| Field | Notes |
|---|---|
id | mem_<nanoid>. |
user_id, profile_id | Owner. profile_id can be null for “global” memory across all profiles. |
type | user / feedback / project / reference. Helps the agent pick what to recall. |
name | Slug-style identifier (user_profile, feedback_no_db_mocking, project_q3_outage). |
description | One-line summary the agent surfaces during memory_list. |
body | The actual content (markdown). |
importance | Integer ordering hint. |
created_at, updated_at, last_accessed_at | Timestamps. |
Memory namespace per profile
Section titled “Memory namespace per profile”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).
How the agent uses it
Section titled “How the agent uses it”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.
Manually managing memory
Section titled “Manually managing memory”Memory has its own REST surface for power users and migrations:
| Endpoint | Purpose |
|---|---|
GET /v1/memories | List your memory rows (across all profiles). |
POST /v1/memories | Create a row. |
GET /v1/memories/:id | Read one. |
PATCH /v1/memories/:id | Update. |
DELETE /v1/memories/:id | Delete. |
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.