{
  "schemaVersion": "1.0",
  "item": {
    "slug": "neolata-mem",
    "name": "Neolata Memory Engine",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/Jeremiaheth/neolata-mem",
    "canonicalUrl": "https://clawhub.ai/Jeremiaheth/neolata-mem",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/neolata-mem",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=neolata-mem",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "references/guide.md",
      "references/implementation-notes.md",
      "references/runtime-helpers.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/neolata-mem"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/neolata-mem",
    "agentPageUrl": "https://openagent3.xyz/skills/neolata-mem/agent",
    "manifestUrl": "https://openagent3.xyz/skills/neolata-mem/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/neolata-mem/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "neolata-mem — Agent Memory Engine",
        "body": "Graph-native memory for AI agents with hybrid search, biological decay, and zero infrastructure.\n\nnpm package: @jeremiaheth/neolata-mem\nRepository: github.com/Jeremiaheth/neolata-mem\nLicense: Elastic-2.0 | Tests: 367/367 passing (34 files) | Node: ≥18"
      },
      {
        "title": "When to Use This Skill",
        "body": "Use neolata-mem when you need:\n\nPersistent memory across sessions that survives context compaction\nSemantic search over stored facts, decisions, and findings\nMemory decay so stale information naturally fades\nMulti-agent memory with cross-agent search and graph linking\nConflict resolution — detect and evolve contradictory memories\n\nDo NOT use if:\n\nYou only need OpenClaw's built-in memorySearch (keyword + vector on workspace files)\nYou want cloud-hosted memory (use Mem0 instead)\nYou need a full knowledge graph database (use Graphiti + Neo4j)"
      },
      {
        "title": "Install",
        "body": "npm install @jeremiaheth/neolata-mem\n\nNo Docker. No Python. No Neo4j. No cloud API required.\n\nSupply-chain verification: This package has zero runtime dependencies and no install scripts. Verify before installing:\n# Check for install scripts (should show only \"test\"):\nnpm view @jeremiaheth/neolata-mem scripts\n# Check for runtime deps (should be empty):\nnpm view @jeremiaheth/neolata-mem dependencies\n# Audit the tarball contents (15 files, ~40 kB):\nnpm pack @jeremiaheth/neolata-mem --dry-run\n\nSource is fully auditable at github.com/Jeremiaheth/neolata-mem."
      },
      {
        "title": "Security & Data Flow",
        "body": "Default configuration is fully local — JSON files on disk, no network calls, no embeddings, no external services.\n\nData only leaves the host if you explicitly configure one of these:\n\nFeatureWhat leavesWhere it goesHow to avoidEmbeddings (OpenAI/NVIDIA/Azure)Memory textEmbedding API endpointUse noop embeddings or Ollama (local)LLM (OpenAI/OpenClaw/Ollama)Memory text for extraction/compressionLLM API endpointDon't configure llm option, or use OllamaSupabase storageAll memory dataYour Supabase projectUse json or memory storage (default)Webhook writethroughStore/decay event payloadsYour webhook URLDon't configure webhookWritethrough\n\nKey security properties:\n\nOnly 2 env vars are read directly by code: OPENAI_API_KEY and OPENCLAW_GATEWAY_TOKEN. All others (Supabase, NVIDIA, Azure) are passed via explicit config objects.\nAll provider URLs are validated against SSRF (private IPs blocked, cloud metadata blocked).\nSupabase: prefer anon key + RLS over service key. Service key bypasses row-level security.\nJSON storage uses atomic writes (temp file + rename) to prevent corruption.\nAll user content sent to LLMs is XML-fenced with injection guards.\nTest safely with storage: { type: 'memory' } — nothing touches disk or network.\n\nSee docs/guide.md § Security for the full security model."
      },
      {
        "title": "Quick Start (Zero Config)",
        "body": "import { createMemory } from '@jeremiaheth/neolata-mem';\n\nconst mem = createMemory();\nawait mem.store('agent-1', 'User prefers dark mode');\nconst results = await mem.search('agent-1', 'UI preferences');\n\nWorks immediately with local JSON storage and keyword search. No API keys needed."
      },
      {
        "title": "With Semantic Search",
        "body": "const mem = createMemory({\n  embeddings: {\n    type: 'openai',\n    apiKey: process.env.OPENAI_API_KEY,\n    model: 'text-embedding-3-small',\n  },\n});\n\n// Agent IDs like 'kuro' and 'maki' are just examples — use any string.\nawait mem.store('kuro', 'Found XSS in login form', { category: 'finding', importance: 0.9 });\nconst results = await mem.search('kuro', 'security vulnerabilities');\n\nSupports 5+ embedding providers: OpenAI, NVIDIA NIM, Ollama, Azure, Together, or any OpenAI-compatible endpoint."
      },
      {
        "title": "Hybrid Search (Vector + Keyword Fallback)",
        "body": "Uses semantic similarity when embeddings are configured; falls back to tokenized keyword matching when they're not:\n\n// With embeddings → vector cosine similarity search\n// Without embeddings → normalized keyword matching (stop word removal, lowercase, dedup)\nconst results = await mem.search('agent', 'security vulnerabilities');\n\nKeyword search uses an inverted token index for O(1) lookups. When >500 memories exist, vector search pre-filters candidates using token overlap before cosine similarity (candidate narrowing)."
      },
      {
        "title": "Biological Decay",
        "body": "Memories fade over time unless reinforced. Old, unaccessed memories naturally lose relevance:\n\nawait mem.decay();        // Run maintenance — archive/delete stale memories\nawait mem.reinforce(id);  // Boost a memory to resist decay"
      },
      {
        "title": "Memory Graph (Zettelkasten Linking)",
        "body": "Every memory is automatically linked to related memories by semantic similarity:\n\nconst links = await mem.links(memoryId);     // Direct connections\nconst path = await mem.path(idA, idB);       // Shortest path between memories\nconst clusters = await mem.clusters();        // Detect topic clusters"
      },
      {
        "title": "Conflict Resolution & Quarantine",
        "body": "Detect contradictions before storing — with claim-based structural detection or LLM-based semantic detection:\n\n// Structural (no LLM needed): claim-based conflict detection\nawait mem.store('agent', 'Server uses port 443', {\n  claim: { subject: 'server', predicate: 'port', value: '443' },\n  provenance: { source: 'user_explicit', trust: 1.0 },\n  onConflict: 'quarantine',  // low-trust conflicts quarantined for review\n});\n\n// Semantic (requires LLM): LLM classifies as conflict/update/novel\nawait mem.evolve('agent', 'Server now uses port 8080');\n\n// Review quarantined memories\nconst quarantined = await mem.listQuarantined();\nawait mem.reviewQuarantine(quarantined[0].id, { action: 'activate' });"
      },
      {
        "title": "Predicate Schema Registry",
        "body": "Define per-predicate rules for conflict handling, normalization, and deduplication:\n\nconst mem = createMemory({\n  predicateSchemas: {\n    'preferred_language': { cardinality: 'single', conflictPolicy: 'supersede', normalize: 'lowercase_trim' },\n    'spoken_languages':   { cardinality: 'multi', dedupPolicy: 'corroborate' },\n    'salary':             { cardinality: 'single', conflictPolicy: 'require_review', normalize: 'currency' },\n  },\n});\n\nOptions: cardinality (single/multi), conflictPolicy (supersede/require_review/keep_both), normalize (none/trim/lowercase/lowercase_trim/currency), dedupPolicy (corroborate/store)."
      },
      {
        "title": "Explainability API",
        "body": "Understand why search returned or filtered specific memories:\n\nconst results = await mem.search('agent', 'query', { explain: true });\nconsole.log(results.meta);        // query options, result count\nconsole.log(results[0].explain);  // retrieved, rerank, statusFilter details\n\nconst detail = await mem.explainMemory(memoryId);\n// { id, status, trust, confidence, provenance, claimSummary }"
      },
      {
        "title": "Multi-Agent Support",
        "body": "await mem.store('kuro', 'Vuln found in API gateway');\nawait mem.store('maki', 'API gateway deployed to prod');\nconst all = await mem.searchAll('API gateway');  // Cross-agent search"
      },
      {
        "title": "Episodes (Temporal Grouping)",
        "body": "Group related memories into named episodes:\n\nconst ep = await mem.createEpisode('Deploy v2.0', [id1, id2, id3], { tags: ['deploy'] });\nconst ep2 = await mem.captureEpisode('kuro', 'Standup', { start: '...', end: '...' });\nconst results = await mem.searchEpisode(ep.id, 'database migration');\nconst { summary } = await mem.summarizeEpisode(ep.id);  // requires LLM"
      },
      {
        "title": "Memory Compression & Consolidation",
        "body": "Consolidate redundant memories into digests:\n\nawait mem.compress([id1, id2, id3], { method: 'llm', archiveOriginals: true });\nawait mem.compressEpisode(episodeId);\nawait mem.autoCompress({ minClusterSize: 3, maxDigests: 5 });\n\n// Full maintenance: dedup → contradictions → corroborate → compress → prune\nawait mem.consolidate({ dedupThreshold: 0.95, compressAge: 30, pruneAge: 90 });"
      },
      {
        "title": "Labeled Clusters",
        "body": "Persistent named groups:\n\nawait mem.createCluster('Security findings', [id1, id2]);\nawait mem.autoLabelClusters();  // LLM labels unlabeled clusters"
      },
      {
        "title": "Event Emitter",
        "body": "Hook into the memory lifecycle:\n\nmem.on('store', ({ agent, content, id }) => { /* ... */ });\nmem.on('search', ({ agent, query, results }) => { /* ... */ });\nmem.on('decay', ({ archived, deleted, dryRun }) => { /* counts, not arrays */ });"
      },
      {
        "title": "Batch APIs",
        "body": "Amortize embedding calls and I/O with bulk operations:\n\n// Store many memories in one call (single embed batch + single persist)\nconst result = await mem.storeMany('agent', [\n  { text: 'Fact one', category: 'fact', importance: 0.8 },\n  { text: 'Fact two', tags: ['infra'] },\n  'Plain string also works',\n]);\n// { total: 3, stored: 3, results: [{ id, links }, ...] }\n\n// Search multiple queries in one call (single embed batch)\nconst results = await mem.searchMany('agent', ['query one', 'query two']);\n// [{ query: 'query one', results: [...] }, { query: 'query two', results: [...] }]\n\nBatch operations include:\n\nAtomic rollback on persist failure (memories, indexes, backlinks all reverted)\nCross-linking within the same batch\nConfigurable caps: maxBatchSize (default 1000), maxQueryBatchSize (default 100)"
      },
      {
        "title": "Bulk Ingestion with Fact Extraction",
        "body": "Extract atomic facts from text using an LLM, then store each with A-MEM linking:\n\nconst mem = createMemory({\n  embeddings: { type: 'openai', apiKey: process.env.OPENAI_API_KEY },\n  extraction: { type: 'llm', apiKey: process.env.OPENAI_API_KEY },\n});\n\nconst result = await mem.ingest('agent', longText);\n// { total: 12, stored: 10, results: [...] }"
      },
      {
        "title": "CLI",
        "body": "npx neolata-mem store myagent \"Important fact here\"\nnpx neolata-mem search myagent \"query\"\nnpx neolata-mem decay --dry-run\nnpx neolata-mem health\nnpx neolata-mem clusters"
      },
      {
        "title": "OpenClaw Integration",
        "body": "neolata-mem complements OpenClaw's built-in memorySearch:\n\nmemorySearch = searches your workspace .md files (BM25 + vector)\nneolata-mem = structured memory store with graph, decay, evolution, multi-agent\n\nUse both together: memorySearch for workspace file recall, neolata-mem for agent-managed knowledge."
      },
      {
        "title": "Recommended Setup",
        "body": "In your agent's daily cron or heartbeat:\n\n// Store important facts from today's session\nawait mem.store(agentId, 'Key decision: migrated to Postgres', {\n  category: 'decision',\n  importance: 0.8,\n  tags: ['infrastructure'],\n});\n\n// Run decay maintenance\nawait mem.decay();"
      },
      {
        "title": "Comparison",
        "body": "Featureneolata-memMem0OpenClaw memorySearchLocal-first (data stays on machine)✅ (default)❌✅Hybrid search (vector + keyword)✅❌✅Memory decay✅❌❌Memory graph / linking✅❌❌Conflict resolution✅Partial❌Quarantine lane✅❌❌Predicate schemas✅❌❌Explainability API✅❌❌Episodes & compression✅❌❌Labeled clusters✅❌❌Multi-agent✅✅Per-agentZero infrastructure✅❌✅Event emitter✅❌❌Batch APIs (storeMany/searchMany)✅❌❌npm package✅✅Built-in"
      },
      {
        "title": "Security",
        "body": "neolata-mem includes hardening against common agent memory attack vectors:\n\nPrompt injection mitigation: XML-fenced user content in all LLM prompts + structural output validation\nInput validation: Agent names (alphanumeric, max 64), text length caps (10KB), bounded memory count (50K), batch size caps (1000 store / 100 query)\nBatch atomicity: storeMany rolls back all memories, indexes, and backlinks on persist failure\nSSRF protection: All provider URLs validated via validateBaseUrl() — blocks cloud metadata endpoints (169.254.169.254), private IP ranges, non-HTTP protocols\nSupabase hardening: UUID validation on query params, error text sanitized (strips tokens/keys), upsert-based save (crash-safe), 429 retry with backoff\nAtomic writes: Write-to-temp + rename prevents file corruption\nPath traversal guards: Storage directories and write-through paths validated with resolve() + prefix checks\nCryptographic IDs: crypto.randomUUID() — no predictable memory references\nRetry bounds: Exponential backoff with max 3 retries on 429s\nError surfacing: Failed conflict detection returns { error } instead of silent fallthrough\n\nSupabase key guidance: Prefer the anon key with Row Level Security (RLS) policies over the service role key. The service key bypasses RLS and grants full access to all stored memories. Only use it for admin/migration tasks.\n\nSee the full security section for details."
      },
      {
        "title": "Data Residency & External API Usage",
        "body": "Local-only mode (default): Memories are stored as JSON at ./neolata-mem-data/graph.json (relative to CWD). No data leaves your machine. Keyword search works without any API keys.\n\nWith embeddings/extraction/LLM: When you configure an external provider (OpenAI, NIM, Ollama, etc.), your memory text is sent to that provider's API for embedding or extraction. This is opt-in — you must explicitly provide an API key and base URL.\n\nModeData sent externally?Storage locationDefault (no config)❌ No./neolata-mem-data/graph.jsonOllama embeddings❌ No (local)./neolata-mem-data/graph.jsonOpenAI/NIM embeddings⚠️ Memory text → provider./neolata-mem-data/graph.jsonSupabase storage⚠️ All data → SupabaseSupabase PostgreSQLLLM conflict resolution⚠️ Memory text → providerStorage unchanged\n\nTo keep all data local: Use Ollama for embeddings and JSON storage. No API keys needed for keyword-only search."
      },
      {
        "title": "Links",
        "body": "npm: @jeremiaheth/neolata-mem\nGitHub: Jeremiaheth/neolata-mem\nFull docs: See docs/guide.md in the package"
      }
    ],
    "body": "neolata-mem — Agent Memory Engine\n\nGraph-native memory for AI agents with hybrid search, biological decay, and zero infrastructure.\n\nnpm package: @jeremiaheth/neolata-mem Repository: github.com/Jeremiaheth/neolata-mem License: Elastic-2.0 | Tests: 367/367 passing (34 files) | Node: ≥18\n\nWhen to Use This Skill\n\nUse neolata-mem when you need:\n\nPersistent memory across sessions that survives context compaction\nSemantic search over stored facts, decisions, and findings\nMemory decay so stale information naturally fades\nMulti-agent memory with cross-agent search and graph linking\nConflict resolution — detect and evolve contradictory memories\n\nDo NOT use if:\n\nYou only need OpenClaw's built-in memorySearch (keyword + vector on workspace files)\nYou want cloud-hosted memory (use Mem0 instead)\nYou need a full knowledge graph database (use Graphiti + Neo4j)\nInstall\nnpm install @jeremiaheth/neolata-mem\n\n\nNo Docker. No Python. No Neo4j. No cloud API required.\n\nSupply-chain verification: This package has zero runtime dependencies and no install scripts. Verify before installing:\n\n# Check for install scripts (should show only \"test\"):\nnpm view @jeremiaheth/neolata-mem scripts\n# Check for runtime deps (should be empty):\nnpm view @jeremiaheth/neolata-mem dependencies\n# Audit the tarball contents (15 files, ~40 kB):\nnpm pack @jeremiaheth/neolata-mem --dry-run\n\n\nSource is fully auditable at github.com/Jeremiaheth/neolata-mem.\n\nSecurity & Data Flow\n\nDefault configuration is fully local — JSON files on disk, no network calls, no embeddings, no external services.\n\nData only leaves the host if you explicitly configure one of these:\n\nFeature\tWhat leaves\tWhere it goes\tHow to avoid\nEmbeddings (OpenAI/NVIDIA/Azure)\tMemory text\tEmbedding API endpoint\tUse noop embeddings or Ollama (local)\nLLM (OpenAI/OpenClaw/Ollama)\tMemory text for extraction/compression\tLLM API endpoint\tDon't configure llm option, or use Ollama\nSupabase storage\tAll memory data\tYour Supabase project\tUse json or memory storage (default)\nWebhook writethrough\tStore/decay event payloads\tYour webhook URL\tDon't configure webhookWritethrough\n\nKey security properties:\n\nOnly 2 env vars are read directly by code: OPENAI_API_KEY and OPENCLAW_GATEWAY_TOKEN. All others (Supabase, NVIDIA, Azure) are passed via explicit config objects.\nAll provider URLs are validated against SSRF (private IPs blocked, cloud metadata blocked).\nSupabase: prefer anon key + RLS over service key. Service key bypasses row-level security.\nJSON storage uses atomic writes (temp file + rename) to prevent corruption.\nAll user content sent to LLMs is XML-fenced with injection guards.\nTest safely with storage: { type: 'memory' } — nothing touches disk or network.\n\nSee docs/guide.md § Security for the full security model.\n\nQuick Start (Zero Config)\nimport { createMemory } from '@jeremiaheth/neolata-mem';\n\nconst mem = createMemory();\nawait mem.store('agent-1', 'User prefers dark mode');\nconst results = await mem.search('agent-1', 'UI preferences');\n\n\nWorks immediately with local JSON storage and keyword search. No API keys needed.\n\nWith Semantic Search\nconst mem = createMemory({\n  embeddings: {\n    type: 'openai',\n    apiKey: process.env.OPENAI_API_KEY,\n    model: 'text-embedding-3-small',\n  },\n});\n\n// Agent IDs like 'kuro' and 'maki' are just examples — use any string.\nawait mem.store('kuro', 'Found XSS in login form', { category: 'finding', importance: 0.9 });\nconst results = await mem.search('kuro', 'security vulnerabilities');\n\n\nSupports 5+ embedding providers: OpenAI, NVIDIA NIM, Ollama, Azure, Together, or any OpenAI-compatible endpoint.\n\nKey Features\nHybrid Search (Vector + Keyword Fallback)\n\nUses semantic similarity when embeddings are configured; falls back to tokenized keyword matching when they're not:\n\n// With embeddings → vector cosine similarity search\n// Without embeddings → normalized keyword matching (stop word removal, lowercase, dedup)\nconst results = await mem.search('agent', 'security vulnerabilities');\n\n\nKeyword search uses an inverted token index for O(1) lookups. When >500 memories exist, vector search pre-filters candidates using token overlap before cosine similarity (candidate narrowing).\n\nBiological Decay\n\nMemories fade over time unless reinforced. Old, unaccessed memories naturally lose relevance:\n\nawait mem.decay();        // Run maintenance — archive/delete stale memories\nawait mem.reinforce(id);  // Boost a memory to resist decay\n\nMemory Graph (Zettelkasten Linking)\n\nEvery memory is automatically linked to related memories by semantic similarity:\n\nconst links = await mem.links(memoryId);     // Direct connections\nconst path = await mem.path(idA, idB);       // Shortest path between memories\nconst clusters = await mem.clusters();        // Detect topic clusters\n\nConflict Resolution & Quarantine\n\nDetect contradictions before storing — with claim-based structural detection or LLM-based semantic detection:\n\n// Structural (no LLM needed): claim-based conflict detection\nawait mem.store('agent', 'Server uses port 443', {\n  claim: { subject: 'server', predicate: 'port', value: '443' },\n  provenance: { source: 'user_explicit', trust: 1.0 },\n  onConflict: 'quarantine',  // low-trust conflicts quarantined for review\n});\n\n// Semantic (requires LLM): LLM classifies as conflict/update/novel\nawait mem.evolve('agent', 'Server now uses port 8080');\n\n// Review quarantined memories\nconst quarantined = await mem.listQuarantined();\nawait mem.reviewQuarantine(quarantined[0].id, { action: 'activate' });\n\nPredicate Schema Registry\n\nDefine per-predicate rules for conflict handling, normalization, and deduplication:\n\nconst mem = createMemory({\n  predicateSchemas: {\n    'preferred_language': { cardinality: 'single', conflictPolicy: 'supersede', normalize: 'lowercase_trim' },\n    'spoken_languages':   { cardinality: 'multi', dedupPolicy: 'corroborate' },\n    'salary':             { cardinality: 'single', conflictPolicy: 'require_review', normalize: 'currency' },\n  },\n});\n\n\nOptions: cardinality (single/multi), conflictPolicy (supersede/require_review/keep_both), normalize (none/trim/lowercase/lowercase_trim/currency), dedupPolicy (corroborate/store).\n\nExplainability API\n\nUnderstand why search returned or filtered specific memories:\n\nconst results = await mem.search('agent', 'query', { explain: true });\nconsole.log(results.meta);        // query options, result count\nconsole.log(results[0].explain);  // retrieved, rerank, statusFilter details\n\nconst detail = await mem.explainMemory(memoryId);\n// { id, status, trust, confidence, provenance, claimSummary }\n\nMulti-Agent Support\nawait mem.store('kuro', 'Vuln found in API gateway');\nawait mem.store('maki', 'API gateway deployed to prod');\nconst all = await mem.searchAll('API gateway');  // Cross-agent search\n\nEpisodes (Temporal Grouping)\n\nGroup related memories into named episodes:\n\nconst ep = await mem.createEpisode('Deploy v2.0', [id1, id2, id3], { tags: ['deploy'] });\nconst ep2 = await mem.captureEpisode('kuro', 'Standup', { start: '...', end: '...' });\nconst results = await mem.searchEpisode(ep.id, 'database migration');\nconst { summary } = await mem.summarizeEpisode(ep.id);  // requires LLM\n\nMemory Compression & Consolidation\n\nConsolidate redundant memories into digests:\n\nawait mem.compress([id1, id2, id3], { method: 'llm', archiveOriginals: true });\nawait mem.compressEpisode(episodeId);\nawait mem.autoCompress({ minClusterSize: 3, maxDigests: 5 });\n\n// Full maintenance: dedup → contradictions → corroborate → compress → prune\nawait mem.consolidate({ dedupThreshold: 0.95, compressAge: 30, pruneAge: 90 });\n\nLabeled Clusters\n\nPersistent named groups:\n\nawait mem.createCluster('Security findings', [id1, id2]);\nawait mem.autoLabelClusters();  // LLM labels unlabeled clusters\n\nEvent Emitter\n\nHook into the memory lifecycle:\n\nmem.on('store', ({ agent, content, id }) => { /* ... */ });\nmem.on('search', ({ agent, query, results }) => { /* ... */ });\nmem.on('decay', ({ archived, deleted, dryRun }) => { /* counts, not arrays */ });\n\nBatch APIs\n\nAmortize embedding calls and I/O with bulk operations:\n\n// Store many memories in one call (single embed batch + single persist)\nconst result = await mem.storeMany('agent', [\n  { text: 'Fact one', category: 'fact', importance: 0.8 },\n  { text: 'Fact two', tags: ['infra'] },\n  'Plain string also works',\n]);\n// { total: 3, stored: 3, results: [{ id, links }, ...] }\n\n// Search multiple queries in one call (single embed batch)\nconst results = await mem.searchMany('agent', ['query one', 'query two']);\n// [{ query: 'query one', results: [...] }, { query: 'query two', results: [...] }]\n\n\nBatch operations include:\n\nAtomic rollback on persist failure (memories, indexes, backlinks all reverted)\nCross-linking within the same batch\nConfigurable caps: maxBatchSize (default 1000), maxQueryBatchSize (default 100)\nBulk Ingestion with Fact Extraction\n\nExtract atomic facts from text using an LLM, then store each with A-MEM linking:\n\nconst mem = createMemory({\n  embeddings: { type: 'openai', apiKey: process.env.OPENAI_API_KEY },\n  extraction: { type: 'llm', apiKey: process.env.OPENAI_API_KEY },\n});\n\nconst result = await mem.ingest('agent', longText);\n// { total: 12, stored: 10, results: [...] }\n\nCLI\nnpx neolata-mem store myagent \"Important fact here\"\nnpx neolata-mem search myagent \"query\"\nnpx neolata-mem decay --dry-run\nnpx neolata-mem health\nnpx neolata-mem clusters\n\nOpenClaw Integration\n\nneolata-mem complements OpenClaw's built-in memorySearch:\n\nmemorySearch = searches your workspace .md files (BM25 + vector)\nneolata-mem = structured memory store with graph, decay, evolution, multi-agent\n\nUse both together: memorySearch for workspace file recall, neolata-mem for agent-managed knowledge.\n\nRecommended Setup\n\nIn your agent's daily cron or heartbeat:\n\n// Store important facts from today's session\nawait mem.store(agentId, 'Key decision: migrated to Postgres', {\n  category: 'decision',\n  importance: 0.8,\n  tags: ['infrastructure'],\n});\n\n// Run decay maintenance\nawait mem.decay();\n\nComparison\nFeature\tneolata-mem\tMem0\tOpenClaw memorySearch\nLocal-first (data stays on machine)\t✅ (default)\t❌\t✅\nHybrid search (vector + keyword)\t✅\t❌\t✅\nMemory decay\t✅\t❌\t❌\nMemory graph / linking\t✅\t❌\t❌\nConflict resolution\t✅\tPartial\t❌\nQuarantine lane\t✅\t❌\t❌\nPredicate schemas\t✅\t❌\t❌\nExplainability API\t✅\t❌\t❌\nEpisodes & compression\t✅\t❌\t❌\nLabeled clusters\t✅\t❌\t❌\nMulti-agent\t✅\t✅\tPer-agent\nZero infrastructure\t✅\t❌\t✅\nEvent emitter\t✅\t❌\t❌\nBatch APIs (storeMany/searchMany)\t✅\t❌\t❌\nnpm package\t✅\t✅\tBuilt-in\nSecurity\n\nneolata-mem includes hardening against common agent memory attack vectors:\n\nPrompt injection mitigation: XML-fenced user content in all LLM prompts + structural output validation\nInput validation: Agent names (alphanumeric, max 64), text length caps (10KB), bounded memory count (50K), batch size caps (1000 store / 100 query)\nBatch atomicity: storeMany rolls back all memories, indexes, and backlinks on persist failure\nSSRF protection: All provider URLs validated via validateBaseUrl() — blocks cloud metadata endpoints (169.254.169.254), private IP ranges, non-HTTP protocols\nSupabase hardening: UUID validation on query params, error text sanitized (strips tokens/keys), upsert-based save (crash-safe), 429 retry with backoff\nAtomic writes: Write-to-temp + rename prevents file corruption\nPath traversal guards: Storage directories and write-through paths validated with resolve() + prefix checks\nCryptographic IDs: crypto.randomUUID() — no predictable memory references\nRetry bounds: Exponential backoff with max 3 retries on 429s\nError surfacing: Failed conflict detection returns { error } instead of silent fallthrough\n\nSupabase key guidance: Prefer the anon key with Row Level Security (RLS) policies over the service role key. The service key bypasses RLS and grants full access to all stored memories. Only use it for admin/migration tasks.\n\nSee the full security section for details.\n\nData Residency & External API Usage\n\nLocal-only mode (default): Memories are stored as JSON at ./neolata-mem-data/graph.json (relative to CWD). No data leaves your machine. Keyword search works without any API keys.\n\nWith embeddings/extraction/LLM: When you configure an external provider (OpenAI, NIM, Ollama, etc.), your memory text is sent to that provider's API for embedding or extraction. This is opt-in — you must explicitly provide an API key and base URL.\n\nMode\tData sent externally?\tStorage location\nDefault (no config)\t❌ No\t./neolata-mem-data/graph.json\nOllama embeddings\t❌ No (local)\t./neolata-mem-data/graph.json\nOpenAI/NIM embeddings\t⚠️ Memory text → provider\t./neolata-mem-data/graph.json\nSupabase storage\t⚠️ All data → Supabase\tSupabase PostgreSQL\nLLM conflict resolution\t⚠️ Memory text → provider\tStorage unchanged\n\nTo keep all data local: Use Ollama for embeddings and JSON storage. No API keys needed for keyword-only search.\n\nLinks\nnpm: @jeremiaheth/neolata-mem\nGitHub: Jeremiaheth/neolata-mem\nFull docs: See docs/guide.md in the package"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/Jeremiaheth/neolata-mem",
    "publisherUrl": "https://clawhub.ai/Jeremiaheth/neolata-mem",
    "owner": "Jeremiaheth",
    "version": "0.8.5",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/neolata-mem",
    "downloadUrl": "https://openagent3.xyz/downloads/neolata-mem",
    "agentUrl": "https://openagent3.xyz/skills/neolata-mem/agent",
    "manifestUrl": "https://openagent3.xyz/skills/neolata-mem/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/neolata-mem/agent.md"
  }
}