Quickstart
Install HybridDB, create your first table, and run keyword, semantic, and hybrid search — plus versioned agent memory — in about 60 seconds.
Install
- Install the package
pip install hybriddbHybridDB uses ChromaDB’s bundled local MiniLM embedding by default — no API key required. Optional extras:
pip install "hybriddb[analytics]" # DuckDB columnar analytics - Create a table and insert rows
Column types drive the search indexes automatically:
TEXTgets FTS5 keyword search,LONGTEXTgets both keyword and vector search.from hybriddb import HybridDB, LONGTEXT, TEXT db = HybridDB("./my_data") db.create_table("docs", {"title": TEXT, "body": LONGTEXT}) db.insert("docs", {"title": "Getting Started", "body": "A guide to using HybridDB..."}) db.insert("docs", {"title": "API Reference", "body": "Full API documentation..."}) - Run your first hybrid search
# Search every text column at once db.search_all("docs", "getting started") # Search one column — hybrid (RRF fusion of keyword + semantic) is the default db.search("docs", "body", "how do I begin", mode="hybrid") # Structured query with parameters db.query("docs", where="title LIKE ?", params=("%start%",))
Try the three search modes
from hybriddb import SearchMode
# Keyword only — fast, exact, great for names and titles
db.search("contacts", "name", "Alice", mode="keyword")
# Semantic only — finds "9am standup" when searching for "morning meetings"
db.search("memories", "content", "team rituals", mode=SearchMode.SEMANTIC)
# Hybrid — best of both, RRF fusion, the default
db.search("docs", "body", "getting started guide", mode=SearchMode.HYBRID)
# Search across ALL text columns at once
db.search_all("contacts", "engineering manager")
Measured on real BEIR benchmarks, hybrid fusion beats both single modes on every metric — +11% nDCG over keyword on NFCorpus, +5% on SciFact. See Benchmarks.
Next: agent memory with versioned tables
Opt any table into versioned history with a tamper-evident hash chain — built for agent memory, session logs, and audit trails:
db = HybridDB("./agent_memory")
db.create_table("memories", {"id": TEXT, "content": LONGTEXT}, versioned=True)
db.author = "assistant" # recorded on every event
db.upsert("memories", {"id": "m1", "content": "User prefers morning meetings"})
db.upsert("memories", {"id": "m1", "content": "User prefers afternoon standups"})
db.history("memories", key="m1") # every version, with hashes
db.diff("docs", from_seq=1, to_seq=2) # what changed between two points
db.as_of("memories", seq=3) # what the agent knew at seq 3
cp = db.checkpoint("memories", "before-cleanup")
db.rollback("memories", checkpoint="before-cleanup") # rewind — nothing erased
db.verify_chain("memories") # -> {"valid": True, ...}
Rollback re-applies restored state as new versions, so the audit trail stays complete. verify_chain() detects any direct tampering with the history store.
Async (for FastAPI and friends)
All core operations have async wrappers that run blocking SQLite/ChromaDB work in a worker thread:
await db.acreate_table("messages", {"content": LONGTEXT})
await db.ainsert("messages", {"content": "async-safe memory"})
results = await db.asearch("messages", "content", "memory")
Continue to Core concepts for column types, versioned tables, and the journal — or jump to the API reference.
Source of truth for this page: HybridDB · open-assistants-lab/HybridDB