| name | lite-sqlite |
| description | Fast lightweight local SQLite database for OpenClaw agents with minimal RAM and storage usage. Use when creating or managing SQLite databases for storing agent data efficiently. Ideal for local data persistence quick agent data storage low-memory databases small-scale applications and agent memo and caching storage. |
Lite SQLite - Lightweight Local Database
Ultra-lightweight SQLite database management optimized for OpenClaw agents with minimal RAM (~2-5MB) and storage overhead.
Why SQLite?
✅ Zero setup - No server, no configuration, file-based
✅ Minimal RAM - 2-5MB typical usage
✅ Fast - Millions of queries/second
✅ Portable - Single .db file
✅ Reliable - ACID compliant, crash-proof
✅ Cross-platform - Works everywhere Python works
Core Features
- In-memory mode for temporary data (even faster!)
- WAL mode for concurrent access
- Connection pooling
- Automatic schema migration
- Built-in backup/restore
- Query optimization hints
Quick Start
Basic Database Operations
from sqlite_connector import SQLiteDB
db = SQLiteDB("agent_data.db")
db.create_table("memos", {
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
"title": "TEXT NOT NULL",
"content": "TEXT",
"created_at": "TEXT DEFAULT CURRENT_TIMESTAMP",
"tags": "TEXT"
})
db.insert("memos", [title="First memo", content="Hello world", tags="test"])
results = db.query("SELECT * FROM memos WHERE tags = ?", ("test",))
db.update("memos", "id = ?", [content="Updated content"], (1,))
db.delete("memos", "id = ?", (1,))
db.close()
In-Memory Database (Fastest)
db = SQLiteDB(":memory:")
db.create_table("temp", {...})
Performance Optimization
Essential Settings
import sqlite3
conn = sqlite3.connect("agent_data.db")
conn.execute("PRAGMA journal_mode=WAL")
conn.execute("PRAGMA synchronous=NORMAL")
conn.execute("PRAGMA cache_size=-64000")
conn.execute("PRAGMA page_size=4096")
conn.execute("PRAGMA temp_store=MEMORY")
Query Optimization
db.create_index("memos", "tags")
db.create_index("memos", "created_at")
db.query("SELECT * FROM memos WHERE id = ?", (id,))
db.batch_insert("memos", rows_data)
Predefined Schemas
Agent Memo Schema (Memory Store)
db.create_table("agent_memos", {
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
"agent_id": "TEXT NOT NULL",
"key": "TEXT NOT NULL",
"value": "TEXT",
"priority": "INTEGER DEFAULT 0",
"created_at": "TEXT DEFAULT CURRENT_TIMESTAMP",
"expires_at": "TEXT"
})
db.create_index("agent_memos", "agent_id")
db.create_index("agent_memos", "key")
db.create_index("agent_memos", "expires_at")
Session Log Schema
db.create_table("session_logs", {
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
"session_id": "TEXT NOT NULL",
"agent": "TEXT NOT NULL",
"message": "TEXT",
"metadata": "TEXT",
"created_at": "TEXT DEFAULT CURRENT_TIMESTAMP"
})
db.create_index("session_logs", "session_id")
db.create_index("session_logs", "created_at")
Cache Schema (TTL-based)
db.create_table("cache", {
"id": "INTEGER PRIMARY KEY AUTOINCREMENT",
"key": "TEXT UNIQUE NOT NULL",
"value": "BLOB",
"created_at": "TEXT DEFAULT CURRENT_TIMESTAMP",
"expires_at": "TEXT NOT NULL"
})
db.query("DELETE FROM cache WHERE expires_at < ?", (datetime.now().isoformat(),))
db.create_index("cache", "key")
db.create_index("cache", "expires_at")
Advanced Features
Connection Pooling
from sqlite_connector import ConnectionPool
pool = ConnectionPool("agent_data.db", max_connections=5)
conn = pool.get_connection()
pool.release_connection(conn)
Automatic Backup
db.backup("agent_data_backup.db")
db.auto_backup("backups/", "daily")
Schema Migration
db.add_column("memos", "updated_at", "TEXT DEFAULT CURRENT_TIMESTAMP")
db.migrate("memos", {
"old_column": "new_column"
})
Performance Benchmarks
Typical Performance
| Operation | Rows | Time (In-Memory) | Time (Disk) |
|---|
| Insert | 10,000 | 0.05s | 0.3s |
| Select (indexed) | 10,000 | 0.001s | 0.01s |
| Select (full scan) | 10,000 | 0.05s | 0.5s |
| Update | 1,000 | 0.01s | 0.1s |
| Delete | 1,000 | 0.01s | 0.1s |
Memory Usage
- Base Memory: 2-5MB
- With 100K rows: ~10-15MB
- With 1M rows: ~50-100MB
- In-memory mode: Same as data size + overhead
Best Practices for OpenClaw Agents
1. Choose the Right Mode
temp_db = SQLiteDB(":memory:")
persist_db = SQLiteDB("agent_storage.db")
2. Use Proper Indexes
db.create_index("table", "column_name")
db.create_index("table", "col1, col2")
3. Batch Operations
for row in rows:
db.insert("table", row)
db.batch_insert("table", rows)
4. Use TTL for Expiring Data
db.cleanup_expired("cache", "expires_at")
db.cleanup_old("logs", "created_at", days=7)
5. Compact Database Periodically
db.vacuum()
DuckDB Alternative (Analytics)
For analytical queries (aggregations, joins on large datasets), consider DuckDB:
import duckdb
conn = duckdb.connect(":memory:")
conn.execute("""
SELECT COUNT(*) as rows,
AVG(value) as avg_value
FROM large_table
""").fetchall()
When to use DuckDB:
- Analytics on large datasets (>100M rows)
- Complex aggregations and joins
- Columnar data operations
- Statistical analysis
When to use SQLite:
- Transactional operations
- Small to medium datasets (<100M rows)
- Point queries and updates
- General-purpose storage
Common Patterns
1. Memo Storage
def save_memo(db, agent_id, key, value, ttl_hours=24):
expires_at = (datetime.now() + timedelta(hours=ttl_hours)).isoformat()
db.insert("agent_memos", {
"agent_id": agent_id,
"key": key,
"value": json.dumps(value),
"expires_at": expires_at
})
2. Session Persistence
def save_session(db, session_id, agent, message, metadata=None):
db.insert("session_logs", {
"session_id": session_id,
"agent": agent,
"message": message,
"metadata": json.dumps(metadata) if metadata else None
})
3. Caching Layer
def cache_get(db, key):
if expired_key := db.query_one(
"SELECT value FROM cache WHERE key = ? AND expires_at > ?",
(key, datetime.now().isoformat())
):
return json.loads(expired_key)
return None
def cache_set(db, key, value, ttl_seconds=3600):
expires_at = (datetime.now() + timedelta(seconds=ttl_seconds)).isoformat()
db.insert_or_replace("cache", {
"key": key,
"value": json.dumps(value),
"expires_at": expires_at
})
Error Handling
try:
db.insert("metrics", {...})
except sqlite3.IntegrityError:
pass
except sqlite3.OperationalError:
pass
Size Optimization Tips
Reduce Storage
-
Use appropriate data types:
- INTEGER instead of TEXT for numbers
- REAL instead of TEXT for floats
- Use CHECK constraints for validation
-
Normalize data:
- Store JSON as TEXT
- Use TEXT for variable-length strings
- Avoid storing redundant data
-
Vacuum regularly:
db.vacuum()
-
Use WAL instead of journal:
conn.execute("PRAGMA journal_mode=WAL")
Migration from Other Stores
From JSON Files
import json
with open("data.json") as f:
data = json.load(f)
db.create_table("json_data", {key: "TEXT" for key in data[0].keys()})
db.batch_insert("json_data", data)
From CSV Files
import pandas as pd
df = pd.read_csv("data.csv")
df.to_sql("csv_data", conn, if_exists="replace", index=False)
Troubleshooting
Database Locked Error
conn.execute("PRAGMA journal_mode=WAL")
pool = ConnectionPool("db.db", timeout=5.0)
Slow Queries
plan = conn.execute("EXPLAIN QUERY PLAN SELECT * FROM ...").fetchall()
db.create_index("table", "column")
conn.execute("ANALYZE")
Large Database Size
size_info = conn.execute("PRAGMA page_count, page_size").fetchone()
print(f"Size: {(page_count * page_size) / (1024*1024):.2f} MB")
db.vacuum()
CLI Tool
The bundled sqlite_cli.py provides command-line access:
python scripts/sqlite_cli.py create agent_data.db
python scripts/sqlite_cli.py create-table agent_memos -c id:INTEGER:P -c title:TEXT -c content:TEXT
python scripts/sqlite_cli.py insert agent_memos '{"title": "Test", "content": "Hello"}'
python scripts/sqlite_cli.py query "SELECT * FROM agent_memos"
python scripts/sqlite_cli.py optimize agent_data.db
Resources