topodb
Embedded, temporal, graph-native memory for AI agents — Python bindings for the TopoDB engine.
TopoDB is a single-file property graph (redb-backed) with scoped recall, text +
vector search, and bi-temporal edges. These bindings embed the engine in your
process: no server, no daemon, one .redb file on disk.
Install
pip install topodb
Prebuilt wheels (abi3, Python ≥ 3.9):
| Platform | Architecture |
|---|---|
| Linux (manylinux) | x86_64 |
| Linux (manylinux) | aarch64 |
| macOS | universal2 (x86_64 + arm64) |
| Windows | x64 |
Other platforms build from the sdist (requires a Rust toolchain via maturin).
Quickstart
import topodb
from topodb import ops
# Indexing is opt-in per (label, prop): declare equality lookups and what
# full-text search should cover. Plain TopoDB.open() indexes nothing (fine
# for pure graph workloads); TopoDB.open_stored() reopens a file with the
# spec it was created with.
spec = {
"equality": [{"label": "Entity", "prop": "name"}],
"text": [{"label": "Memory", "prop": "content"}],
}
with topodb.TopoDB.open_with("memory.redb", spec) as db:
r = db.submit([
ops.create_entity("ada"),
ops.create_memory("ada wrote the first program"),
ops.link("#1", "#0", "ABOUT"), # "#n" back-references the n-th op's new id
])
ada_id, memory_id, edge_id = r["ids"]
scopes = ["shared"] # reads always name the scopes they may see
hits = db.search_text(scopes, "first program", 5)
print(hits[0]["node"]["props"]["content"], hits[0]["score"])
sg = db.traverse(scopes, seeds=[memory_id], max_hops=2)
print([n["id"] for n in sg["nodes"]], len(sg["edges"]))
TopoDB.open(path) creates or opens a database with the default index spec;
TopoDB.open_with(path, spec) sets an explicit index spec (equality + text
indexes) on create; TopoDB.open_stored(path) reopens with whatever spec the
file already carries. The handle is a context manager — leaving the with
block closes it, and any later call raises ClosedError.
Writes: ops builders + submit
All mutation goes through db.submit(batch), one atomic batch of command
dicts. The topodb.ops module builds those dicts (the same wire shapes the
CLI and MCP server speak):
ops.create_entity(name, scope=None)
ops.create_memory(content, scope=None)
ops.create_node(label, props=None, scope=None)
ops.link(from_, to, type, props=None, scope=None, valid_from=None)
ops.set_node_props(id, props) # a None value inside props deletes that prop
ops.remove_node(id)
ops.close_edge(id, valid_to=None)
ops.set_embedding(id, model, vector)
Within a batch, "#0", "#1", … refer to the ids created by earlier ops in
the same batch. submit returns {"first_seq", "last_seq", "ids"} — one ULID
string per op. Pass now_ms= to pin the write timestamp (defaults to the wall
clock) and default_scope= to stamp the whole batch (see below).
The multi-scope read model
Every read takes a list of scopes as its first argument and only sees data
stamped with one of them. Every write is stamped with exactly one scope —
per-op via the builder's scope= parameter, or batch-wide via
db.submit(batch, default_scope=...). A scope is "shared" or a ULID string.
This asymmetry is the point: an agent can read across ["shared", project_scope]
while writing only into project_scope.
db.node(scopes, id) # dict or None
db.nodes_by_label(scopes, label)
db.nodes_by_label_newest(scopes, label, k)
db.nodes_by_prop(scopes, label, prop, value) # equality-indexed props only
db.nodes_by_prop_normalized(scopes, label, prop, value)
db.nodes_by_float_range(scopes, prop, lo, hi)
db.edges_from(scopes, id, type=None)
db.traverse(scopes, seeds=[...], max_hops=n,
edge_types=None, direction="both", as_of=None)
db.search_text(scopes, query, k)
db.search_vector(scopes, model, vector, k)
db.recall(scopes, query, k, vector=(model, vec), labels=None, now_ms=None)
db.suggest_links(scopes, id, k, model=None)
Nodes come back as plain dicts: {"id", "scope", "label", "props"}. Search
hits are {"node", "score"}.
Bi-temporal edges
Edges carry two independent time axes, both in the wire dict:
- World time —
valid_from/valid_to: when the fact was true in the world. Settable on write (ops.link(..., valid_from=...),ops.close_edge(id, valid_to=...));valid_toisNonewhile the edge is open.traverse(..., as_of=t)answers "what was true at t". - Belief time —
recorded_at/superseded_at: when the database learned and stopped believing the fact. Stamped by the engine, never settable;superseded_atisNonewhile the edge is current.
The two differ whenever a fact is recorded late or corrected after the fact. Full edge shape:
{"id", "scope", "type", "from", "to", "props",
"valid_from", "valid_to", "recorded_at", "superseded_at"}
Errors
All errors derive from topodb.TopoDBError, so one except catches
everything; subclasses carry the detail:
| Exception | Meaning | Extra attributes |
|---|---|---|
StorageError |
I/O or storage-layer failure | |
EncodingError |
corrupt or undecodable stored data | |
RejectedError |
invalid batch, arguments, or unindexed-prop query | |
CompactedError |
requested ops feed range was compacted away | oldest — first seq still available |
BusyError |
database file held by another process; retryable | |
ClosedError |
handle used after close() |
|
UnsupportedFormatError |
file format version mismatch | found, supported |
Change feed
db.subscribe(capacity) returns a Subscription that yields committed ops as
dicts. sub.next(timeout=...) returns the next event or None on timeout
(the GIL is released while waiting), and the object is also a plain iterator
that ends when the database closes. db.ops_since(seq) / db.current_seq() /
db.compact_ops(seq) cover catch-up and log compaction.
Embedded vs MCP
These bindings are the embedded client: in-process, zero-IPC, one Python
process owning the file. If you want TopoDB behind an agent framework instead
— shared across sessions, spoken over the Model Context Protocol — use the
topodb-mcp server. Both speak the same wire shapes and the same batch DSL;
see docs/agent-clients.md
for the trade-offs.
Versioning
0.1.0 is the first published release of these bindings; it wraps the frozen
0.1 engine API. See the repository CHANGELOG.md for history from here on.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file topodb-0.1.0.tar.gz.
File metadata
- Download URL: topodb-0.1.0.tar.gz
- Upload date:
- Size: 2.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d034bfd1c6d73b06c34678299dd31e0a64ba3d66c69c2fdb66540898a5a12f62
|
|
| MD5 |
f289d17c33a113dbf890d587d58963a5
|
|
| BLAKE2b-256 |
ee03c3cc10d0658a0931fc72bfafab6643d48b7a4ddaeb30289f7b787ba2116a
|
Provenance
The following attestation bundles were made for topodb-0.1.0.tar.gz:
Publisher:
bindings.yml on TopoDB/TopoDB
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topodb-0.1.0.tar.gz -
Subject digest:
d034bfd1c6d73b06c34678299dd31e0a64ba3d66c69c2fdb66540898a5a12f62 - Sigstore transparency entry: 2568192924
- Sigstore integration time:
-
Permalink:
TopoDB/TopoDB@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Branch / Tag:
refs/tags/bindings-v0.1.0 - Owner: https://github.com/TopoDB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
bindings.yml@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Trigger Event:
push
-
Statement type:
File details
Details for the file topodb-0.1.0-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: topodb-0.1.0-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c55f6e10397b99e2fb8b90ecb2fd0bd1f99e4645d7f1e15c6d0ccb74f6a698d
|
|
| MD5 |
e7ce6d37427581f489a40ffe5c87505e
|
|
| BLAKE2b-256 |
5bc01b5760c1d59a8fec03d8881dbfb1f47566c23032da4acaf64c54b679c45c
|
Provenance
The following attestation bundles were made for topodb-0.1.0-cp39-abi3-win_amd64.whl:
Publisher:
bindings.yml on TopoDB/TopoDB
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topodb-0.1.0-cp39-abi3-win_amd64.whl -
Subject digest:
8c55f6e10397b99e2fb8b90ecb2fd0bd1f99e4645d7f1e15c6d0ccb74f6a698d - Sigstore transparency entry: 2568192933
- Sigstore integration time:
-
Permalink:
TopoDB/TopoDB@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Branch / Tag:
refs/tags/bindings-v0.1.0 - Owner: https://github.com/TopoDB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
bindings.yml@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Trigger Event:
push
-
Statement type:
File details
Details for the file topodb-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: topodb-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f5d0533d37fdda8f959803f128e0d323e1ed057b6ec0f7d4e283642c9341de0
|
|
| MD5 |
dfc73ae23f95dd59833b1c4c5902edd6
|
|
| BLAKE2b-256 |
cdee8ac1417ef28afbc4c9a32437e92e7113777cc64f4aadb831e6da42e99429
|
Provenance
The following attestation bundles were made for topodb-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
bindings.yml on TopoDB/TopoDB
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topodb-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
2f5d0533d37fdda8f959803f128e0d323e1ed057b6ec0f7d4e283642c9341de0 - Sigstore transparency entry: 2568192940
- Sigstore integration time:
-
Permalink:
TopoDB/TopoDB@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Branch / Tag:
refs/tags/bindings-v0.1.0 - Owner: https://github.com/TopoDB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
bindings.yml@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Trigger Event:
push
-
Statement type:
File details
Details for the file topodb-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: topodb-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c5b5c9627d7158e29ee998ce71f4b5a37df29a8694461d3989763bc5299d7c6
|
|
| MD5 |
26a64f688155ae76353a8b91c707876f
|
|
| BLAKE2b-256 |
92c373ffb03d1b3d973756fbc1f7aa5c4fa02463365abe605c32e87a05ff6e4a
|
Provenance
The following attestation bundles were made for topodb-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
bindings.yml on TopoDB/TopoDB
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topodb-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
6c5b5c9627d7158e29ee998ce71f4b5a37df29a8694461d3989763bc5299d7c6 - Sigstore transparency entry: 2568192943
- Sigstore integration time:
-
Permalink:
TopoDB/TopoDB@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Branch / Tag:
refs/tags/bindings-v0.1.0 - Owner: https://github.com/TopoDB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
bindings.yml@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Trigger Event:
push
-
Statement type:
File details
Details for the file topodb-0.1.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: topodb-0.1.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 2.9 MB
- Tags: CPython 3.9+, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f8293ea7b8cceb12904ee5bad8165e2eb0c448ad1db1d72f721fb2d559425cc
|
|
| MD5 |
ea140eb2f8354e05d941bbf5daa39913
|
|
| BLAKE2b-256 |
6143fab41eadc964ce11a7ed4add70d431841b15a48fef4592efd87f05b97098
|
Provenance
The following attestation bundles were made for topodb-0.1.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:
Publisher:
bindings.yml on TopoDB/TopoDB
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topodb-0.1.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl -
Subject digest:
1f8293ea7b8cceb12904ee5bad8165e2eb0c448ad1db1d72f721fb2d559425cc - Sigstore transparency entry: 2568192926
- Sigstore integration time:
-
Permalink:
TopoDB/TopoDB@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Branch / Tag:
refs/tags/bindings-v0.1.0 - Owner: https://github.com/TopoDB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
bindings.yml@2ac2e95f04a6526e58d17ed0f5eeb92dfc4dcacb -
Trigger Event:
push
-
Statement type: