OriginChainDB docs
sdks · python

Python SDK

The widest of the three clients. Sync and async, typed namespaces for every query surface, and the only one that retries transient failures for you.

Install

Python 3.9 or newer. The client uses httpx, and will negotiate HTTP/2 when the extra is present.

pip install originchain

Connect

The standard bootstrap reads three environment variables - OC_BASE_URL, OC_BEARER and OC_TENANT - and raises if any is missing, rather than failing later on the first call.

from originchain import OriginChain

db = OriginChain.from_env()
print(db.health())

Pass them explicitly when the environment is not yours to set, in tests for instance:

db = OriginChain(
    base_url="https://t-abc.your-region.db.originchain.ai",
    bearer="oc_live_...",
    tenant="t-abc",
    timeout=30.0,
    max_retries=3,
)

There is an async client with the same surface. Everything on this page works on it with await, and it closes with await db.aclose().

from originchain import AsyncOriginChain

db = AsyncOriginChain.from_env()
rows = await db.sql("SELECT 1")
await db.aclose()

The namespaces

The client is organised by surface. Each namespace hangs off the client instance:

NamespaceWhat is on it
db.schemaslist(), get(), register()
db.rowsget(), put(), put_batch()
db.sqlcallable, plus query(), execute() and the materialized-view calls
db.vectorput(), topk(), delete(), delete_bulk(), centroid install and training
db.ftsindex(), search(), install_synonyms(), install_stopwords()
db.graphneighbours, BFS, shortest path, Dijkstra, and the graph algorithms
db.adminper-tenant replication configuration
one attribute, two shapes

db.sql is a callable namespace. db.sql("SELECT ...") and db.sql.query("SELECT ...") both work and hit the same endpoint, so older code keeps running while new code can reach the typed calls next to it.

Register a schema and write rows

A schema is TOML, and it is the same declaration every surface reads - see the schema reference.

db.schemas.register(open("products.toml").read())
db.schemas.list()

db.rows.put("shop.products", {
    "id": "sku-1",
    "name": "Aeron chair",
    "price": 1195,
})

# Batched writes are chunked, and each chunk carries its own
# derived idempotency key, so a partial retry does not duplicate.
db.rows.put_batch("shop.products", rows)

Query

SQL

resp = db.sql.query(
    "SELECT name, price FROM shop.products WHERE price > 500 ORDER BY price DESC"
)
for r in resp.rows:
    print(r["name"], r["price"])

one = db.sql_one("SELECT count(*) AS n FROM shop.products")

Full-text

db.fts.index("shop.products", "name", pk="sku-1", text="Aeron chair")
hits = db.fts.search("shop.products", "name", q="chair", limit=10)

Vector

db.vector.put("shop.products", pk="sku-1", vector=embedding)
hits = db.vector.topk("shop.products", vector=query_vec, k=10)

Graph

The five traversals plus the algorithm calls. Which algorithms your instance answers is covered in the graph reference.

db.graph.neighbors("shop", rel="bought_with", pk="sku-1")
db.graph.bfs("shop", rel="bought_with", pk="sku-1", depth=3)
db.graph.pagerank("shop", rel="bought_with")
db.graph.louvain("shop", rel="bought_with")

Natural language

answer = db.ask("which products sold best last week?", schemas=["shop"])

Errors

Every failure is a typed exception, so you can catch the one case you can do something about:

ExceptionRaised when
OCAuthErrorthe token is missing, wrong, or lacks the role for this call
OCValidationErrorthe request was malformed - a bad schema, an unknown column
OCNotFoundErrorthe schema, table or row does not exist
OCPaymentRequiredErrorthe call needs an add-on the account does not have
OCRateLimitedErrorthe tenant is over its request budget
OCServerErrorthe engine failed - retried already, if retries are on
OCReplicationDegradeda warning, not an exception: the read was served while a replica was catching up

All of them subclass OCError, so a single catch still works.

from originchain import OCRateLimitedError, OCError

try:
    db.sql("SELECT 1")
except OCRateLimitedError:
    back_off()
except OCError as e:
    log.exception(e)

Retries and idempotency

This client retries 429, 500, 502, 503 and 504 up to max_retries times. Mutating requests carry a generated Idempotency-Key, which the engine caches server-side, so a retried write lands once.

Pass a stable idempotency_key yourself when the retry has to survive a process restart - a job runner picking the same task up again, for instance. Batched writes derive one key per chunk from the key you give, so partial progress is preserved.

Source

pip install originchain · originchain-ai/originchain-python · the HTTP API underneath