Skip to content

Technical Specification

Detailed technical specification for Memorg.

System Architecture

┌─────────────────────────────────────┐
│           Client Interface          │
│   (CLI, library, MCP server)        │
└───────────────┬─────────────────────┘
┌───────────────▼─────────────────────┐
│        MemorgSystem (orchestrator)  │
├─────────────────────────────────────┤
│  ┌─────────────┐   ┌─────────────┐  │
│  │   Context   │   │  Retrieval  │  │
│  │   Manager   │◄──►   System    │  │
│  └─────┬───────┘   └─────┬───────┘  │
│        │                 │          │
│  ┌─────▼───────┐   ┌─────▼───────┐  │
│  │   Window    │   │   Context   │  │
│  │  Optimizer  │   │    Store    │  │
│  └─────────────┘   └─────────────┘  │
│                                     │
│  ┌─────────────┐  ┌───────────────┐ │
│  │ Hierarchical│  │   Generic     │ │
│  │ MemoryStore │◄─┤ MemoryManager │ │
│  └─────────────┘  └───────────────┘ │
└─────────────────────────────────────┘
┌───────────────▼─────────────────────┐
│   Storage backends                  │
│   SQLite (+ FTS5)   USearch index   │
└─────────────────────────────────────┘
┌───────────────▼─────────────────────┐
│         OpenAI (embeddings, chat)   │
└─────────────────────────────────────┘

Data Structures

Context Hierarchy

@dataclass
class Session:
    id: str
    created_at: datetime
    updated_at: datetime
    user_id: str
    system_config: Dict[str, Any]
    conversations: List[Conversation]
    metadata: Dict[str, Any]

@dataclass
class Conversation:
    id: str
    created_at: datetime
    updated_at: datetime
    title: str
    summary: str
    topics: List[Topic]
    embedding: List[float]
    metadata: Dict[str, Any]

@dataclass
class Topic:
    id: str
    created_at: datetime
    updated_at: datetime
    title: str
    summary: str
    exchanges: List[Exchange]
    embedding: List[float]
    key_entities: List[Entity]
    metadata: Dict[str, Any]

@dataclass
class Exchange:
    id: str
    created_at: datetime
    updated_at: datetime
    user_message: Message
    system_message: Message
    importance_score: float
    embedding: List[float]
    metadata: Dict[str, Any]

@dataclass
class Message:
    raw_content: str
    parsed_content: ParsedContent
    embedding: List[float]

@dataclass
class ParsedContent:
    entities: List[Entity]
    intents: List[str]
    sentiment: Dict[str, float]

@dataclass
class Entity:
    name: str
    type: EntityType
    salience: float
    metadata: Dict[str, Any]

Search Types

class SearchScope(Enum):
    SESSION = "session"
    CONVERSATION = "conversation"
    TOPIC = "topic"
    ALL = "all"

class MatchType(Enum):
    KEYWORD = "keyword"
    SEMANTIC = "semantic"
    TEMPORAL = "temporal"
    HYBRID = "hybrid"
    IMPORTANCE = "importance"

@dataclass
class SearchResult:
    entity: Any
    score: float
    match_type: MatchType

Component Specifications

Context Store

StorageAdapter protocol (memorg.storage.storage_adapter):

class StorageAdapter(Protocol):
    async def write(self, collection: str, id: str, data: Dict) -> None: ...
    async def read(self, collection: str, id: str) -> Optional[Dict]: ...
    async def query(self, collection: str, filter: Dict) -> List[Dict]: ...
    async def delete(self, collection: str, id: str) -> bool: ...
    async def get_stats(self) -> Dict[str, int]: ...

SQLiteStorageAdapter is the default implementation. It treats data as JSON, supports $text: {$search: ...} filters via FTS5, and uses aiosqlite for async access.

VectorStore protocol (memorg.vector_store.vector_store):

class VectorStore(Protocol):
    async def add_vector(self, id: str, vector: List[float], metadata: Dict) -> None: ...
    async def search_nearest(self, vector: List[float], limit: int) -> List[Dict]: ...
    async def delete_vector(self, id: str) -> bool: ...
    async def get_stats(self) -> Dict[str, int]: ...

USearchVectorStore defaults to 1536-dimensional f32 vectors with cosine metric, connectivity=16, expansion_add=128, expansion_search=64. The index is persisted to a .usearch file next to the SQLite database, and vector metadata is stored in a vector_metadata table inside the same SQLite file.

Context Manager

Prioritization Strategy:

class PrioritizationStrategy(Protocol):
    def calculate_priority(
        self,
        entity: Exchange,
        context: Dict[str, Any],
    ) -> float: ...

Default: RecencyWeightedStrategy.

Compression Strategy:

class CompressionStrategy(Protocol):
    async def compress(
        self,
        content: str,
        context: Dict[str, Any],
    ) -> CompressedEntity: ...

Default: ExtractiveSummarization(openai_client).

Working memory: WorkingMemory(capacity=4096) in MemorgSystem.

Retrieval System

Query Processor:

class QueryProcessor(Protocol):
    async def process_query(
        self,
        query: str,
        context: Dict[str, Any],
    ) -> ProcessedQuery: ...

Default: SimpleQueryProcessor(openai_client). Produces a ProcessedQuery with at least a semantic_embedding field consumed by MemorgSystem.search_context.

Relevance Scorer:

class RelevanceScorer(Protocol):
    def score(
        self,
        item: Dict[str, Any],
        query: ProcessedQuery,
    ) -> float: ...

Default: MultiFactorScorer.

Window Optimizer

Summarization Strategy:

class SummarizationStrategy(Protocol):
    async def summarize(
        self,
        content: str,
        entities: List[Entity],
        max_tokens: int,
    ) -> SummarizedContent: ...

Default: ProgressiveSummarization(openai_client).

Token Optimizer: TokenOptimizer(openai_client=openai_client), using tiktoken with the cl100k_base encoding.

Storage Schema

SQLite Tables (chat hierarchy)

For each of sessions, conversations, topics, exchanges:

CREATE TABLE <collection> (
    id          TEXT PRIMARY KEY,
    data        TEXT,                               -- JSON
    created_at  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE VIRTUAL TABLE <collection>_fts USING fts5(
    id,
    content,
    data
);

AFTER INSERT/UPDATE/DELETE triggers keep the FTS5 mirror in sync. The mirror's content column is json_extract(data, '$.content'), which is what $text: {$search: ...} filters search against.

SQLite Tables (vectors)

CREATE TABLE vector_metadata (
    id           INTEGER PRIMARY KEY AUTOINCREMENT,
    string_id    TEXT UNIQUE,
    vector_data  BLOB,
    metadata     TEXT,
    text_content TEXT,
    is_deleted   BOOLEAN DEFAULT FALSE,
    created_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_vector_metadata_string_id ON vector_metadata(string_id);

The USearch index file (<basename>.usearch) lives next to the database.

USearch Index Parameters

Parameter Value
ndim 1536
metric cos
dtype f32
connectivity 16
expansion_add 128
expansion_search 64

Implementation Notes

Embedding Generation

Embeddings are generated using OpenAI's text-embedding-ada-002 model (1536 dimensions). The OPENAI_API_KEY environment variable is expected to be set on the calling AsyncOpenAI client.

Token Counting

TokenOptimizer uses tiktoken with the cl100k_base encoding. The CLI's coarse total_tokens estimate in get_memory_usage is computed as len(content) // 4 summed across all collections, deliberately approximate and intended only as a quick gauge.

Async Operations

All I/O is asynchronous (asyncio, aiosqlite, openai.AsyncOpenAI). USearch index operations are synchronous, but they are CPU-bound and called inline from async code.

MCP Server

memorg.mcp.server.MemorgMCP wraps a single MemorgSystem instance and registers six FastMCP tools. The server constructs its components in initialize_system() lazily on first request and reuses them for the lifetime of the process.

Concurrency

There is one MemorgSystem per process and one SQLite database file. Concurrent writes to that file go through SQLite's standard locking. The vector index is held in memory and persisted via index.save(self.index_path).