repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources15d ago| #1 | # API Reference - Clawd Memory |
| #2 | |
| #3 | This page documents the Clawd-facing API first, then the lower-level Mnemosyne engine API. |
| #4 | |
| #5 | ## ClawdBrain Quick Start |
| #6 | |
| #7 | ```python |
| #8 | from mnemosyne.clawd_brain import ClawdBrain |
| #9 | |
| #10 | brain = ClawdBrain() |
| #11 | |
| #12 | brain.remember( |
| #13 | "Solana RPC Provider", |
| #14 | "The Clawd gateway should use Helius for Solana RPC and websocket access.", |
| #15 | kind="protocol", |
| #16 | source="clawd", |
| #17 | tags=["solana", "helius"], |
| #18 | importance=0.8, |
| #19 | ) |
| #20 | |
| #21 | results = brain.recall("Solana RPC provider", top_k=5) |
| #22 | status = brain.status() |
| #23 | ``` |
| #24 | |
| #25 | ## Clawd CLI |
| #26 | |
| #27 | ```bash |
| #28 | clawd-brain init |
| #29 | clawd-brain status |
| #30 | clawd-brain remember TITLE CONTENT --kind agent --tag clawd --importance 0.9 |
| #31 | clawd-brain recall QUERY --top-k 8 |
| #32 | clawd-brain research URL_OR_TOPIC --tag solana |
| #33 | clawd-brain ingest-ooda --journal ../ooda/journal/ticks.jsonl --limit 100 |
| #34 | ``` |
| #35 | |
| #36 | Module form: |
| #37 | |
| #38 | ```bash |
| #39 | python3 -m mnemosyne.clawd_brain recall "agent preferences" |
| #40 | ``` |
| #41 | |
| #42 | Compatibility note: `mnemosyne` remains the Python package and storage engine. Use `ClawdBrain` for Clawd agent workflows. |
| #43 | |
| #44 | ## Engine Quick Start |
| #45 | |
| #46 | ```python |
| #47 | from mnemosyne import Mnemosyne |
| #48 | |
| #49 | # Initialize (uses ~/.hermes/mnemosyne/data/ by default) |
| #50 | mem = Mnemosyne() |
| #51 | |
| #52 | # Store memories |
| #53 | mem.remember("User prefers dark mode", importance=0.9) |
| #54 | |
| #55 | # Recall memories |
| #56 | results = mem.recall("user preferences", top_k=5) |
| #57 | |
| #58 | # Get stats |
| #59 | stats = mem.get_stats() |
| #60 | ``` |
| #61 | |
| #62 | --- |
| #63 | |
| #64 | ## Module-Level Convenience Functions |
| #65 | |
| #66 | ```python |
| #67 | from mnemosyne import remember, recall, get_stats, forget, update, get_context |
| #68 | ``` |
| #69 | |
| #70 | These functions create a default `Mnemosyne` instance and delegate to it. The optional `bank` parameter applies only to these module-level helpers; instance methods use the bank configured on `Mnemosyne(...)`. |
| #71 | |
| #72 | | Function | Signature | Description | |
| #73 | |---|---|---| |
| #74 | | `remember()` | `(content, source="conversation", importance=0.5, **kwargs) -> str` | Store a memory, returns memory ID | |
| #75 | | `recall()` | `(query, top_k=5, **kwargs) -> list` | Search memories | |
| #76 | | `get_stats()` | `() -> dict` | Memory statistics | |
| #77 | | `forget()` | `(memory_id) -> bool` | Delete a memory | |
| #78 | | `update()` | `(memory_id, **kwargs) -> bool` | Update a memory | |
| #79 | | `get_context()` | `(limit=10, bank=None) -> list[dict]` | Get recent working-memory context | |
| #80 | |
| #81 | --- |
| #82 | |
| #83 | ## Mnemosyne Class |
| #84 | |
| #85 | **Module:** `mnemosyne.core.memory` |
| #86 | |
| #87 | ```python |
| #88 | from mnemosyne.core.memory import Mnemosyne |
| #89 | |
| #90 | # Default instance |
| #91 | mem = Mnemosyne() |
| #92 | |
| #93 | # With custom database path |
| #94 | from pathlib import Path |
| #95 | mem = Mnemosyne(db_path=Path("/path/to/mnemosyne.db")) |
| #96 | |
| #97 | # With memory bank |
| #98 | mem = Mnemosyne(bank="work") |
| #99 | |
| #100 | # With session ID |
| #101 | mem = Mnemosyne(session_id="my-agent-session") |
| #102 | ``` |
| #103 | |
| #104 | ### Constructor |
| #105 | |
| #106 | ```python |
| #107 | Mnemosyne( |
| #108 | session_id: str = "default", # Session identifier |
| #109 | db_path: Path = None, # Custom database path |
| #110 | bank: str = None, # Memory bank name for isolation |
| #111 | author_id: str = None, |
| #112 | author_type: str = None, |
| #113 | channel_id: str = None, |
| #114 | ) |
| #115 | ``` |
| #116 | |
| #117 | ### `remember()` |
| #118 | |
| #119 | Store a memory. Returns the memory ID. |
| #120 | |
| #121 | ```python |
| #122 | memory_id = mem.remember( |
| #123 | content: str, # The text to remember |
| #124 | source: str = "conversation", # Origin: "conversation", "document", "system" |
| #125 | importance: float = 0.5, # 0.0–1.0 relevance score |
| #126 | metadata: dict = None, # Optional additional fields |
| #127 | valid_until: str = None, # ISO timestamp when this memory expires |
| #128 | scope: str = "session", # "session" or "global" |
| #129 | extract_entities: bool = False, # Extract entity mentions as triples |
| #130 | extract: bool = False # Extract structured facts via LLM |
| #131 | ) |
| #132 | ``` |
| #133 | |
| #134 | **Examples:** |
| #135 | |
| #136 | ```python |
| #137 | # Basic storage |
| #138 | mid = mem.remember("User prefers dark mode", importance=0.9) |
| #139 | |
| #140 | # With entity extraction |
| #141 | mid = mem.remember("Abdias founded Mnemosyne in New York", |
| #142 | extract_entities=True) |
| #143 | |
| #144 | # With fact extraction (requires LLM) |
| #145 | mid = mem.remember("The project deadline is June 15th", |
| #146 | extract=True, importance=0.8) |
| #147 | |
| #148 | # Session-scoped (auto-evicted after TTL) |
| #149 | mid = mem.remember("Current task: fixing bug #42", |
| #150 | scope="session", source="system") |
| #151 | |
| #152 | # Global (persists across sessions) |
| #153 | mid = mem.remember("User's timezone is EST", |
| #154 | scope="global") |
| #155 | ``` |
| #156 | |
| #157 | ### `recall()` |
| #158 | |
| #159 | Search memories using hybrid vector + FTS + importance scoring. |
| #160 | |
| #161 | ```python |
| #162 | results = mem.recall( |
| #163 | query: str, # Search query |
| #164 | top_k: int = 5, # Number of results |
| #165 | from_date: str = None, # Optional lower timestamp bound |
| #166 | to_date: str = None, # Optional upper timestamp bound |
| #167 | source: str = None, # Filter by source |
| #168 | topic: str = None, # Filter by topic metadata |
| #169 | author_id: str = None, # Filter by author identity |
| #170 | author_type: str = None, # Filter by human/agent/system author type |
| #171 | channel_id: str = None, # Filter by channel/group |
| #172 | temporal_weight: float = 0.0, # 0.0–1.0, boosts memories near query_time |
| #173 | query_time = None, # datetime or ISO string for temporal calculation |
| #174 | temporal_halflife: float = None, # Hours for decay (default: 24) |
| #175 | vec_weight: float = None, # Override vector scoring weight |
| #176 | fts_weight: float = None, # Override FTS scoring weight |
| #177 | importance_weight: float = None # Override importance weight |
| #178 | ) |
| #179 | ``` |
| #180 | |
| #181 | Returns a list of dicts with keys: `id`, `content`, `score`, `source`, `timestamp`, `importance`, `scope`, `metadata`. |
| #182 | |
| #183 | **Examples:** |
| #184 | |
| #185 | ```python |
| #186 | # Basic recall |
| #187 | results = mem.recall("user preferences") |
| #188 | |
| #189 | # Temporal boost — prefer recent memories |
| #190 | results = mem.recall("current task", temporal_weight=0.5) |
| #191 | |
| #192 | # Custom scoring weights |
| #193 | results = mem.recall("python code", |
| #194 | vec_weight=0.7, fts_weight=0.2, importance_weight=0.1) |
| #195 | |
| #196 | # Filter by source |
| #197 | results = mem.recall("meeting notes", source="document") |
| #198 | ``` |
| #199 | |
| #200 | ### `update()` |
| #201 | |
| #202 | Update an existing memory. |
| #203 | |
| #204 | ```python |
| #205 | success = mem.update( |
| #206 | memory_id: str, |
| #207 | content: str = None, |
| #208 | importance: float = None, |
| #209 | metadata: dict = None |
| #210 | ) |
| #211 | ``` |
| #212 | |
| #213 | ### `forget()` |
| #214 | |
| #215 | Delete a memory by ID. |
| #216 | |
| #217 | ```python |
| #218 | success = mem.forget(memory_id: str) |
| #219 | ``` |
| #220 | |
| #221 | ### `sleep()` |
| #222 | |
| #223 | Run BEAM consolidation cycle — moves working memory to episodic storage. |
| #224 | |
| #225 | ```python |
| #226 | stats = mem.sleep() |
| #227 | # Returns dict with consolidation statistics |
| #228 | ``` |
| #229 | |
| #230 | ### `get_stats()` |
| #231 | |
| #232 | Get memory statistics. |
| #233 | |
| #234 | ```python |
| #235 | stats = mem.get_stats() |
| #236 | # Returns dict with counts per tier, session info, etc. |
| #237 | ``` |
| #238 | |
| #239 | ### `get_context()` |
| #240 | |
| #241 | Get recent working-memory context for prompt injection. |
| #242 | |
| #243 | ```python |
| #244 | context = mem.get_context(limit=5) |
| #245 | # Returns a list of recent working-memory dictionaries |
| #246 | ``` |
| #247 | |
| #248 | ### `export_to_file()` / `import_from_file()` |
| #249 | |
| #250 | Portable export/import for backup and migration. |
| #251 | |
| #252 | ```python |
| #253 | mem.export_to_file("backup.json") |
| #254 | mem.import_from_file("backup.json") |
| #255 | ``` |
| #256 | |
| #257 | ### v2 Properties (lazy-initialized) |
| #258 | |
| #259 | ```python |
| #260 | mem.stream # MemoryStream — event stream |
| #261 | mem.compressor # MemoryCompressor — compress/decompress |
| #262 | mem.patterns # PatternDetector — temporal/content patterns |
| #263 | mem.delta_sync # DeltaSync — incremental sync |
| #264 | mem.plugin_manager # PluginManager — plugin lifecycle |
| #265 | ``` |
| #266 | |
| #267 | --- |
| #268 | |
| #269 | ## BeamMemory Class |
| #270 | |
| #271 | **Module:** `mnemosyne.core.beam` |
| #272 | |
| #273 | The BEAM (Bilevel Episodic-Associative Memory) engine. Usually accessed through `Mnemosyne`, but can be used directly. |
| #274 | |
| #275 | ```python |
| #276 | from mnemosyne.core.beam import BeamMemory |
| #277 | |
| #278 | beam = BeamMemory( |
| #279 | session_id: str = "default", |
| #280 | db_path: Path = None |
| #281 | ) |
| #282 | ``` |
| #283 | |
| #284 | ### Key Methods |
| #285 | |
| #286 | | Method | Description | |
| #287 | |---|---| |
| #288 | | `remember(content, **kwargs) -> str` | Store to working memory | |
| #289 | | `recall(query, **kwargs) -> list` | Hybrid search across all tiers | |
| #290 | | `sleep() -> dict` | Consolidate working → episodic | |
| #291 | | `invalidate(memory_id, replacement_id=None) -> bool` | Mark memory as superseded | |
| #292 | | `scratchpad_write(content) -> str` | Write to scratchpad | |
| #293 | | `scratchpad_read() -> list[dict]` | Read scratchpad entries | |
| #294 | | `scratchpad_clear() -> None` | Clear scratchpad | |
| #295 | |
| #296 | --- |
| #297 | |
| #298 | ## Memory Banks |
| #299 | |
| #300 | **Module:** `mnemosyne.core.banks` |
| #301 | |
| #302 | ```python |
| #303 | from mnemosyne.core.banks import BankManager |
| #304 | |
| #305 | manager = BankManager(data_dir="~/.hermes/mnemosyne/data") |
| #306 | |
| #307 | # Create a bank |
| #308 | manager.create_bank("work") |
| #309 | |
| #310 | # List banks |
| #311 | banks = manager.list_banks() |
| #312 | |
| #313 | # Check if bank exists |
| #314 | exists = manager.bank_exists("work") |
| #315 | |
| #316 | # Get bank stats |
| #317 | stats = manager.get_bank_stats("work") |
| #318 | |
| #319 | # Rename a bank |
| #320 | manager.rename_bank("work", "work-v2") |
| #321 | |
| #322 | # Delete a bank |
| #323 | manager.delete_bank("work") |
| #324 | ``` |
| #325 | |
| #326 | --- |
| #327 | |
| #328 | ## Entity Extraction |
| #329 | |
| #330 | **Module:** `mnemosyne.core.entities` |
| #331 | |
| #332 | ```python |
| #333 | from mnemosyne.core.entities import ( |
| #334 | extract_entities_regex, |
| #335 | levenshtein_distance, |
| #336 | find_similar_entities |
| #337 | ) |
| #338 | |
| #339 | # Extract entities from text |
| #340 | entities = extract_entities_regex("Abdias founded Clawd Memory in New York") |
| #341 | # Returns: ["Abdias", "Clawd Memory", "New York"] |
| #342 | |
| #343 | # Fuzzy match |
| #344 | distance = levenshtein_distance("Abdias", "Abdias J") |
| #345 | |
| #346 | # Find similar entities in a list |
| #347 | matches = find_similar_entities("Abdias", ["Abdias J", "Python", "New York"], threshold=0.7) |
| #348 | ``` |
| #349 | |
| #350 | --- |
| #351 | |
| #352 | ## Fact Extraction |
| #353 | |
| #354 | **Module:** `mnemosyne.core.extraction` |
| #355 | |
| #356 | ```python |
| #357 | from mnemosyne.core.extraction import extract_facts, extract_facts_safe |
| #358 | |
| #359 | # Extract facts (may raise if no LLM available) |
| #360 | facts = extract_facts("Mnemosyne uses SQLite for storage and fastembed for embeddings.") |
| #361 | # Returns: list of fact strings |
| #362 | |
| #363 | # Safe wrapper (never raises, returns empty list on failure) |
| #364 | facts = extract_facts_safe("Some text to extract facts from") |
| #365 | ``` |
| #366 | |
| #367 | **Fallback chain:** Remote OpenAI API → Local ctransformers GGUF → Skip (returns []) |
| #368 | |
| #369 | --- |
| #370 | |
| #371 | ## Streaming & Delta Sync |
| #372 | |
| #373 | **Module:** `mnemosyne.core.streaming` |
| #374 | |
| #375 | ### MemoryStream |
| #376 | |
| #377 | ```python |
| #378 | from mnemosyne.core.streaming import MemoryStream |
| #379 | |
| #380 | stream = MemoryStream() |
| #381 | |
| #382 | # Push events |
| #383 | stream.push("remember", {"id": "abc", "content": "test"}) |
| #384 | |
| #385 | # Pull via callback |
| #386 | stream.on_event(lambda event: print(event)) |
| #387 | |
| #388 | # Pull via iterator |
| #389 | for event in stream: |
| #390 | process(event) |
| #391 | ``` |
| #392 | |
| #393 | ### DeltaSync |
| #394 | |
| #395 | ```python |
| #396 | from mnemosyne.core.streaming import DeltaSync |
| #397 | |
| #398 | sync = DeltaSync(mnemosyne_instance) |
| #399 | |
| #400 | # Compute changes since last checkpoint |
| #401 | delta = sync.compute_delta() |
| #402 | |
| #403 | # Apply delta to another instance |
| #404 | sync.apply_delta(delta) |
| #405 | |
| #406 | # Full bidirectional sync |
| #407 | sync.sync_to(other_mnemosyne) |
| #408 | sync.sync_from(other_mnemosyne) |
| #409 | ``` |
| #410 | |
| #411 | --- |
| #412 | |
| #413 | ## Pattern Detection & Compression |
| #414 | |
| #415 | **Module:** `mnemosyne.core.patterns` |
| #416 | |
| #417 | ### PatternDetector |
| #418 | |
| #419 | ```python |
| #420 | from mnemosyne.core.patterns import PatternDetector |
| #421 | |
| #422 | detector = PatternDetector() |
| #423 | |
| #424 | # Detect temporal patterns (hour-of-day, day-of-week) |
| #425 | temporal = detector.detect_temporal_patterns(memories) |
| #426 | |
| #427 | # Detect content patterns (keyword frequency, co-occurrence) |
| #428 | content = detector.detect_content_patterns(memories) |
| #429 | |
| #430 | # Detect sequence patterns |
| #431 | sequences = detector.detect_sequence_patterns(memories) |
| #432 | ``` |
| #433 | |
| #434 | ### MemoryCompressor |
| #435 | |
| #436 | ```python |
| #437 | from mnemosyne.core.patterns import MemoryCompressor |
| #438 | |
| #439 | compressor = MemoryCompressor() |
| #440 | |
| #441 | # Compress memories |
| #442 | compressed = compressor.compress(memories) |
| #443 | |
| #444 | # Decompress |
| #445 | decompressed = compressor.decompress(compressed) |
| #446 | |
| #447 | # Batch compress |
| #448 | batch = compressor.compress_batch(memory_list) |
| #449 | ``` |
| #450 | |
| #451 | --- |
| #452 | |
| #453 | ## Plugin System |
| #454 | |
| #455 | **Module:** `mnemosyne.core.plugins` |
| #456 | |
| #457 | ### Creating a Plugin |
| #458 | |
| #459 | ```python |
| #460 | from mnemosyne.core.plugins import MnemosynePlugin |
| #461 | |
| #462 | class MyPlugin(MnemosynePlugin): |
| #463 | name = "my-plugin" |
| #464 | |
| #465 | def on_remember(self, memory_id, content, **kwargs): |
| #466 | """Called after a memory is stored.""" |
| #467 | pass |
| #468 | |
| #469 | def on_recall(self, query, results, **kwargs): |
| #470 | """Called after recall. Can modify results.""" |
| #471 | return results |
| #472 | |
| #473 | def on_consolidate(self, count, **kwargs): |
| #474 | """Called after sleep() consolidation.""" |
| #475 | pass |
| #476 | |
| #477 | def on_invalidate(self, memory_id, **kwargs): |
| #478 | """Called after a memory is invalidated.""" |
| #479 | pass |
| #480 | ``` |
| #481 | |
| #482 | ### PluginManager |
| #483 | |
| #484 | ```python |
| #485 | from mnemosyne.core.plugins import PluginManager |
| #486 | |
| #487 | pm = PluginManager() |
| #488 | |
| #489 | # Register a plugin |
| #490 | pm.register(MyPlugin()) |
| #491 | |
| #492 | # Load from directory (auto-discovers .py files) |
| #493 | pm.discover("~/.hermes/mnemosyne/plugins/") |
| #494 | |
| #495 | # Unregister |
| #496 | pm.unregister("my-plugin") |
| #497 | |
| #498 | # List loaded plugins |
| #499 | plugins = pm.list_plugins() |
| #500 | ``` |
| #501 | |
| #502 | --- |
| #503 | |
| #504 | ## TripleStore (Knowledge Graph) |
| #505 | |
| #506 | **Module:** `mnemosyne.core.triples` |
| #507 | |
| #508 | ```python |
| #509 | from mnemosyne.core.triples import TripleStore |
| #510 | |
| #511 | store = TripleStore(db_path) |
| #512 | |
| #513 | # Add a triple |
| #514 | store.add_triple("user_123", "prefers", "dark_mode") |
| #515 | |
| #516 | # Query triples |
| #517 | results = store.query_triples(subject="user_123") |
| #518 | |
| #519 | # Get all triples for an entity |
| #520 | triples = store.get_triples_for_subject("memory_id_abc") |
| #521 | ``` |
| #522 | |
| #523 | --- |
| #524 | |
| #525 | ## MCP Server |
| #526 | |
| #527 | **Module:** `mnemosyne.mcp_server` |
| #528 | |
| #529 | ```bash |
| #530 | # stdio transport (for Claude Desktop, etc.) |
| #531 | mnemosyne mcp |
| #532 | |
| #533 | # SSE transport (for web clients) |
| #534 | mnemosyne mcp --transport sse --port 8080 |
| #535 | |
| #536 | # Scoped to a specific bank |
| #537 | mnemosyne mcp --bank project_a |
| #538 | ``` |
| #539 | |
| #540 | ### MCP Tools |
| #541 | |
| #542 | These are the standalone MCP server tools from `mnemosyne.mcp_tools`. The Hermes plugin exposes a larger tool surface and uses `mnemosyne_stats` rather than the MCP-only `mnemosyne_get_stats` name. |
| #543 | |
| #544 | | Tool | Description | |
| #545 | |---|---| |
| #546 | | `mnemosyne_remember` | Store a memory | |
| #547 | | `mnemosyne_recall` | Search memories | |
| #548 | | `mnemosyne_sleep` | Run consolidation | |
| #549 | | `mnemosyne_scratchpad_read` | Read scratchpad | |
| #550 | | `mnemosyne_scratchpad_write` | Write to scratchpad | |
| #551 | | `mnemosyne_get_stats` | Get memory statistics | |
| #552 | |
| #553 | --- |
| #554 | |
| #555 | ## LLM Backends (Host Adapter) |
| #556 | |
| #557 | **Module:** `mnemosyne.core.llm_backends` |
| #558 | |
| #559 | Mnemosyne can route LLM-backed operations (consolidation and fact extraction) through a host-provided backend instead of its own remote/local chain. This is used when Mnemosyne runs inside Hermes to reuse Hermes' authenticated provider (including OAuth-backed providers like ChatGPT/Codex). |
| #560 | |
| #561 | ### LLMBackend Protocol |
| #562 | |
| #563 | ```python |
| #564 | from mnemosyne.core.llm_backends import LLMBackend, set_host_llm_backend |
| #565 | |
| #566 | class MyBackend: |
| #567 | name = "my-backend" |
| #568 | |
| #569 | def complete(self, prompt, *, max_tokens, temperature, timeout, |
| #570 | provider=None, model=None): |
| #571 | # Route through your authenticated client |
| #572 | return text_or_none |
| #573 | |
| #574 | set_host_llm_backend(MyBackend()) |
| #575 | ``` |
| #576 | |
| #577 | ### Registry API |
| #578 | |
| #579 | ```python |
| #580 | from mnemosyne.core.llm_backends import ( |
| #581 | set_host_llm_backend, |
| #582 | get_host_llm_backend, |
| #583 | call_host_llm, |
| #584 | CallableLLMBackend, |
| #585 | ) |
| #586 | |
| #587 | # Register a backend |
| #588 | set_host_llm_backend(CallableLLMBackend(name="test", func=my_func)) |
| #589 | |
| #590 | # Check if registered |
| #591 | backend = get_host_llm_backend() |
| #592 | |
| #593 | # Call with automatic fallback |
| #594 | result = call_host_llm(prompt, max_tokens=256, temperature=0.3, timeout=15.0) |
| #595 | ``` |
| #596 | |
| #597 | ### Fallback Chain |
| #598 | |
| #599 | When `MNEMOSYNE_HOST_LLM_ENABLED=true`: |
| #600 | |
| #601 | ```text |
| #602 | 0. Host backend (if registered) |
| #603 | ↓ on failure: skip remote URL entirely (A3 rule) |
| #604 | 1. Local GGUF (ctransformers / llama-cpp-python) |
| #605 | ↓ on failure |
| #606 | 2. Return None / [] — caller falls back to AAAK encoding |
| #607 | ``` |
| #608 | |
| #609 | When `MNEMOSYNE_HOST_LLM_ENABLED=false` or unset: |
| #610 | |
| #611 | ```text |
| #612 | 0. Remote OpenAI-compatible API (if MNEMOSYNE_LLM_BASE_URL set) |
| #613 | ↓ on failure |
| #614 | 1. Local GGUF |
| #615 | ↓ on failure |
| #616 | 2. AAAK encoding |
| #617 | ``` |
| #618 | |
| #619 | --- |
| #620 | |
| #621 | ## Importers |
| #622 | |
| #623 | **Module:** `mnemosyne.core.importers` |
| #624 | |
| #625 | Mnemosyne can import memories from supported external providers. All importers preserve metadata, timestamps, and identity. |
| #626 | |
| #627 | ### Supported Providers |
| #628 | |
| #629 | | Provider | Class | Input | Key Preservation | |
| #630 | |---|---|---|---| |
| #631 | | **Mem0** | `Mem0Importer` | API key + user ID | User/app scoping | |
| #632 | | **Letta** | `LettaImporter` | AgentFile `.af` | Memory blocks, messages | |
| #633 | | **Zep** | `ZepImporter` | API key | Sessions, summaries, facts | |
| #634 | | **Cognee** | `CogneeImporter` | Graph data | Nodes → memories, edges → triples | |
| #635 | | **Honcho** | `HonchoImporter` | API key | Peer identity as author_id | |
| #636 | | **SuperMemory** | `SuperMemoryImporter` | API key | Container tags → channel_id | |
| #637 | | **Hindsight** | `HindsightImporter` | JSON file or HTTP API | **Timestamps, fact_type, session IDs, metadata, veracity** | |
| #638 | |
| #639 | ### HindsightImporter |
| #640 | |
| #641 | **Special behavior:** Unlike other importers that route through `remember()`, HindsightImporter writes directly to `episodic_memory`. This preserves historical timestamps and avoids working-memory session contamination. |
| #642 | |
| #643 | ```python |
| #644 | from mnemosyne.core.importers import HindsightImporter |
| #645 | |
| #646 | # From JSON export |
| #647 | importer = HindsightImporter(file_path="hindsight-export.json", bank="hermes") |
| #648 | result = importer.run(mnemosyne) |
| #649 | |
| #650 | # From live API |
| #651 | importer = HindsightImporter(base_url="http://localhost:8888", bank="hermes") |
| #652 | result = importer.run(mnemosyne) |
| #653 | |
| #654 | # Convenience wrapper |
| #655 | from mnemosyne.core.importers import import_from_hindsight |
| #656 | result = import_from_hindsight(mnemosyne, file_path="export.json", bank="hermes") |
| #657 | ``` |
| #658 | |
| #659 | **Parameters:** |
| #660 | - `file_path` — Path to Hindsight JSON export file |
| #661 | - `base_url` — Base URL of running Hindsight API (e.g., `http://localhost:8888`) |
| #662 | - `bank` — Hindsight bank name (default: `hermes`) |
| #663 | - `page_size` — API pagination size, 1–1000 (default: 500) |
| #664 | - `max_items` — Maximum memories to import (default: unlimited) |
| #665 | - `namespace` — ID namespace for stable hashing (default: bank name) |
| #666 | |
| #667 | **Result object:** |
| #668 | ```python |
| #669 | result.provider # "hindsight" |
| #670 | result.total # Total items found |
| #671 | result.imported # Successfully inserted |
| #672 | result.skipped # Duplicates or empty content |
| #673 | result.failed # Insertion errors |
| #674 | result.memory_ids # List of imported memory IDs |
| #675 | result.errors # List of error strings |
| #676 | result.started_at # ISO timestamp |
| #677 | result.finished_at # ISO timestamp |
| #678 | ``` |
| #679 | |
| #680 | ### Provider Registry |
| #681 | |
| #682 | ```python |
| #683 | from mnemosyne.core.importers import import_from_provider, PROVIDERS |
| #684 | |
| #685 | # See all supported providers |
| #686 | print(PROVIDERS.keys()) |
| #687 | # dict_keys(['mem0', 'letta', 'zep', 'cognee', 'honcho', 'supermemory', 'hindsight']) |
| #688 | |
| #689 | # Generic import dispatcher |
| #690 | result = import_from_provider("hindsight", mnemosyne, file_path="export.json") |
| #691 | ``` |
| #692 | |
| #693 | --- |
| #694 | |
| #695 | ## CLI |
| #696 | |
| #697 | ```bash |
| #698 | mnemosyne store "User prefers dark mode" --importance 0.9 |
| #699 | mnemosyne recall "user preferences" 10 |
| #700 | mnemosyne update <memory_id> "Updated content" |
| #701 | mnemosyne delete <memory_id> |
| #702 | mnemosyne stats |
| #703 | mnemosyne sleep |
| #704 | mnemosyne export backup.json |
| #705 | mnemosyne import backup.json |
| #706 | mnemosyne import-hindsight export.json [bank] # Import Hindsight JSON |
| #707 | mnemosyne import-hindsight http://localhost:8888 # Import from live API |
| #708 | |
| #709 | # Hermes CLI routes through the same HindsightImporter, preserving timestamps |
| #710 | hermes mnemosyne import --from hindsight --file export.json --bank hermes |
| #711 | hermes mnemosyne import --from hindsight --input export.json --bank hermes |
| #712 | hermes mnemosyne import --from hindsight --base-url http://localhost:8888 --bank hermes |
| #713 | mnemosyne bank list |
| #714 | mnemosyne bank create work |
| #715 | mnemosyne bank delete work |
| #716 | mnemosyne mcp |
| #717 | mnemosyne diagnose |
| #718 | ``` |
| #719 | |
| #720 | --- |
| #721 | |
| #722 | ## Environment Variables |
| #723 | |
| #724 | | Variable | Default | Description | |
| #725 | |---|---|---| |
| #726 | | `MNEMOSYNE_DATA_DIR` | `~/.hermes/mnemosyne/data/` | Root data directory | |
| #727 | | `MNEMOSYNE_VEC_TYPE` | `int8` | Vector storage type: `bit` (48 bytes), `int8` (384 bytes), `float32` (1536 bytes) | |
| #728 | | `MNEMOSYNE_SESSION_ID` | Auto UUID | Default session identifier | |
| #729 | | `MNEMOSYNE_TEMPORAL_HALFLIFE_HOURS` | `24` | Default temporal decay halflife | |
| #730 | | `FASTEMBED_CACHE_PATH` | `~/.hermes/cache/fastembed` | FastEmbed model cache directory | |
| #731 | |
| #732 | --- |
| #733 | |
| #734 | *API reference generated from source code. Every method and parameter verified against actual implementation.* |
| #735 |