# ๐Ÿง  SimpleMem-Cross ### Persistent Cross-Conversation Memory for LLM Agents

Your agents remember everything. Across every conversation.
Context, decisions, and learnings persist automatically โ€” no manual re-injection needed.


License Tests Python Async
FastAPI MCP Tools Storage


[![Performance](https://img.shields.io/badge/๐Ÿ†_LoCoMo_Benchmark-64%25_faster_than_Claude--Mem-FFD700?style=for-the-badge&labelColor=FFD700&color=FF6B6B)](../)
[Features](#-key-features) โ€ข [Quick Start](#-quick-start) โ€ข [API Reference](#-api-reference) โ€ข [Architecture](#-architecture) โ€ข [Configuration](#%EF%B8%8F-configuration)
--- ## ๐Ÿ† Performance
| System | LoCoMo Score | vs SimpleMem | |:-------|:------------:|:------------:| | **SimpleMem** | **48** | โ€” | | Claude-Mem | 29.3 | **+64%** |
> **SimpleMem-Cross** extends [SimpleMem](https://github.com/aiming-lab/SimpleMem) with persistent cross-conversation memory. The original SimpleMem code is preserved **byte-identical** โ€” all new functionality resides in this `cross/` package using composition, not modification. --- ## โœจ Key Features
### ๐Ÿ”„ Session Lifecycle Full session management with **start โ†’ record โ†’ stop โ†’ end** lifecycle. Every event is tracked, timestamped, and persisted. ### ๐ŸŽฏ Automatic Context Injection Token-budgeted context from previous sessions is **injected automatically** at session start. No manual prompt engineering. ### ๐Ÿ“ Smart Event Collection Record messages, tool uses, and file changes with **3-tier automatic redaction** for secrets and sensitive data. ### ๐Ÿ” Observation Extraction Heuristic extraction of **decisions, discoveries, and learnings** from conversations. Your agent learns from experience. ### ๐Ÿ”— Provenance Tracking Every memory entry **links back to source evidence**. Know exactly where each piece of context originated. ### ๐Ÿงน Memory Consolidation Automatic **decay, merge, and prune** of old memories. Quality over quantity, maintained automatically.
--- ## ๐Ÿš€ Quick Start ```python import asyncio from cross.orchestrator import create_orchestrator async def main(): # ๐Ÿ”ง Create the orchestrator for your project orch = create_orchestrator(project="my-project") # ๐Ÿš€ Start a new session โ€” context from previous sessions is injected automatically result = await orch.start_session( content_session_id="session-001", user_prompt="Continue building the REST API authentication", ) memory_session_id = result["memory_session_id"] print(result["context"]) # ๐Ÿ“š Relevant context from previous sessions # ๐Ÿ“ Record events during the session await orch.record_message(memory_session_id, "User asked about JWT auth") await orch.record_tool_use( memory_session_id, tool_name="read_file", tool_input="auth/jwt.py", tool_output="class JWTHandler: ...", ) await orch.record_message(memory_session_id, "Implemented token refresh logic", role="assistant") # โœ… Finalize โ€” extracts observations, generates summary, stores memory entries report = await orch.stop_session(memory_session_id) print(f"Stored {report.entries_stored} memory entries, {report.observations_count} observations") # ๐Ÿงน Cleanup await orch.end_session(memory_session_id) orch.close() asyncio.run(main()) ``` --- ## ๐Ÿ“ฆ Installation SimpleMem-Cross uses the same dependencies as SimpleMem, plus standard library `sqlite3`: ```bash pip install -r requirements.txt ``` > **Note**: No additional packages required. LanceDB and Pydantic are already in the SimpleMem dependency tree. --- ## ๐Ÿ—๏ธ Architecture ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Agent Frameworks (Claude Code / Cursor / custom) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Hook/Lifecycle โ”‚ โ”‚ HTTP/MCP API โ”‚ โ”‚ Adapter โ”‚ โ”‚ (FastAPI) โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ SessionStart โ”‚ โ”‚ POST /sessions/start โ”‚ โ”‚ UserMessage โ”‚ โ”‚ POST /sessions/{id}/* โ”‚ โ”‚ ToolUse โ”‚ โ”‚ POST /search โ”‚ โ”‚ Stop / End โ”‚ โ”‚ GET /stats โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ CrossMemOrchestrator โ”‚ โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• โ”‚ โ”‚ โ€ข Facade for all memory operations โ”‚ โ”‚ โ€ข Multi-tenant isolation โ”‚ โ”‚ โ€ข Async-first design โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ–ผ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Session โ”‚ โ”‚ Context โ”‚ โ”‚ Consolidation โ”‚ โ”‚ Manager โ”‚ โ”‚ Injector โ”‚ โ”‚ Worker โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ SQLite DB โ”‚ โ”‚ Token- โ”‚ โ”‚ Decay / Merge โ”‚ โ”‚ โ€ข sessions โ”‚ โ”‚ budgeted โ”‚ โ”‚ Prune old โ”‚ โ”‚ โ€ข events โ”‚ โ”‚ context โ”‚ โ”‚ entries โ”‚ โ”‚ โ€ข summaries โ”‚ โ”‚ bundle โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Cross-Session Vector Store โ”‚ โ”‚ (LanceDB) โ”‚ โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• โ”‚ โ”‚ โ€ข Semantic search (1024-d vectors) โ”‚ โ”‚ โ€ข Keyword matching (BM25-style) โ”‚ โ”‚ โ€ข Structured metadata filtering โ”‚ โ”‚ โ€ข Provenance fields for tracing โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Reuses SimpleMem 3-Stage Pipeline โ”‚ โ”‚ (Composition, not modification) โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ MemoryBuilder โ†’ HybridRetriever โ†’ โ”‚ โ”‚ AnswerGenerator โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### ๐ŸŽฏ Design Principles | Principle | Implementation | |-----------|----------------| | **Composition over modification** | Original SimpleMem is wrapped, never edited | | **SQLite for session timeline** | Sessions, events, observations, summaries | | **LanceDB for vectors** | Cross-session memory entries with provenance | | **Hook-based lifecycle** | `SessionStart โ†’ UserMessage/ToolUse โ†’ Stop โ†’ End` | | **Progressive disclosure** | Token-budgeted context injection at session start | | **Provenance tracking** | Every vector links back to its source evidence | --- ## ๐Ÿ“š Module Reference | Module | Lines | Description | |:-------|------:|:------------| | `types.py` | 227 | ๐Ÿ“‹ Pydantic models โ€” enums, records, ContextBundle, FinalizationReport | | `storage_sqlite.py` | 805 | ๐Ÿ—„๏ธ SQLite backend โ€” 6 tables (sessions, events, observations, summaries) | | `storage_lancedb.py` | 542 | ๐Ÿ” LanceDB vector store โ€” semantic/keyword/structured search | | `hooks.py` | 401 | ๐Ÿช Abstract `SessionHooks` with 5 async lifecycle methods | | `collectors.py` | 413 | ๐Ÿ“ `RedactionFilter` (3-tier regex), thread-safe `EventCollector` | | `session_manager.py` | 755 | ๐Ÿ”„ Full lifecycle orchestration โ€” start/record/finalize/end | | `context_injector.py` | 385 | ๐Ÿ’‰ Token-budgeted `ContextBundle` builder and renderer | | `orchestrator.py` | 530 | ๐ŸŽญ Top-level facade `CrossMemOrchestrator` and factory | | `api_http.py` | 556 | ๐ŸŒ FastAPI router โ€” 8 REST endpoints with Pydantic models | | `api_mcp.py` | 620 | ๐Ÿ”Œ `MCPToolRegistry` โ€” 8 MCP tool definitions with JSON Schema | | `consolidation.py` | 390 | ๐Ÿงน `ConsolidationWorker` โ€” decay/merge/prune pipeline | --- ## ๐Ÿ“– API Reference ### CrossMemOrchestrator
MethodParametersReturnsDescription
start_session content_session_id, user_prompt? dict Start session with context injection
record_message memory_session_id, content, role? None Record a chat message event
record_tool_use memory_session_id, tool_name, tool_input, tool_output None Record a tool invocation
stop_session memory_session_id FinalizationReport Finalize: extract observations, generate summary
end_session memory_session_id None Mark session completed, cleanup
search query, top_k? list[CrossMemoryEntry] Semantic search across all sessions
get_context_for_prompt user_prompt? str Build and render context for system prompt
get_stats โ€” dict Storage statistics
close โ€” None Close SQLite connection
--- ## ๐ŸŒ HTTP API
REST Endpoints | Method | Path | Description | |:-------|:-----|:------------| | `POST` | `/cross/sessions/start` | ๐Ÿš€ Start a new cross-session | | `POST` | `/cross/sessions/{id}/message` | ๐Ÿ’ฌ Record a message event | | `POST` | `/cross/sessions/{id}/tool-use` | ๐Ÿ”ง Record a tool-use event | | `POST` | `/cross/sessions/{id}/stop` | โœ… Finalize session memory | | `POST` | `/cross/sessions/{id}/end` | ๐Ÿ End and cleanup session | | `POST` | `/cross/search` | ๐Ÿ” Search cross-session memories | | `GET` | `/cross/stats` | ๐Ÿ“Š Get memory system statistics | | `GET` | `/cross/health` | ๐Ÿ’š Health check with uptime |
### Running the HTTP Server ```python from cross.api_http import create_app app = create_app(project="my-project") # Run with uvicorn # uvicorn cross.api_http:app --host 0.0.0.0 --port 8000 ``` Or mount on an existing FastAPI app: ```python from cross.api_http import create_cross_router from cross.orchestrator import create_orchestrator orch = create_orchestrator(project="my-project") router = create_cross_router(orch) app.include_router(router, prefix="/cross") ``` --- ## ๐Ÿ”Œ MCP Integration
Available MCP Tools | Tool Name | Description | |:----------|:------------| | `cross_session_start` | ๐Ÿš€ Start a new cross-session memory session | | `cross_session_message` | ๐Ÿ’ฌ Record a user/assistant message | | `cross_session_tool_use` | ๐Ÿ”ง Record a tool invocation | | `cross_session_stop` | โœ… Finalize and persist session memory | | `cross_session_end` | ๐Ÿ End session and cleanup | | `cross_session_search` | ๐Ÿ” Search across all session memories | | `cross_session_context` | ๐Ÿ“š Get context bundle for system prompt | | `cross_session_stats` | ๐Ÿ“Š Get memory system statistics |
### MCP Setup ```python from cross.api_mcp import create_mcp_tools from cross.orchestrator import create_orchestrator orch = create_orchestrator(project="my-project") tools = create_mcp_tools(orch) # Get tool definitions for MCP server registration definitions = tools.get_tool_definitions() # Dispatch a tool call result = await tools.call_tool("cross_session_start", { "tenant_id": "default", "content_session_id": "ses-1", "project": "my-project", "user_prompt": "Help me debug the auth module", }) ``` --- ## โš™๏ธ Configuration ### ๐Ÿ“ Default Paths | Setting | Default | Description | |:--------|:--------|:------------| | SQLite DB | `~/.simplemem-cross/cross_memory.db` | Session metadata, events, observations | | LanceDB | `~/.simplemem-cross/lancedb_cross` | Vector storage for memory entries | | Max context tokens | `2000` | Token budget for context injection | ### ๐Ÿ”ง Custom Configuration ```python orch = create_orchestrator( project="my-project", tenant_id="team-alpha", db_path="/custom/path/memory.db", lancedb_path="/custom/path/lancedb", max_context_tokens=3000, ) ``` ### ๐Ÿ‘ฅ Multi-Tenant Support Pass `tenant_id` to isolate memory across tenants. Each tenant's memories are stored and retrieved independently. --- ## ๐Ÿงน Consolidation The consolidation worker maintains memory quality over time: ```python from cross.consolidation import ConsolidationWorker, ConsolidationPolicy policy = ConsolidationPolicy( max_age_days=90, # โฐ Decay entries older than 90 days decay_factor=0.9, # ๐Ÿ“‰ Multiply importance by 0.9 per period merge_similarity_threshold=0.95, # ๐Ÿ”— Merge near-duplicates min_importance=0.05, # ๐Ÿ—‘๏ธ Prune below this threshold ) worker = ConsolidationWorker(sqlite_storage, vector_store, policy) result = worker.run(tenant_id="default") print(f"๐Ÿ“‰ Decayed: {result.decayed_count}") print(f"๐Ÿ”— Merged: {result.merged_count}") print(f"๐Ÿ—‘๏ธ Pruned: {result.pruned_count}") ``` --- ## ๐Ÿงช Testing ```bash # ๐Ÿงช Run all cross-session tests pytest cross/tests/ -v # ๐Ÿ“‹ Run specific test module pytest cross/tests/test_types.py -v pytest cross/tests/test_storage.py -v pytest cross/tests/test_e2e.py -v ``` > **Note**: Tests use real SQLite (temp databases) and mock LanceDB. No external services, API keys, or GPU required. --- ## ๐Ÿ“ Constraints | Constraint | Reason | |:-----------|:-------| | โœ… **Original SimpleMem is byte-identical** | Published research paper; never modified | | โœ… **All code in English** | No Chinese in code, comments, docstrings, or strings | | โœ… **Python-only** | Matches SimpleMem's tech stack | | โœ… **Composition pattern** | SimpleMem is wrapped via duck typing, never subclassed | ---

**[โฌ† Back to Top](#-simplemem-cross)**
Made with โค๏ธ by the SimpleMem Team