Source Code:
src/gaia/database/mixin.pyComponent: DatabaseMixin
Module:
gaia.database.mixin
Import: from gaia.database.mixin import DatabaseMixinOverview
DatabaseMixin is a zero-dependency SQLite mixin for agents that need
persistent, queryable state (user intake records, chat sessions, job queues,
etc.). It wraps Python’s stdlib sqlite3 with a small ergonomic API and an
optional transaction context manager.
Design goals:
- No extra dependencies. Uses only
sqlite3from the standard library. - Dict-oriented API. Every query returns dicts (via
sqlite3.Rowunder the hood) so tools can serialize results without transformation. - LLM-friendly SQL. Explicit parameterised SQL with
:nameplaceholders and a consistent(table, data, where, params)signature for CRUD operations. - Safe concurrency for agents. Single connection with
check_same_thread=False; usetransaction()for atomic writes.
API Reference
All methods are instance methods on any class that mixes inDatabaseMixin.
Connection lifecycle
init_db(path)— open (or re-open) a SQLite connection. Accepts:memory:or a filesystem path; parent directories are auto-created. Enables foreign keys (PRAGMA foreign_keys = ON) and usessqlite3.Rowfor dict-style access.close_db()— close the connection. Safe to call multiple times; safe to call beforeinit_db.db_ready—Trueif a connection is open.
RuntimeError("Database not initialized. Call init_db() first.") if the connection isn’t ready.
Reads
:name placeholders. When one=True, returns either a
single row dict or None; otherwise returns a list of row dicts (possibly
empty).
Writes
insert(table, data)— buildsINSERT INTO table (...) VALUES (...)from the data dict and returns the new row’slastrowid.update(table, data, where, params)— the implementation prefixes the data keys with__set_internally so they can’t collide with theparamsused in theWHEREclause. Returns the affected row count.delete(table, where, params)— returns the deleted row count.
transaction()
block.
Transactions
execute() (raw DDL below) cannot be called inside a transaction — it will
raise RuntimeError.
Raw SQL / schema
execute(sql)— runs arbitrary SQL viaexecutescript(). Use forCREATE TABLE/CREATE INDEXbootstrap. Auto-commits any pending work.table_exists(name)— returnsTrueif a table of that name exists.
Example agent
Caveats
- SQLite only — there is no PostgreSQL/MySQL support. If you need a different backend, you’ll need a different mixin.
- Single connection per agent instance; the mixin assumes single-process
ownership. For multi-process scenarios, either use a shared DB file with
WAL-mode via
execute("PRAGMA journal_mode=WAL")or route writes through a single coordinator agent. - There is no ORM layer. You work directly with SQL and dict results, which is intentional — it keeps the surface small and LLM-friendly.
Related
- EMR Agent uses this mixin as its persistence layer.
- FileWatcher is commonly paired with
DatabaseMixinto record ingestion events.