๐ง SimpleMem-Cross
February 10, 2026 ยท View on GitHub
๐ง 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.
Features โข Quick Start โข API Reference โข Architecture โข Configuration
๐ Performance
| System | LoCoMo Score | vs SimpleMem |
|---|---|---|
| SimpleMem | 48 | โ |
| Claude-Mem | 29.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 LifecycleFull session management with start โ record โ stop โ end lifecycle. Every event is tracked, timestamped, and persisted. ๐ฏ Automatic Context InjectionToken-budgeted context from previous sessions is injected automatically at session start. No manual prompt engineering. ๐ Smart Event CollectionRecord messages, tool uses, and file changes with 3-tier automatic redaction for secrets and sensitive data. |
๐ Observation ExtractionHeuristic extraction of decisions, discoveries, and learnings from conversations. Your agent learns from experience. ๐ Provenance TrackingEvery memory entry links back to source evidence. Know exactly where each piece of context originated. ๐งน Memory ConsolidationAutomatic 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
| 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
| Method | Parameters | Returns | Description |
|---|---|---|---|
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
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 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
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
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
| 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 |