{"title":"Memory Best Practices","slug":"memory-best-practices","category":"guides","summary":"How to structure memories for effective recall — categories, keys, tags, priorities.","audience":["human","llm"],"tags":["guide","memory","best-practices","patterns"],"difficulty":"intermediate","updated":"2026-06-27","word_count":605,"read_minutes":3,"lang":"en","translated":true,"requested_lang":"en","content_markdown":"\n# Memory Best Practices\n\nHow you structure memories determines how useful they are. This guide covers\npatterns for categorizing, tagging, and prioritizing memories so the LLM can\nrecall the right information at the right time.\n\n## Categories: Pick the Most Specific\n\n| Category | Use For | Example |\n|----------|---------|---------|\n| `identity` | User name, role, contact info | `\"user_name\": \"Michael Schäfer\"` |\n| `preference` | Likes, dislikes, working style | `\"communication\": \"Prefers concise responses\"` |\n| `fact` | Verifiable facts | `\"office_location\": \"Berlin, Germany\"` |\n| `project` | Project status, decisions | `\"project_synapse\": \"v1.5.0 deployed\"` |\n| `skill` | User's skills | `\"skill_python\": \"Advanced, 10+ years\"` |\n| `mistake` | Past errors to avoid | `\"mistake_npm_version\": \"Always bump version\"` |\n| `context` | Session-relevant context | `\"current_focus\": \"Working on docs system\"` |\n| `note` | Misc notes | `\"note_idea\": \"Try Redis for caching\"` |\n\n> [!TIP]\n> When in doubt, use `fact` for verifiable info and `note` for everything else.\n> Don't over-categorize — better to have a clear `fact` than a confusing `context`.\n\n## Keys: Meaningful Identifiers\n\nThe `key` field is the memory's identifier. Use meaningful, stable keys:\n\n**Good keys:**\n- `user_name`\n- `project_synapse_status`\n- `preference_communication_style`\n- `mistake_npm_version_bump`\n\n**Bad keys:**\n- `mem_001` (not meaningful)\n- `temp` (not descriptive)\n- `2026-06-27-note` (date doesn't help recall)\n\n### Key naming conventions\n\n- `snake_case` (lowercase with underscores)\n- Prefix with category: `preference_*`, `project_*`, `mistake_*`\n- Use descriptive nouns, not verbs\n- Keep under 50 characters\n\n## Tags: For Search and Filtering\n\nTags enable fast filtering and search. Add 2-5 tags per memory:\n\n```json\n{\n  \"category\": \"project\",\n  \"key\": \"project_synapse_status\",\n  \"content\": \"Synapse v1.5.0 deployed. Next: v1.6.0 with docs system.\",\n  \"tags\": [\"synapse\", \"deployment\", \"status\", \"v1.5.0\"]\n}\n```\n\n### Tag patterns\n\n- **Project names**: `synapse`, `synapse-mcp`, `synapse-chat`\n- **Topics**: `deployment`, `ci`, `database`, `auth`\n- **Status**: `active`, `completed`, `blocked`\n- **Priority indicators**: `urgent`, `long-term`\n\n> [!NOTE]\n> Tags are case-insensitive. Use lowercase for consistency.\n\n## Priorities: Be Realistic\n\n| Priority | Use For | % of Memories |\n|----------|---------|---------------|\n| `critical` | User identity, legal info, irreversible decisions | ~5% |\n| `high` | Active projects, important preferences | ~20% |\n| `normal` | Most facts, notes, context | ~65% |\n| `low` | Ephemeral, nice-to-know | ~10% |\n\n> [!WARNING]\n> Don't mark everything `critical`. If everything is critical, nothing is.\n> Reserve `critical` for things that would cause real harm if forgotten.\n\n## When to Store vs Not Store\n\n### Always store\n\n- User identity (name, email, role)\n- Long-term preferences\n- Project decisions and rationale\n- Past mistakes and lessons learned\n- Commitments made to the user\n\n### Don't store\n\n- Transient state (use variables instead)\n- Verbatim conversation history (chat system handles this)\n- Sensitive data (passwords, API keys)\n- Easily derivable facts (current date, file contents)\n- Ephemeral context (use `context` category with low priority)\n\n## Updating Memories\n\nPOST `/memory` with the same `category` + `key` updates the existing memory:\n\n```python\n# Initial store\nstore(\"project\", \"project_synapse_status\", \"v1.4.0 deployed\", priority=\"high\")\n\n# Later: update with same key\nstore(\"project\", \"project_synapse_status\", \"v1.5.0 deployed. CI green.\", priority=\"high\")\n```\n\n> [!TIP]\n> Use stable keys so you can update without creating duplicates. The LLM\n> should re-POST the same key as info changes, not create new memories.\n\n## Memory Lifecycle\n\n```\nCreate → Active → Stale → Archive → Delete\n```\n\n- **Create**: POST /memory with full context\n- **Active**: Recall frequently, update as needed\n- **Stale**: Still relevant but not actively used (lower priority?)\n- **Archive**: Set priority to `low`, keep for historical reference\n- **Delete**: DELETE /memory/:id when no longer relevant\n\n### Periodic cleanup\n\n```python\n# Find memories not updated in 90 days\nold_memories = requests.get(\n    f\"{URL}/memory/search?q=*\",\n    headers={\"Authorization\": f\"Bearer {KEY}\"}\n)\n\nfor mem in old_memories[\"results\"]:\n    if is_stale(mem, days=90):\n        # Either delete or lower priority\n        if is_obsolete(mem):\n            delete_memory(mem[\"id\"])\n        else:\n            update_memory(mem[\"id\"], priority=\"low\")\n```\n\n## Pattern: Memory Inheritance\n\nFor hierarchical context (project → subproject → task):\n\n```python\n# Parent project\nstore(\"project\", \"project_synapse\", \"Main Synapse project\", \n      tags=[\"synapse\", \"parent\"], priority=\"high\")\n\n# Sub-project (tags link to parent)\nstore(\"project\", \"project_synapse_docs\", \"Docs system for Synapse\",\n      tags=[\"synapse\", \"docs\", \"synapse-parent\"], priority=\"high\")\n\n# Specific task (tags link to sub-project)\nstore(\"project\", \"task_docs_loader\", \"Implement docs-loader.ts\",\n      tags=[\"synapse\", \"docs\", \"task\"], priority=\"normal\")\n```\n\nThe LLM can then search `q=synapse+docs` to find all related memories.\n\n## Pattern: Decision Log\n\nStore decisions with rationale so the LLM doesn't re-litigate them:\n\n```python\nstore(\"fact\", \"decision_postgres_over_sqlite\",\n      \"Chose PostgreSQL over SQLite for production. Reason: concurrent writes, \"\n      \"FTS5 native support, better backup story. Date: 2026-06-15. Decided by: Michael.\",\n      tags=[\"decision\", \"database\", \"postgres\", \"sqlite\"],\n      priority=\"high\")\n```\n\n## Pattern: Mistake Avoidance\n\nStore mistakes with specific avoidance instructions:\n\n```python\nstore(\"mistake\", \"mistake_forget_version_bump\",\n      \"Forgot to bump package.json version after changes. npm publish failed. \"\n      \"FIX: Always run `npm version patch` before pushing. \"\n      \"CI fails with 'version already exists' if you forget.\",\n      tags=[\"npm\", \"ci\", \"publish\", \"version\"],\n      priority=\"high\")\n```\n\n## Anti-Patterns to Avoid\n\n> [!WARNING]\n> - **Storing conversation logs** — chat system handles this\n> - **Storing entire files** — use script store or external storage\n> - **Storing ephemeral state** — use variables\n> - **Storing secrets** — use environment variables\n> - **Duplicating memories** — use stable keys\n> - **Over-tagging** — 2-5 tags per memory is ideal\n> - **Everything is critical** — be realistic with priorities\n\n## Next Steps\n\n- [Memory API](/docs/api/memory)\n- [Persistent LLM Agent](/docs/guides/persistent-llm-agent)\n- [Memory Tagging Strategy](/docs/llm-cookbook/memory-tagging-strategy)\n","content_html":"<h1>Memory Best Practices</h1>\n<p>How you structure memories determines how useful they are. This guide covers\npatterns for categorizing, tagging, and prioritizing memories so the LLM can\nrecall the right information at the right time.</p>\n<h2>Categories: Pick the Most Specific</h2>\n<table>\n<thead>\n<tr>\n<th>Category</th>\n<th>Use For</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>identity</code></td>\n<td>User name, role, contact info</td>\n<td><code>&quot;user_name&quot;: &quot;Michael Schäfer&quot;</code></td>\n</tr>\n<tr>\n<td><code>preference</code></td>\n<td>Likes, dislikes, working style</td>\n<td><code>&quot;communication&quot;: &quot;Prefers concise responses&quot;</code></td>\n</tr>\n<tr>\n<td><code>fact</code></td>\n<td>Verifiable facts</td>\n<td><code>&quot;office_location&quot;: &quot;Berlin, Germany&quot;</code></td>\n</tr>\n<tr>\n<td><code>project</code></td>\n<td>Project status, decisions</td>\n<td><code>&quot;project_synapse&quot;: &quot;v1.5.0 deployed&quot;</code></td>\n</tr>\n<tr>\n<td><code>skill</code></td>\n<td>User&#39;s skills</td>\n<td><code>&quot;skill_python&quot;: &quot;Advanced, 10+ years&quot;</code></td>\n</tr>\n<tr>\n<td><code>mistake</code></td>\n<td>Past errors to avoid</td>\n<td><code>&quot;mistake_npm_version&quot;: &quot;Always bump version&quot;</code></td>\n</tr>\n<tr>\n<td><code>context</code></td>\n<td>Session-relevant context</td>\n<td><code>&quot;current_focus&quot;: &quot;Working on docs system&quot;</code></td>\n</tr>\n<tr>\n<td><code>note</code></td>\n<td>Misc notes</td>\n<td><code>&quot;note_idea&quot;: &quot;Try Redis for caching&quot;</code></td>\n</tr>\n</tbody></table>\n<div class=\"callout callout-ok\">When in doubt, use `fact` for verifiable info and `note` for everything else.\nDon't over-categorize — better to have a clear `fact` than a confusing `context`.</div><h2>Keys: Meaningful Identifiers</h2>\n<p>The <code>key</code> field is the memory&#39;s identifier. Use meaningful, stable keys:</p>\n<p><strong>Good keys:</strong></p>\n<ul>\n<li><code>user_name</code></li>\n<li><code>project_synapse_status</code></li>\n<li><code>preference_communication_style</code></li>\n<li><code>mistake_npm_version_bump</code></li>\n</ul>\n<p><strong>Bad keys:</strong></p>\n<ul>\n<li><code>mem_001</code> (not meaningful)</li>\n<li><code>temp</code> (not descriptive)</li>\n<li><code>2026-06-27-note</code> (date doesn&#39;t help recall)</li>\n</ul>\n<h3>Key naming conventions</h3>\n<ul>\n<li><code>snake_case</code> (lowercase with underscores)</li>\n<li>Prefix with category: <code>preference_*</code>, <code>project_*</code>, <code>mistake_*</code></li>\n<li>Use descriptive nouns, not verbs</li>\n<li>Keep under 50 characters</li>\n</ul>\n<h2>Tags: For Search and Filtering</h2>\n<p>Tags enable fast filtering and search. Add 2-5 tags per memory:</p>\n<pre><code class=\"hljs language-json\"><span class=\"hljs-punctuation\">{</span>\n  <span class=\"hljs-attr\">&quot;category&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;project&quot;</span><span class=\"hljs-punctuation\">,</span>\n  <span class=\"hljs-attr\">&quot;key&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;project_synapse_status&quot;</span><span class=\"hljs-punctuation\">,</span>\n  <span class=\"hljs-attr\">&quot;content&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;Synapse v1.5.0 deployed. Next: v1.6.0 with docs system.&quot;</span><span class=\"hljs-punctuation\">,</span>\n  <span class=\"hljs-attr\">&quot;tags&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-punctuation\">[</span><span class=\"hljs-string\">&quot;synapse&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;deployment&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;status&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;v1.5.0&quot;</span><span class=\"hljs-punctuation\">]</span>\n<span class=\"hljs-punctuation\">}</span></code></pre><h3>Tag patterns</h3>\n<ul>\n<li><strong>Project names</strong>: <code>synapse</code>, <code>synapse-mcp</code>, <code>synapse-chat</code></li>\n<li><strong>Topics</strong>: <code>deployment</code>, <code>ci</code>, <code>database</code>, <code>auth</code></li>\n<li><strong>Status</strong>: <code>active</code>, <code>completed</code>, <code>blocked</code></li>\n<li><strong>Priority indicators</strong>: <code>urgent</code>, <code>long-term</code></li>\n</ul>\n<div class=\"callout callout-note\">Tags are case-insensitive. Use lowercase for consistency.</div><h2>Priorities: Be Realistic</h2>\n<table>\n<thead>\n<tr>\n<th>Priority</th>\n<th>Use For</th>\n<th>% of Memories</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>critical</code></td>\n<td>User identity, legal info, irreversible decisions</td>\n<td>~5%</td>\n</tr>\n<tr>\n<td><code>high</code></td>\n<td>Active projects, important preferences</td>\n<td>~20%</td>\n</tr>\n<tr>\n<td><code>normal</code></td>\n<td>Most facts, notes, context</td>\n<td>~65%</td>\n</tr>\n<tr>\n<td><code>low</code></td>\n<td>Ephemeral, nice-to-know</td>\n<td>~10%</td>\n</tr>\n</tbody></table>\n<div class=\"callout callout-warn\">Don't mark everything `critical`. If everything is critical, nothing is.\nReserve `critical` for things that would cause real harm if forgotten.</div><h2>When to Store vs Not Store</h2>\n<h3>Always store</h3>\n<ul>\n<li>User identity (name, email, role)</li>\n<li>Long-term preferences</li>\n<li>Project decisions and rationale</li>\n<li>Past mistakes and lessons learned</li>\n<li>Commitments made to the user</li>\n</ul>\n<h3>Don&#39;t store</h3>\n<ul>\n<li>Transient state (use variables instead)</li>\n<li>Verbatim conversation history (chat system handles this)</li>\n<li>Sensitive data (passwords, API keys)</li>\n<li>Easily derivable facts (current date, file contents)</li>\n<li>Ephemeral context (use <code>context</code> category with low priority)</li>\n</ul>\n<h2>Updating Memories</h2>\n<p>POST <code>/memory</code> with the same <code>category</code> + <code>key</code> updates the existing memory:</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># Initial store</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;project_synapse_status&quot;</span>, <span class=\"hljs-string\">&quot;v1.4.0 deployed&quot;</span>, priority=<span class=\"hljs-string\">&quot;high&quot;</span>)\n\n<span class=\"hljs-comment\"># Later: update with same key</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;project_synapse_status&quot;</span>, <span class=\"hljs-string\">&quot;v1.5.0 deployed. CI green.&quot;</span>, priority=<span class=\"hljs-string\">&quot;high&quot;</span>)</code></pre><div class=\"callout callout-ok\">Use stable keys so you can update without creating duplicates. The LLM\nshould re-POST the same key as info changes, not create new memories.</div><h2>Memory Lifecycle</h2>\n<pre><code class=\"hljs language-plaintext\">Create → Active → Stale → Archive → Delete</code></pre><ul>\n<li><strong>Create</strong>: POST /memory with full context</li>\n<li><strong>Active</strong>: Recall frequently, update as needed</li>\n<li><strong>Stale</strong>: Still relevant but not actively used (lower priority?)</li>\n<li><strong>Archive</strong>: Set priority to <code>low</code>, keep for historical reference</li>\n<li><strong>Delete</strong>: DELETE /memory/:id when no longer relevant</li>\n</ul>\n<h3>Periodic cleanup</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># Find memories not updated in 90 days</span>\nold_memories = requests.get(\n    <span class=\"hljs-string\">f&quot;<span class=\"hljs-subst\">{URL}</span>/memory/search?q=*&quot;</span>,\n    headers={<span class=\"hljs-string\">&quot;Authorization&quot;</span>: <span class=\"hljs-string\">f&quot;Bearer <span class=\"hljs-subst\">{KEY}</span>&quot;</span>}\n)\n\n<span class=\"hljs-keyword\">for</span> mem <span class=\"hljs-keyword\">in</span> old_memories[<span class=\"hljs-string\">&quot;results&quot;</span>]:\n    <span class=\"hljs-keyword\">if</span> is_stale(mem, days=<span class=\"hljs-number\">90</span>):\n        <span class=\"hljs-comment\"># Either delete or lower priority</span>\n        <span class=\"hljs-keyword\">if</span> is_obsolete(mem):\n            delete_memory(mem[<span class=\"hljs-string\">&quot;id&quot;</span>])\n        <span class=\"hljs-keyword\">else</span>:\n            update_memory(mem[<span class=\"hljs-string\">&quot;id&quot;</span>], priority=<span class=\"hljs-string\">&quot;low&quot;</span>)</code></pre><h2>Pattern: Memory Inheritance</h2>\n<p>For hierarchical context (project → subproject → task):</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># Parent project</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;project_synapse&quot;</span>, <span class=\"hljs-string\">&quot;Main Synapse project&quot;</span>, \n      tags=[<span class=\"hljs-string\">&quot;synapse&quot;</span>, <span class=\"hljs-string\">&quot;parent&quot;</span>], priority=<span class=\"hljs-string\">&quot;high&quot;</span>)\n\n<span class=\"hljs-comment\"># Sub-project (tags link to parent)</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;project_synapse_docs&quot;</span>, <span class=\"hljs-string\">&quot;Docs system for Synapse&quot;</span>,\n      tags=[<span class=\"hljs-string\">&quot;synapse&quot;</span>, <span class=\"hljs-string\">&quot;docs&quot;</span>, <span class=\"hljs-string\">&quot;synapse-parent&quot;</span>], priority=<span class=\"hljs-string\">&quot;high&quot;</span>)\n\n<span class=\"hljs-comment\"># Specific task (tags link to sub-project)</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;task_docs_loader&quot;</span>, <span class=\"hljs-string\">&quot;Implement docs-loader.ts&quot;</span>,\n      tags=[<span class=\"hljs-string\">&quot;synapse&quot;</span>, <span class=\"hljs-string\">&quot;docs&quot;</span>, <span class=\"hljs-string\">&quot;task&quot;</span>], priority=<span class=\"hljs-string\">&quot;normal&quot;</span>)</code></pre><p>The LLM can then search <code>q=synapse+docs</code> to find all related memories.</p>\n<h2>Pattern: Decision Log</h2>\n<p>Store decisions with rationale so the LLM doesn&#39;t re-litigate them:</p>\n<pre><code class=\"hljs language-python\">store(<span class=\"hljs-string\">&quot;fact&quot;</span>, <span class=\"hljs-string\">&quot;decision_postgres_over_sqlite&quot;</span>,\n      <span class=\"hljs-string\">&quot;Chose PostgreSQL over SQLite for production. Reason: concurrent writes, &quot;</span>\n      <span class=\"hljs-string\">&quot;FTS5 native support, better backup story. Date: 2026-06-15. Decided by: Michael.&quot;</span>,\n      tags=[<span class=\"hljs-string\">&quot;decision&quot;</span>, <span class=\"hljs-string\">&quot;database&quot;</span>, <span class=\"hljs-string\">&quot;postgres&quot;</span>, <span class=\"hljs-string\">&quot;sqlite&quot;</span>],\n      priority=<span class=\"hljs-string\">&quot;high&quot;</span>)</code></pre><h2>Pattern: Mistake Avoidance</h2>\n<p>Store mistakes with specific avoidance instructions:</p>\n<pre><code class=\"hljs language-python\">store(<span class=\"hljs-string\">&quot;mistake&quot;</span>, <span class=\"hljs-string\">&quot;mistake_forget_version_bump&quot;</span>,\n      <span class=\"hljs-string\">&quot;Forgot to bump package.json version after changes. npm publish failed. &quot;</span>\n      <span class=\"hljs-string\">&quot;FIX: Always run `npm version patch` before pushing. &quot;</span>\n      <span class=\"hljs-string\">&quot;CI fails with &#x27;version already exists&#x27; if you forget.&quot;</span>,\n      tags=[<span class=\"hljs-string\">&quot;npm&quot;</span>, <span class=\"hljs-string\">&quot;ci&quot;</span>, <span class=\"hljs-string\">&quot;publish&quot;</span>, <span class=\"hljs-string\">&quot;version&quot;</span>],\n      priority=<span class=\"hljs-string\">&quot;high&quot;</span>)</code></pre><h2>Anti-Patterns to Avoid</h2>\n<div class=\"callout callout-warn\"></div><h2>Next Steps</h2>\n<ul>\n<li><a href=\"/docs/api/memory\">Memory API</a></li>\n<li><a href=\"/docs/guides/persistent-llm-agent\">Persistent LLM Agent</a></li>\n<li><a href=\"/docs/llm-cookbook/memory-tagging-strategy\">Memory Tagging Strategy</a></li>\n</ul>\n","urls":{"html":"/docs/guides/memory-best-practices","text":"/docs/guides/memory-best-practices?format=text","json":"/docs/guides/memory-best-practices?format=json","llm":"/docs/guides/memory-best-practices?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}