logo
0
0
WeChat Login
Jiaaqiliu<jqliu@cs.unc.edu>
feat: Cross-session memory extension with 64% improvement over Claude-Mem

🧠 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


FeaturesQuick StartAPI ReferenceArchitectureConfiguration


🏆 Performance

SystemLoCoMo Scorevs SimpleMem
SimpleMem48
Claude-Mem29.3+64%

SimpleMem-Cross extends 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

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:

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

PrincipleImplementation
Composition over modificationOriginal SimpleMem is wrapped, never edited
SQLite for session timelineSessions, events, observations, summaries
LanceDB for vectorsCross-session memory entries with provenance
Hook-based lifecycleSessionStart → UserMessage/ToolUse → Stop → End
Progressive disclosureToken-budgeted context injection at session start
Provenance trackingEvery vector links back to its source evidence

📚 Module Reference

ModuleLinesDescription
types.py227📋 Pydantic models — enums, records, ContextBundle, FinalizationReport
storage_sqlite.py805🗄️ SQLite backend — 6 tables (sessions, events, observations, summaries)
storage_lancedb.py542🔍 LanceDB vector store — semantic/keyword/structured search
hooks.py401🪝 Abstract SessionHooks with 5 async lifecycle methods
collectors.py413📝 RedactionFilter (3-tier regex), thread-safe EventCollector
session_manager.py755🔄 Full lifecycle orchestration — start/record/finalize/end
context_injector.py385💉 Token-budgeted ContextBundle builder and renderer
orchestrator.py530🎭 Top-level facade CrossMemOrchestrator and factory
api_http.py556🌐 FastAPI router — 8 REST endpoints with Pydantic models
api_mcp.py620🔌 MCPToolRegistry — 8 MCP tool definitions with JSON Schema
consolidation.py390🧹 ConsolidationWorker — decay/merge/prune pipeline

📖 API Reference

CrossMemOrchestrator

MethodParametersReturnsDescription
start_sessioncontent_session_id, user_prompt?dictStart session with context injection
record_messagememory_session_id, content, role?NoneRecord a chat message event
record_tool_usememory_session_id, tool_name, tool_input, tool_outputNoneRecord a tool invocation
stop_sessionmemory_session_idFinalizationReportFinalize: extract observations, generate summary
end_sessionmemory_session_idNoneMark session completed, cleanup
searchquery, top_k?list[CrossMemoryEntry]Semantic search across all sessions
get_context_for_promptuser_prompt?strBuild and render context for system prompt
get_statsdictStorage statistics
closeNoneClose SQLite connection

🌐 HTTP API

REST Endpoints
MethodPathDescription
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

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:

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 NameDescription
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

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

SettingDefaultDescription
SQLite DB~/.simplemem-cross/cross_memory.dbSession metadata, events, observations
LanceDB~/.simplemem-cross/lancedb_crossVector storage for memory entries
Max context tokens2000Token budget for context injection

🔧 Custom Configuration

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:

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

# 🧪 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

ConstraintReason
Original SimpleMem is byte-identicalPublished research paper; never modified
All code in EnglishNo Chinese in code, comments, docstrings, or strings
Python-onlyMatches SimpleMem's tech stack
Composition patternSimpleMem is wrapped via duck typing, never subclassed


⬆ Back to Top


Made with ❤️ by the SimpleMem Team