Lillo uses a serverless-first database architecture powered by Vercel Postgres, designed for scalable AI agent interactions and content management.
Schema Structure
Core Tables
1. chat_messages
CREATE TABLE chat_messages ( id SERIAL PRIMARY KEY, message_id BIGINT NOT NULL, chat_id BIGINT NOT NULL, user_id BIGINT NOT NULL, user_first_name VARCHAR(255) NOT NULL, username VARCHAR(255),roleVARCHAR(50) NOT NULL, content TEXT NOT NULL,timestamp BIGINT NOT NULL, reply_to_message_id BIGINT, agent_id VARCHAR(255) NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, UNIQUE(chat_id, message_id, agent_id));-- IndexesCREATE INDEX idx_chat_messages_chat_id_timestamp ON chat_messages(chat_id, timestampDESC);CREATE INDEX idx_chat_messages_agent_idON chat_messages(agent_id);
2. posts
CREATE TABLE posts ( id SERIAL PRIMARY KEY,typeVARCHAR(50) NOT NULL, content TEXT NOT NULL,timestamp BIGINT NOT NULL,locationVARCHAR(255), prompt TEXT, image_url TEXT, tweet_id VARCHAR(255), created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP);-- IndexCREATE INDEX idx_posts_timestamp ON posts(timestampDESC);
3. user_data
CREATE TABLE user_data ( id SERIAL PRIMARY KEY, wallet_address VARCHAR(255) UNIQUE, telegram_id BIGINT UNIQUE, username VARCHAR(255), first_name VARCHAR(255), token_balance VARCHAR(255), last_verified BIGINT, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP);-- IndexesCREATE INDEX idx_user_data_telegram_id ON user_data(telegram_id);CREATE INDEX idx_user_data_wallet ON user_data(wallet_address);
4. command_metrics
CREATE TABLE command_metrics ( id SERIAL PRIMARY KEY, command VARCHAR(50) NOT NULL, user_id BIGINT NOT NULL, chat_id BIGINT NOT NULL, duration INTEGER NOT NULL, success BOOLEAN NOT NULL, error TEXT,timestamp BIGINT NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP);-- IndexCREATE INDEX idx_command_metrics_timestamp ON command_metrics(timestampDESC);
5. gerta_poses
CREATE TABLE gerta_poses ( id SERIAL PRIMARY KEY,filenameVARCHAR(255) NOT NULL, last_used TIMESTAMP WITH TIME ZONE, usage_count INTEGER DEFAULT 0, command_type VARCHAR(50), created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, CONSTRAINT unique_filename UNIQUE (filename));-- IndexCREATE INDEX idx_gerta_poses_last_used ON gerta_poses(last_used);
6. illustrations
CREATE TABLE illustrations ( id SERIAL PRIMARY KEY,filenameTEXT UNIQUE NOT NULL, last_used TIMESTAMP, usage_count INTEGER DEFAULT 0, command_type TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);-- IndexCREATE INDEX idx_illustrations_last_usedON illustrations(last_used);
7. agents
CREATE TABLE agents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(),nameVARCHAR(255) NOT NULL,typeVARCHAR(50) NOT NULL,-- Basic Info ticker VARCHAR(50), token_address VARCHAR(255), network VARCHAR(50),-- Encrypted Telegram Config telegram_config TEXT,-- Links website_url VARCHAR(255), twitter_handle VARCHAR(255), telegram_group VARCHAR(255),-- Agent Configuration system_prompt TEXT, capabilities JSONB DEFAULT '{}',-- Metadata created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, is_active BOOLEAN DEFAULT true,-- Constraints CONSTRAINT unique_agent_name UNIQUE (name), CONSTRAINT unique_token_address UNIQUE (token_address));-- IndexCREATE INDEX idx_agents_name ON agents(name);
8. model_preferences
CREATE TABLE model_preferences ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), agent_id UUID NOT NULL REFERENCES agents(id), chat_id BIGINT NOT NULL, model_type VARCHAR(50) NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, CONSTRAINT unique_agent_chat UNIQUE (agent_id, chat_id));-- IndexCREATE INDEX idx_model_preferences_lookupON model_preferences(agent_id, chat_id);
// Store messageasyncfunctionstoreMessage(entry: { messageId:number; chatId:number; userId:number; userFirstName:string; username?:string; role:'user'|'assistant'; content:string; timestamp:number; replyToMessageId?:number; agentId:string;}):Promise<void>// Get chat historyasyncfunctiongetRecentChatHistory( chatId:number, agentId:string, limit:number=20):Promise<ChatMessageData[]>
Agent Operations
// Get active agentasyncfunctiongetActiveAgent():Promise<Agent|null>// Get agent by nameasyncfunctiongetAgentByName(name:string):Promise<Agent|null>// Create agentasyncfunctioncreateAgent(agent:Omit<Agent,'id'|'createdAt'|'updatedAt'>):Promise<Agent>// Update agentasyncfunctionupdateAgent(id:string, updates:Partial<Agent>):Promise<Agent>
Metrics Operations
// Store command metricsasyncfunctionstoreCommandMetrics(metrics:CommandMetrics):Promise<void>// Get recent metricsasyncfunctiongetRecentCommandMetrics( limit:number=100):Promise<CommandMetrics[]>