Skip to main content
Glama
danielsimonjr

Enhanced Knowledge Graph Memory Server

ARCHIVING.md29.8 kB
# Memory Archiving Guide ## Managing Memory Lifecycle and Long-Term Storage **Version:** 0.8.0 **Last Updated:** 2025-11-23 --- ## Table of Contents 1. [Overview](#overview) 2. [Core Concepts](#core-concepts) 3. [Understanding Archiving Criteria](#understanding-archiving-criteria) 4. [Getting Started](#getting-started) 5. [Tool Reference](#tool-reference) 6. [Common Use Cases](#common-use-cases) 7. [Best Practices](#best-practices) 8. [Advanced Patterns](#advanced-patterns) 9. [Troubleshooting](#troubleshooting) --- ## Overview Memory archiving helps you manage the lifecycle of your knowledge graph by moving inactive, low-priority, or completed entities out of active memory. This keeps your active graph focused, performant, and relevant while preserving historical data for future reference. ### Key Features - ✅ **Criteria-Based Archiving**: Archive by age, importance, or tags - ✅ **OR Logic**: Archive if ANY criterion matches (flexible filtering) - ✅ **Dry-Run Preview**: Safe preview before executing - ✅ **Clean Removal**: Automatically removes related relations - ✅ **Permanent Storage**: Archived entities saved to separate file - ✅ **Selective Archiving**: Target specific entity groups ### When to Use Archiving - **Memory optimization**: Active graph is too large and slowing down queries - **Focus maintenance**: Keep active memory focused on current work - **Lifecycle management**: Archive completed projects, deprecated features - **Temporal cleanup**: Remove old entities that are no longer relevant - **Capacity planning**: Prevent unbounded growth of active memory ### What Gets Archived When entities are archived: - **Entity data**: Moved to `archive.jsonl` - **Relations**: Incoming and outgoing relations are **removed** - **Active graph**: Entity and its relations are removed from `memory.jsonl` - **Permanence**: Archived entities are **not** automatically restored ⚠️ **Important:** Archiving is **permanent** removal from active memory. Plan carefully! --- ## Core Concepts ### The Archive File Archived entities are stored in a separate JSONL file: ``` /path/to/memory-mcp/ ├── memory.jsonl # Active knowledge graph ├── archive.jsonl # Archived entities (permanent storage) ├── saved-searches.jsonl # Saved search queries └── tag-aliases.jsonl # Tag alias mappings ``` **Archive format:** ```jsonl {"name":"Old Project","entityType":"project","observations":["Completed in 2023"],"archivedAt":"2025-11-23T10:00:00.000Z"} {"name":"Deprecated API","entityType":"api","observations":["No longer used"],"archivedAt":"2025-11-23T10:00:00.000Z"} ``` ### Archiving Criteria (OR Logic) You can specify up to 3 criteria, and entities matching **ANY** criterion will be archived: | Criterion | Type | Description | |-----------|------|-------------| | **olderThan** | ISO Date String | Archive entities last modified before this date | | **importanceLessThan** | Number (0-10) | Archive entities below this importance threshold | | **tags** | String[] | Archive entities with ANY of these tags | **Example:** ```javascript archive_entities({ olderThan: "2025-06-01", importanceLessThan: 3, tags: ["deprecated", "completed"] }) // Archives entities that are: // - Modified before June 1, 2025, OR // - Have importance < 3, OR // - Have tag "deprecated", OR // - Have tag "completed" ``` ### What Happens During Archiving 1. **Evaluation**: Each entity is checked against all criteria 2. **Matching**: If ANY criterion matches, entity is marked for archiving 3. **Relations**: All relations involving archived entities are removed 4. **Storage**: Entity data is written to `archive.jsonl` with `archivedAt` timestamp 5. **Removal**: Entity is removed from active `memory.jsonl` 6. **Save**: Both files are persisted --- ## Understanding Archiving Criteria ### Criterion 1: `olderThan` (Temporal) Archives entities based on their **last modification date**. **Format:** ISO 8601 date string (e.g., `"2025-06-01"`, `"2025-01-15T00:00:00.000Z"`) **Logic:** ```typescript entity.lastModified < olderThan // Archive if older ``` **Examples:** ```javascript // Archive entities not modified since January 1, 2025 archive_entities({ olderThan: "2025-01-01" }) // Archive entities from 2024 or earlier archive_entities({ olderThan: "2025-01-01T00:00:00.000Z" }) // Archive 6+ month old entities const sixMonthsAgo = new Date(); sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6); archive_entities({ olderThan: sixMonthsAgo.toISOString() }) ``` **Best for:** - Seasonal cleanup (quarterly, annual) - Time-based retention policies - Historical project archiving --- ### Criterion 2: `importanceLessThan` (Priority) Archives entities based on their **importance level**. **Format:** Number between 0 and 10 **Logic:** ```typescript (entity.importance || 0) < importanceLessThan // Archive if less important ``` **Examples:** ```javascript // Archive low-priority entities (importance 0-2) archive_entities({ importanceLessThan: 3 }) // Archive all but high-priority entities (keep 8-10) archive_entities({ importanceLessThan: 8 }) // Archive unimportant entities (no importance set, or 0) archive_entities({ importanceLessThan: 1 }) ``` **Importance Scale:** - **9-10**: Critical (never archive) - **7-8**: High priority (archive rarely) - **5-6**: Medium priority (archive when old) - **3-4**: Low priority (archive when inactive) - **0-2**: Minimal (archive aggressively) **Best for:** - Capacity management (keep only important entities) - Priority-based cleanup - Focus maintenance --- ### Criterion 3: `tags` (Status/Category) Archives entities with **specific tags** (case-insensitive). **Format:** Array of strings **Logic:** ```typescript entity.tags?.some(tag => tags.includes(tag.toLowerCase())) // Archive if ANY tag matches ``` **Examples:** ```javascript // Archive completed work archive_entities({ tags: ["completed", "done"] }) // Archive deprecated features archive_entities({ tags: ["deprecated", "obsolete", "retired"] }) // Archive draft content archive_entities({ tags: ["draft", "wip", "unfinished"] }) // Archive temporary entities archive_entities({ tags: ["temp", "scratch", "test"] }) ``` **Common Tag Patterns:** | Tag Pattern | Use Case | |-------------|----------| | `completed`, `done`, `finished` | Completed work | | `deprecated`, `obsolete`, `retired` | Outdated features | | `draft`, `wip`, `unfinished` | Incomplete work | | `temp`, `scratch`, `test` | Temporary data | | `archived`, `inactive` | Manual archive markers | | `2024-q1`, `2024-q2` | Temporal tags | **Best for:** - Status-based archiving (completed projects) - Category cleanup (remove drafts) - Manual archiving workflows (tag then archive) --- ## Getting Started ### Example 1: Preview Before Archiving ```javascript // ALWAYS preview first! const preview = await archive_entities({ olderThan: "2025-06-01", importanceLessThan: 3 }, true); // dryRun = true console.log(`Would archive ${preview.archived} entities`); console.log(`Entities: ${preview.entityNames.join(', ')}`); // Review the list, then execute if (confirm("Proceed with archiving?")) { await archive_entities({ olderThan: "2025-06-01", importanceLessThan: 3 }, false); // dryRun = false } ``` ### Example 2: Archive Completed Projects ```javascript // Step 1: Tag completed projects await add_tags_to_multiple({ entityNames: ["Project Alpha", "Q3 Initiative", "Backend Rewrite"], tags: ["completed"] }); // Step 2: Archive all completed projects const result = await archive_entities({ tags: ["completed"] }, false); console.log(`Archived ${result.archived} completed projects`); ``` ### Example 3: Temporal Cleanup ```javascript // Archive entities older than 1 year const oneYearAgo = new Date(); oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1); const result = await archive_entities({ olderThan: oneYearAgo.toISOString() }, false); console.log(`Archived ${result.archived} entities from > 1 year ago`); ``` --- ## Tool Reference ### `archive_entities` Archive entities based on criteria (OR logic). **Parameters:** ```typescript { olderThan?: string; // ISO date (entities modified before this) importanceLessThan?: number; // Importance threshold (0-10) tags?: string[]; // Tag list (any match) } ``` **Second parameter:** `dryRun` (boolean, default `false`) **Returns:** ```typescript { archived: number; // Count of archived entities entityNames: string[]; // Names of archived entities } ``` **Behavior:** 1. Evaluates each entity against all criteria (OR logic) 2. Collects matching entities 3. If `dryRun: true`, returns list without changes 4. If `dryRun: false`, archives entities: - Removes relations involving archived entities - Writes entities to `archive.jsonl` with `archivedAt` timestamp - Removes entities from active graph - Saves both active and archive files **Usage:** ```javascript // Preview only (safe) archive_entities({ olderThan: "2025-01-01" }, true) // Execute archiving archive_entities({ olderThan: "2025-01-01" }, false) // Multiple criteria (OR logic) archive_entities({ olderThan: "2025-06-01", importanceLessThan: 3, tags: ["completed", "deprecated"] }, false) // Single criterion archive_entities({ tags: ["temp"] }, false) ``` **Validation:** - At least one criterion must be provided - `importanceLessThan` must be 0-10 - `olderThan` must be valid ISO date string - `tags` must be non-empty array if provided --- ## Common Use Cases ### Use Case 1: Quarterly Cleanup **Scenario:** Archive old, low-priority entities every quarter. ```javascript async function quarterlyArchive() { // Define criteria const threeMonthsAgo = new Date(); threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3); // Preview const preview = await archive_entities({ olderThan: threeMonthsAgo.toISOString(), importanceLessThan: 4 // Low priority }, true); console.log(`Quarterly Archive Preview:`); console.log(`- Entities to archive: ${preview.archived}`); console.log(`- Names: ${preview.entityNames.slice(0, 10).join(', ')}...`); // Get stats before archiving const before = await get_graph_stats(); // Execute const result = await archive_entities({ olderThan: threeMonthsAgo.toISOString(), importanceLessThan: 4 }, false); // Get stats after const after = await get_graph_stats(); // Log report console.log(`Quarterly Archive Complete:`); console.log(`- Archived: ${result.archived} entities`); console.log(`- Before: ${before.totalEntities} entities`); console.log(`- After: ${after.totalEntities} entities`); console.log(`- Reduction: ${before.totalEntities - after.totalEntities} entities`); // Create audit log await create_entities({ entities: [{ name: `Quarterly Archive ${new Date().toISOString().split('T')[0]}`, entityType: "audit-log", observations: [ `Archived ${result.archived} entities`, `Criteria: olderThan ${threeMonthsAgo.toISOString()}, importanceLessThan 4`, `Graph size: ${before.totalEntities} → ${after.totalEntities}`, `Entities: ${result.entityNames.join(', ')}` ], tags: ["archive", "maintenance", "quarterly"], importance: 7 }] }); } // Run quarterly await quarterlyArchive(); ``` ### Use Case 2: Project Lifecycle Management **Scenario:** Archive completed projects and their entire subtrees. ```javascript async function archiveCompletedProjects() { // Find all completed projects const results = await search_nodes({ query: "", tags: ["completed"], minImportance: 0, maxImportance: 10 }); const completedProjects = results.filter(e => e.entityType === "project"); console.log(`Found ${completedProjects.length} completed projects`); for (const project of completedProjects) { console.log(`Archiving project: ${project.name}`); // Get entire project subtree const subtree = await get_subtree({ entityName: project.name }); console.log(`- Subtree size: ${subtree.entities.length} entities`); // Tag entire subtree for archiving const entityNames = subtree.entities.map(e => e.name); await add_tags_to_multiple({ entityNames, tags: ["archived"] }); // Archive the entire subtree const result = await archive_entities({ tags: ["archived"] }, false); console.log(`- Archived: ${result.archived} entities`); } } // Usage await archiveCompletedProjects(); ``` ### Use Case 3: Capacity Management **Scenario:** Keep active memory under 1000 entities by archiving least important entities. ```javascript async function enforceCapacityLimit(maxEntities = 1000) { const stats = await get_graph_stats(); if (stats.totalEntities <= maxEntities) { console.log(`Under capacity: ${stats.totalEntities}/${maxEntities} entities`); return; } const excess = stats.totalEntities - maxEntities; console.log(`Over capacity by ${excess} entities. Archiving...`); // Archive progressively by importance const thresholds = [1, 2, 3, 4, 5, 6, 7, 8]; for (const threshold of thresholds) { const preview = await archive_entities({ importanceLessThan: threshold }, true); console.log(`Threshold ${threshold}: Would archive ${preview.archived} entities`); if (preview.archived >= excess) { // This threshold is sufficient const result = await archive_entities({ importanceLessThan: threshold }, false); console.log(`Archived ${result.archived} entities (importance < ${threshold})`); const newStats = await get_graph_stats(); console.log(`New entity count: ${newStats.totalEntities}/${maxEntities}`); break; } } } // Usage await enforceCapacityLimit(1000); ``` ### Use Case 4: Temporal Retention Policy **Scenario:** Implement tiered retention based on age and importance. ```javascript async function tieredRetention() { const now = new Date(); // Tier 1: Archive > 2 years old, any importance const twoYearsAgo = new Date(now); twoYearsAgo.setFullYear(twoYearsAgo.getFullYear() - 2); const tier1 = await archive_entities({ olderThan: twoYearsAgo.toISOString() }, false); console.log(`Tier 1 (>2 years): Archived ${tier1.archived} entities`); // Tier 2: Archive > 1 year old AND low importance const oneYearAgo = new Date(now); oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1); const tier2 = await archive_entities({ olderThan: oneYearAgo.toISOString(), importanceLessThan: 5 }, false); console.log(`Tier 2 (>1 year, low priority): Archived ${tier2.archived} entities`); // Tier 3: Archive > 6 months old AND very low importance const sixMonthsAgo = new Date(now); sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6); const tier3 = await archive_entities({ olderThan: sixMonthsAgo.toISOString(), importanceLessThan: 3 }, false); console.log(`Tier 3 (>6 months, very low priority): Archived ${tier3.archived} entities`); const total = tier1.archived + tier2.archived + tier3.archived; console.log(`Total archived: ${total} entities`); } // Run monthly await tieredRetention(); ``` --- ## Best Practices ### 1. Always Preview First **Never** archive without reviewing what will be removed: ```javascript ✅ GOOD: Safe workflow const preview = await archive_entities({ tags: ["completed"] }, true); console.log(`Would archive: ${preview.entityNames.join(', ')}`); // Review list carefully await archive_entities({ tags: ["completed"] }, false); ❌ BAD: Blind archiving await archive_entities({ importanceLessThan: 5 }, false); // Risky! ``` ### 2. Tag Before Archiving Use tags to explicitly mark entities for archiving: ```javascript // Step 1: Tag entities for archiving await add_tags_to_multiple({ entityNames: ["Project A", "Project B", "Project C"], tags: ["ready-to-archive"] }); // Step 2: Review tagged entities const tagged = await search_nodes({ query: "", tags: ["ready-to-archive"] }); console.log(`Ready to archive: ${tagged.length} entities`); // Step 3: Archive await archive_entities({ tags: ["ready-to-archive"] }, false); ``` ### 3. Document Archiving Activity Create audit logs for all archiving operations: ```javascript async function documentedArchive(criteria, dryRun = false) { const before = await get_graph_stats(); const result = await archive_entities(criteria, dryRun); if (!dryRun) { const after = await get_graph_stats(); await create_entities({ entities: [{ name: `Archive Operation ${new Date().toISOString()}`, entityType: "archive-log", observations: [ `Criteria: ${JSON.stringify(criteria)}`, `Archived: ${result.archived} entities`, `Before: ${before.totalEntities} entities`, `After: ${after.totalEntities} entities`, `Entities: ${result.entityNames.join(', ')}` ], tags: ["archive", "audit", "maintenance"], importance: 8 }] }); } return result; } ``` ### 4. Protect Critical Entities Ensure important entities are never archived accidentally: ```javascript // Set high importance for critical entities await set_importance({ entityName: "Mission Critical System", importance: 10 }); await set_importance({ entityName: "Core Architecture", importance: 10 }); await set_importance({ entityName: "Primary Database", importance: 10 }); // Now archiving by importance will never touch these await archive_entities({ importanceLessThan: 9 }, false); // Safe ``` ### 5. Use Progressive Thresholds Start conservative and increase aggressiveness: ```javascript // Progressive archiving async function progressiveArchive() { // Round 1: Very old, low priority (conservative) const oneYearAgo = new Date(); oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1); await archive_entities({ olderThan: oneYearAgo.toISOString(), importanceLessThan: 3 }, false); // Round 2: Completed work (safe) await archive_entities({ tags: ["completed", "done"] }, false); // Round 3: Deprecated (targeted) await archive_entities({ tags: ["deprecated", "obsolete"] }, false); // Round 4: If still over capacity, increase aggressiveness const stats = await get_graph_stats(); if (stats.totalEntities > 1000) { await archive_entities({ importanceLessThan: 5 }, false); } } ``` ### 6. Validate After Archiving Check graph health after major archiving operations: ```javascript async function safeArchive(criteria) { // Backup (optional - depends on your setup) const beforeGraph = await read_graph(); // Archive const result = await archive_entities(criteria, false); // Validate const validation = await validate_graph(); if (validation.errors.length > 0) { console.error("Archiving created errors:", validation.errors); // Consider manual review or restoration } console.log(`Archived ${result.archived} entities`); console.log(`Validation: ${validation.errors.length} errors, ${validation.warnings.length} warnings`); return result; } ``` --- ## Advanced Patterns ### Pattern 1: Selective Subtree Archiving Archive specific branches of a hierarchy: ```javascript async function archiveSubtree(rootEntityName, preserveRoot = false) { // Get entire subtree const subtree = await get_subtree({ entityName: rootEntityName }); let entityNames = subtree.entities.map(e => e.name); if (preserveRoot) { // Remove root from archiving list entityNames = entityNames.filter(name => name !== rootEntityName); } console.log(`Archiving ${entityNames.length} entities from subtree...`); // Tag for archiving await add_tags_to_multiple({ entityNames, tags: ["subtree-archive"] }); // Archive const result = await archive_entities({ tags: ["subtree-archive"] }, false); console.log(`Archived subtree: ${result.archived} entities`); return result; } // Usage await archiveSubtree("Old Project", false); // Archive entire project await archiveSubtree("Active Project", true); // Archive children but keep root ``` ### Pattern 2: Scheduled Archiving Implement automated archiving schedules: ```javascript // Pseudo-code for scheduled archiving class ArchiveScheduler { async dailyArchive() { // Archive temporary entities await archive_entities({ tags: ["temp", "scratch"] }, false); } async weeklyArchive() { // Archive completed work from last week const oneWeekAgo = new Date(); oneWeekAgo.setDate(oneWeekAgo.getDate() - 7); await archive_entities({ olderThan: oneWeekAgo.toISOString(), tags: ["completed"] }, false); } async monthlyArchive() { // Archive old, low-priority entities const oneMonthAgo = new Date(); oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); await archive_entities({ olderThan: oneMonthAgo.toISOString(), importanceLessThan: 4 }, false); } async quarterlyArchive() { // Aggressive cleanup const threeMonthsAgo = new Date(); threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3); await archive_entities({ olderThan: threeMonthsAgo.toISOString(), importanceLessThan: 6 }, false); } } ``` ### Pattern 3: Archive with Backup Create export backup before archiving: ```javascript async function archiveWithBackup(criteria) { // Step 1: Export entities that will be archived const preview = await archive_entities(criteria, true); // Step 2: Get full entity data const entitiesToArchive = await open_nodes({ names: preview.entityNames }); // Step 3: Export to JSON const timestamp = new Date().toISOString().replace(/:/g, '-'); const backup = { archiveDate: timestamp, criteria: criteria, entities: entitiesToArchive }; console.log(`Backup created: archive-backup-${timestamp}.json`); console.log(`Entities: ${entitiesToArchive.length}`); // Save backup (implementation depends on your environment) // Step 4: Execute archiving const result = await archive_entities(criteria, false); console.log(`Archived ${result.archived} entities (backup available)`); return { result, backup }; } ``` ### Pattern 4: Conditional Archiving Archive based on complex conditions: ```javascript async function conditionalArchive() { const graph = await read_graph(); const toArchive = []; for (const entity of graph.entities) { let shouldArchive = false; // Condition 1: Old AND no relations const age = new Date() - new Date(entity.lastModified || entity.createdAt); const sixMonths = 6 * 30 * 24 * 60 * 60 * 1000; const hasRelations = graph.relations.some(r => r.from === entity.name || r.to === entity.name ); if (age > sixMonths && !hasRelations) { shouldArchive = true; } // Condition 2: Low importance AND no children const hasChildren = graph.entities.some(e => e.parentId === entity.name); if ((entity.importance || 0) < 3 && !hasChildren) { shouldArchive = true; } // Condition 3: Tagged for manual archiving if (entity.tags?.includes("manual-archive")) { shouldArchive = true; } if (shouldArchive) { toArchive.push(entity.name); } } console.log(`Conditional archive: ${toArchive.length} entities`); // Tag and archive await add_tags_to_multiple({ entityNames: toArchive, tags: ["auto-archive"] }); await archive_entities({ tags: ["auto-archive"] }, false); } ``` --- ## Troubleshooting ### Issue: Archived Too Much **Problem:** Archived entities that should have been kept. **Solution:** There is no built-in restore function. You need to manually restore from `archive.jsonl`: ```javascript // Read archive.jsonl manually // Find entities to restore // Use create_entities to recreate them in active graph // Manually recreate relations if needed // Prevention: ALWAYS preview with dryRun: true first! ``` ### Issue: Important Entities Archived **Problem:** Critical entities were archived due to low importance or old age. **Solution:** Set high importance on critical entities: ```javascript // Protect critical entities const critical = ["Core System", "Main Database", "Primary API"]; for (const entityName of critical) { await set_importance({ entityName, importance: 10 }); } // Add protection tag await add_tags_to_multiple({ entityNames: critical, tags: ["protected", "critical"] }); // Exclude protected entities from archiving // (You'll need to manually filter these in your archiving logic) ``` ### Issue: Archiving is Too Slow **Problem:** `archive_entities` takes too long on large graphs. **Solution:** Use more specific criteria or batch archiving: ```javascript // Option 1: More specific criteria await archive_entities({ tags: ["completed"], // Targets specific subset importanceLessThan: 3 }, false); // Option 2: Archive by type const types = ["task", "note", "draft"]; for (const type of types) { const entities = await search_nodes({ query: "", entityType: type }); const oldEntities = entities.filter(e => { const age = new Date() - new Date(e.lastModified || e.createdAt); return age > 6 * 30 * 24 * 60 * 60 * 1000; // 6 months }); if (oldEntities.length > 0) { const names = oldEntities.map(e => e.name); await add_tags_to_multiple({ entityNames: names, tags: ["batch-archive"] }); await archive_entities({ tags: ["batch-archive"] }, false); } } ``` ### Issue: Relations Broken After Archiving **Problem:** Entities still reference archived entities. **Solution:** This is expected behavior. Archiving removes all relations involving archived entities. To preserve relations: ```javascript // Option 1: Don't archive entities with important relations const graph = await read_graph(); const entityWithRelations = graph.entities.filter(e => { const hasRelations = graph.relations.some(r => r.from === e.name || r.to === e.name ); return hasRelations && (e.importance || 0) >= 5; }); // Exclude from archiving await add_tags_to_multiple({ entityNames: entityWithRelations.map(e => e.name), tags: ["has-relations"] }); // Option 2: Archive related entities together const subtree = await get_subtree({ entityName: "Project Alpha" }); await add_tags_to_multiple({ entityNames: subtree.entities.map(e => e.name), tags: ["archive-together"] }); await archive_entities({ tags: ["archive-together"] }, false); ``` --- ## Integration Examples ### With Hierarchies ```javascript // Archive completed project subtrees const roots = await get_root_entities(); for (const root of roots) { if (root.tags?.includes("completed")) { const subtree = await get_subtree({ entityName: root.name }); const names = subtree.entities.map(e => e.name); await add_tags_to_multiple({ entityNames: names, tags: ["completed-subtree"] }); await archive_entities({ tags: ["completed-subtree"] }, false); console.log(`Archived completed project: ${root.name} (${names.length} entities)`); } } ``` ### With Search ```javascript // Archive old search results const results = await search_nodes({ query: "deprecated", minImportance: 0, maxImportance: 3 }); const oldResults = results.filter(e => { const age = new Date() - new Date(e.lastModified || e.createdAt); const threeMonths = 3 * 30 * 24 * 60 * 60 * 1000; return age > threeMonths; }); if (oldResults.length > 0) { await add_tags_to_multiple({ entityNames: oldResults.map(e => e.name), tags: ["search-archive"] }); await archive_entities({ tags: ["search-archive"] }, false); } ``` ### With Compression ```javascript // Compress before archiving (maximize efficiency) async function compressThenArchive(criteria) { // Step 1: Compress graph const compression = await compress_graph({ threshold: 0.8, dryRun: false }); console.log(`Compressed: ${compression.entitiesMerged} entities merged`); // Step 2: Archive old/unimportant entities const archiving = await archive_entities(criteria, false); console.log(`Archived: ${archiving.archived} entities`); // Step 3: Report const stats = await get_graph_stats(); console.log(`Final graph size: ${stats.totalEntities} entities`); return { compression, archiving, stats }; } // Usage await compressThenArchive({ olderThan: "2025-01-01", importanceLessThan: 4 }); ``` --- ## Summary Memory archiving provides lifecycle management for your knowledge graph: ✅ **Flexible**: Archive by age, importance, or tags (OR logic) ✅ **Safe**: Dry-run preview prevents accidental data loss ✅ **Clean**: Automatically removes relations to archived entities ✅ **Permanent**: Archived data stored separately for future reference ✅ **Efficient**: Keeps active memory focused and performant **Recommended Workflow:** 1. Define archiving criteria (age, importance, tags) 2. Preview with `archive_entities(criteria, true)` 3. Review entity list carefully 4. Execute with `archive_entities(criteria, false)` 5. Validate with `validate_graph` 6. Document in audit log **Archiving Strategies:** - **Temporal**: Archive entities older than N months/years - **Priority**: Archive low-importance entities - **Status**: Archive completed, deprecated, or draft entities - **Capacity**: Archive to maintain entity count limits - **Hybrid**: Combine multiple criteria for intelligent archiving **Next Steps:** - Read [HIERARCHY_GUIDE.md](HIERARCHY_GUIDE.md) for organizing entities - Read [COMPRESSION_GUIDE.md](COMPRESSION_GUIDE.md) for duplicate detection - Read [QUERY_LANGUAGE.md](QUERY_LANGUAGE.md) for advanced search - See [API Reference](README.md#api-reference) for complete tool documentation

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/danielsimonjr/memory-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server