Create Omni/Agent/Memory.hs module for cross-agent, multi-user shared memory with vector similarity search.
This is the foundation for a multi-agent system where different agents (Telegram bot, researcher, coder, etc.) share knowledge about users. Example: User tells Telegram bot 'I'm an AI engineer' -> later, researcher agent searching for papers should recall this context.
CREATE TABLE users (
id TEXT PRIMARY KEY, -- UUID
telegram_id INTEGER UNIQUE, -- Primary identifier initially
email TEXT UNIQUE, -- Added later for email interface
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE memories (
id TEXT PRIMARY KEY, -- UUID
user_id TEXT NOT NULL REFERENCES users(id),
content TEXT NOT NULL,
embedding BLOB, -- float32 vector for sqlite-vss
source_agent TEXT NOT NULL, -- 'telegram', 'coder', etc.
source_session TEXT, -- Session UUID
source_context TEXT, -- How this was learned
confidence REAL DEFAULT 0.8,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_accessed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
tags TEXT -- JSON array
);
CREATE VIRTUAL TABLE memories_vss USING vss0(embedding(1536));
CREATE INDEX idx_memories_user ON memories(user_id);
data User = User
{ userId :: UUID
, userTelegramId :: Maybe Int64
, userEmail :: Maybe Text
, userName :: Text
, userCreatedAt :: UTCTime
}
data Memory = Memory
{ memoryId :: UUID
, memoryUserId :: UUID
, memoryContent :: Text
, memoryEmbedding :: Maybe (Vector Float)
, memorySource :: MemorySource
, memoryConfidence :: Double
, memoryCreatedAt :: UTCTime
, memoryLastAccessedAt :: UTCTime
, memoryTags :: [Text]
}
data MemorySource = MemorySource
{ sourceAgent :: Text
, sourceSession :: Maybe UUID
, sourceContext :: Text
}
-- User management
createUser :: Text -> Maybe Int64 -> IO User
getUserByTelegramId :: Int64 -> IO (Maybe User)
getOrCreateUserByTelegramId :: Int64 -> Text -> IO User
-- Memory operations
storeMemory :: UUID -> Text -> MemorySource -> IO Memory
recallMemories :: UUID -> Text -> Int -> IO [Memory] -- semantic search by user
forgetMemory :: UUID -> IO ()
getAllMemoriesForUser :: UUID -> IO [Memory]
-- Embedding (via Ollama)
embedText :: Text -> IO (Vector Float)
Create wrapper for agent loop:
runAgentWithMemory :: User -> AgentConfig -> Text -> IO AgentResult
runAgentWithMemory user config prompt = do
memories <- recallMemories (userId user) prompt 10
let memoryContext = formatMemoriesForPrompt memories
let enhancedPrompt = agentSystemPrompt config <> "\n\n## Known about this user\n" <> memoryContext
runAgent config { agentSystemPrompt = enhancedPrompt } prompt
rememberTool :: UUID -> Tool -- takes user ID, returns Tool that stores memories
recallTool :: UUID -> Tool -- takes user ID, returns Tool that queries memories