Skip to main content

pylibseekdb

Low-level Python bindings for the seekdb C client library.

🚀 What is OceanBase seekdb?

OceanBase seekdb is an AI-native search database that unifies relational, vector, full-text, JSON, and GIS in a single engine, enabling hybrid search and in-database AI workflows.

📖 Read the launch blog → · 📚 Docs →

✨ Why seekdb for Agents?

🔥 Streaming Write + Concurrent Search, Without the P99 Spike

Agent workloads are continuous write + millisecond-later read. seekdb's async index pipeline (Change Stream) decouples DML from index build, and its two-level HNSW (incremental + snapshot) makes newly-written vectors immediately searchable.

seekdb async index pipeline architecture

The write path commits and returns without waiting on index construction. The Change Stream pipeline consumes the redo log asynchronously and updates the delta HNSW. Queries hit both delta and snapshot indexes with fine-grained read locks — this is why P99 stays flat under concurrency.

🌿 Copy-on-Write Sandboxes for Agent Exploration

FORK DATABASE snapshots an entire database in seconds — no data copy. Agents experiment freely (write, query, even break tables); then MERGE TABLE commits the work back, or DROP DATABASE discards it.

🔍 Hybrid Search in a Single SQL

Vector + full-text + scalar filter pushed into one execution plan. No N+1 client-side merging, no glue code to combine results.

🐬 MySQL-Compatible, ACID, Embeddable

Built on the proven OceanBase SQL engine. Works as an embedded library, a single-node server, or in the OceanBase distributed cluster. Full ACID, real-time writes, and the entire MySQL ecosystem out of the box.

Installation

pip install pylibseekdb

Requirements

  • CPython >= 3.11
  • Linux x86_64 or aarch64 with glibc >= 2.28 (Alpine / musl not supported yet)
  • macOS arm64 >= 15.6

🎬 Quick Start

pylibseekdb exposes a lightweight DB-API 2-style interface directly over the seekdb C driver. It currently starts a local seekdb runtime via open(). Native embedded-mode support will be released soon.

import pylibseekdb as seekdb

# Start a local seekdb runtime (embedded-mode support will be released soon)
seekdb.open(db_dir="./seekdb.db")

# Get a connection and a cursor
conn   = seekdb.connect(database="test", autocommit=True)
cursor = conn.cursor()

# Create a table with a vector column and an HNSW index
cursor.execute("""
    CREATE TABLE IF NOT EXISTS articles (
        id        INT PRIMARY KEY,
        title     TEXT,
        embedding VECTOR(4),
        VECTOR INDEX idx_vec (embedding)
            WITH (DISTANCE=l2, TYPE=hnsw, LIB=vsag)
    ) ORGANIZATION = HEAP
""")

# Insert a row
cursor.execute(
    "INSERT INTO articles VALUES (1, 'Hello seekdb', '[0.1, 0.2, 0.3, 0.4]')"
)

# Hybrid / vector search
cursor.execute("""
    SELECT id, title,
           l2_distance(embedding, '[0.1, 0.2, 0.3, 0.4]') AS dist
    FROM articles
    ORDER BY dist APPROXIMATE
    LIMIT 5
""")
rows = cursor.fetchall()
for row in rows:
    print(row)

cursor.close()
conn.close()
seekdb.close()

Multiple instances

One process can manage multiple local seekdb runtimes through the SeekdbInstance objects returned by open():

import pylibseekdb as seekdb

first = seekdb.open("./first.db")
second = seekdb.open("./second.db")

first_connection = first.connect(database="test")
second_connection = second.connect(database="test")

first_connection.close()
second_connection.close()
first.close()
second.close()

Each instance uses the local socket inside its normalized database directory, so no additional port configuration is needed. The first successful open() also becomes the module's default instance, preserving the legacy seekdb.connect(), seekdb.connection_options(), and seekdb.close() API. Later calls return independent instance objects without changing that default. Use the object methods for additional instances.

Connect with PyMySQL

connection_options() returns endpoint and authentication arguments shared by Python MySQL-protocol drivers. Install the driver separately:

pip install PyMySQL
import pymysql
import pylibseekdb as seekdb

instance = seekdb.open(db_dir="./seekdb.db")
options = instance.connection_options()

connection = pymysql.connect(database="test", **options)
try:
    with connection.cursor() as cursor:
        cursor.execute("SELECT 1")
        print(cursor.fetchone())
finally:
    # External connections must release the server before its lifecycle handle.
    connection.close()
    instance.close()

On Unix, options contains only user="root" and unix_socket. For TCP it contains only user="root" and port; the driver supplies its default local host. The database name remains caller-owned because PyMySQL uses database while aiomysql uses db. Treat the returned dictionary as lifecycle-scoped: do not use it after closing its SeekdbInstance.

Async initialization and aiomysql

Install aiomysql separately:

pip install aiomysql
import asyncio

import aiomysql
import pylibseekdb as seekdb


async def main():
    instance = await seekdb.aopen(db_dir="./seekdb.db")
    options = instance.connection_options()
    pool = await aiomysql.create_pool(
        db="test",
        minsize=1,
        maxsize=5,
        **options,
    )
    try:
        async with pool.acquire() as connection:
            async with connection.cursor() as cursor:
                await cursor.execute("SELECT 1")
                print(await cursor.fetchone())
    finally:
        pool.close()
        await pool.wait_closed()
        instance.close()


asyncio.run(main())

aopen() runs the synchronous C startup operation in a worker thread and returns a SeekdbInstance, so it does not block the asyncio event loop. Cancelling the coroutine cannot stop seekdb_open() after that worker starts.

Transaction support

conn = seekdb.connect(database="test", autocommit=False)
cursor = conn.cursor()
try:
    conn.begin()
    cursor.execute("INSERT INTO articles VALUES (2, 'Second', '[0.5,0.6,0.7,0.8]')")
    conn.commit()
except seekdb.SeekdbError:
    conn.rollback()
    raise
finally:
    cursor.close()
    conn.close()

SQL — Hybrid Search

-- Create table with vector column, full-text index, and HNSW vector index
CREATE TABLE docs (
    id        INT PRIMARY KEY,
    title     TEXT,
    content   TEXT,
    embedding VECTOR(384),
    FULLTEXT INDEX idx_fts (content) WITH PARSER ik,
    VECTOR   INDEX idx_vec (embedding)
        WITH (DISTANCE=l2, TYPE=hnsw, LIB=vsag)
) ORGANIZATION = HEAP;

-- Hybrid search: vector similarity + full-text match in one query
SELECT id, title,
       l2_distance(embedding, '[0.12, 0.34, ...]') AS dist
FROM docs
WHERE MATCH(content) AGAINST('quarterly report')
ORDER BY dist APPROXIMATE
LIMIT 10;

API Reference

Module-level functions

Function Description
open(db_dir="./seekdb.db") Start a local runtime and return its SeekdbInstance. The first open instance becomes the module default.
await aopen(db_dir="./seekdb.db") Run open() in a worker thread and return its SeekdbInstance.
connection_options() Return connection arguments for the default instance. The database name is not included.
connect(database="test", autocommit=False) Return a Connection to the default instance.
close() Close and clear the default instance. Idempotent.

SeekdbInstance

Attribute or method Description
db_dir Normalized absolute database directory used by this instance.
closed Whether this instance has been closed.
connect(database="test", autocommit=False) Return a Connection to this instance.
connection_options() Return connection arguments for PyMySQL or aiomysql.
close() Release this instance. Existing native Connection objects keep the underlying lifecycle handle alive until they close.

Connection

Method Description
cursor() Return a new Cursor.
begin() Begin a transaction.
commit() Commit the current transaction.
rollback() Roll back the current transaction.
close() Disconnect and release resources.

Cursor

Method Description
execute(sql) Execute sql; returns the number of rows in the result set (0 for statements without a result set).
fetchone() Return the next row as a tuple, or None.
fetchall() Return all remaining rows as a list of tuple.
close() Free the result set.

SeekdbError

Exception raised on driver errors. Subclass of RuntimeError.

📚 Use Cases

  • 🤖 Agentic AI — streaming memory writes, millisecond-later vector retrieval, FORK DATABASE for safe exploration
  • 📖 RAG & Knowledge Retrieval — hybrid search across enterprise knowledge bases
  • 🔍 Semantic Search — embedding-based search for text, images, and other modalities
  • 💻 AI-Assisted Coding — semantic code search with multi-project isolation
  • 📱 On-Device & Edge AI — lightweight local deployments today, with embedded-mode support coming soon

🌐 Resources

License

Apache-2.0 — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pylibseekdb-1.3.0.post4-cp312-abi3-manylinux_2_28_x86_64.whl (126.1 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ x86-64

pylibseekdb-1.3.0.post4-cp312-abi3-manylinux_2_28_aarch64.whl (111.2 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ ARM64

pylibseekdb-1.3.0.post4-cp312-abi3-macosx_15_0_arm64.whl (110.7 MB view details)

Uploaded CPython 3.12+macOS 15.0+ ARM64

pylibseekdb-1.3.0.post4-cp312-abi3-macosx_13_0_x86_64.whl (127.3 MB view details)

Uploaded CPython 3.12+macOS 13.0+ x86-64

pylibseekdb-1.3.0.post4-cp311-cp311-manylinux_2_28_x86_64.whl (126.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

pylibseekdb-1.3.0.post4-cp311-cp311-manylinux_2_28_aarch64.whl (111.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ ARM64

pylibseekdb-1.3.0.post4-cp311-cp311-macosx_15_0_arm64.whl (110.7 MB view details)

Uploaded CPython 3.11macOS 15.0+ ARM64

pylibseekdb-1.3.0.post4-cp311-cp311-macosx_13_0_x86_64.whl (127.3 MB view details)

Uploaded CPython 3.11macOS 13.0+ x86-64

File details

Details for the file pylibseekdb-1.3.0.post4-cp312-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post4-cp312-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ee2700b5990e5e4f11c4b980b182cf7b066817ddd91c7b876152b88a7c24a7ea
MD5 d42dd08bb058cddd5c6298594b6a732b
BLAKE2b-256 19e949507c0859bf0898f99f2b0978baba6cfaca9563e4ba20242be014ee7e6c

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post4-cp312-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post4-cp312-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 5052794da997f3311f9b57c0bf29d492bf184118fe03829df74975bce7beecf5
MD5 5328595ac0b6740c0162909b731a9b90
BLAKE2b-256 fca7e84f65b0ae5eaa8e1adaad3cf7609017c4e9cfd7b957f56efcd87ce14916

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post4-cp312-abi3-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post4-cp312-abi3-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 1365f13dab633eadb2f8f305f8af638adacc5bfb9e71abd877190476d30d1589
MD5 4300c3e9074629f08a3d2ed3f58a49ff
BLAKE2b-256 cd61ae4c488692e9ad1a126c6f7af85d1480da711ff419dc54d6919052386c2a

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post4-cp312-abi3-macosx_13_0_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post4-cp312-abi3-macosx_13_0_x86_64.whl
Algorithm Hash digest
SHA256 7d2065c58d7accfe8e9281487969c996d8ef8d9d6b8a2e7a3cdfc6c5363ff4d5
MD5 b2369615def50e78e7a2e9a39f845e9e
BLAKE2b-256 f67875d5993ca18a3e64cc2ca4e2e8f2738865f93cfc5cebd7ec134314dc347b

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post4-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post4-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5d6934330d218c4e3edf9d2ec9cb339f6c0a73c587883edb58c90904f6f2d6e7
MD5 6e7290a140b16053d07b248c3de26cb4
BLAKE2b-256 5f07d49a43e1211d03fb54bc41ba777debac253bb252d65a5b9cf3771b95ab86

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post4-cp311-cp311-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post4-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 2e59856d1f994ba9c32a58c47f368b0e271127e92e4e47f8831a3093147068ea
MD5 293116e5b7bc5faf9083bdbd19723757
BLAKE2b-256 4c434169d9485b6de641187bf56f5549d318a4d06df01f92ae9f8dfb9b6d99a1

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post4-cp311-cp311-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post4-cp311-cp311-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 6b81347bb6358cbbc285034bf8c90efe6c2e7271d44a3662c783ee3082612716
MD5 357493e2401521bc78b7145e8481bbcb
BLAKE2b-256 f50dc36fb774730d6846cd787744f302f4c0c5d4f10f77d053615c3cfd39c2f2

See more details on using hashes here.

File details

Details for the file pylibseekdb-1.3.0.post4-cp311-cp311-macosx_13_0_x86_64.whl.

File metadata

File hashes

Hashes for pylibseekdb-1.3.0.post4-cp311-cp311-macosx_13_0_x86_64.whl
Algorithm Hash digest
SHA256 b1fc2cebc222c398044bc494d2814f59c37c2795a352c8c8f8e2638b2d3180a7
MD5 9d77a385d97ebf1484d32905167624df
BLAKE2b-256 567b6f32f431c72b79673fa2d63c0f2e073b5435f76dd96d8f0da244c1da6f18

See more details on using hashes here.

Release history Release notifications | RSS feed

1.4.0.post1

8 files

1.4.0

8 files

1.4.0.dev2

1.3.0.post5

8 files

This release

1.3.0.post4 This release

8 files

1.3.0.post3

12 files

1.3.0

18 files

1.2.0

18 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page