Skip to main content

CyborgDB

CyborgDB Python SDK

PyPI - Version PyPI - License PyPI - Python Version

The CyborgDB Python SDK is the Python client for CyborgDB — the vector database that stays encrypted even while it's searching. Run similarity search directly on encrypted data with client-side keys; only the result of a query is ever decrypted, never the index. Built for Python, it fits into existing AI and data workflows.

This SDK talks to cyborgdb-service, which you self-host in your own VPC or on-prem and run alongside your app. Install and start it separately. See our docs for more info.

Key Features

  • Encryption-in-use: Search runs directly on ciphertext; only the query result is decrypted, never the index or stored vectors
  • Encrypted ANN: Disk-backed encrypted DiskIVF index with recall within 2% of a plaintext baseline (read the benchmarks)
  • Filters on encrypted metadata: Combine vector similarity with equality and range predicates in a single request
  • BYOK / HYOK: Wrap per-index keys with AWS KMS or AWS Secrets Manager, or hold the key client-side — you control the key material
  • Per-tenant key isolation: Per-index, per-user keys with cryptographic RBAC; revoke a user and their keys are erased
  • Pythonic API: Familiar client/index interface that integrates with existing Python AI workflows

Getting Started

To get started in minutes, check out our Quickstart Guide.

Install the SDK

  1. Install cyborgdb-service
# Pull the CyborgDB Service image
docker pull cyborginc/cyborgdb-service

# Or install via pip
pip install cyborgdb-service
  1. Install cyborgdb SDK:
# Install the CyborgDB Python SDK
pip install cyborgdb

Index and query vectors

from cyborgdb import Client

client = Client(
    "https://localhost:8000", "your-service-root-key"
)  # api_key optional; only if the service was started with one

# Generate a 32-byte encryption key
index_key = client.generate_key()

# Create an encrypted index
index = client.create_index(index_name="my-index", index_key=index_key)

# Add encrypted vector items
items = [
    {
        "id": "doc1",
        "vector": [0.1] * 128,  # Replace with real embeddings
        "contents": "Hello world!",
        "metadata": {"category": "greeting", "language": "en"},
    },
    {
        "id": "doc2",
        "vector": [0.1] * 128,  # Replace with real embeddings
        "contents": "Bonjour le monde!",
        "metadata": {"category": "greeting", "language": "fr"},
    },
]

index.upsert(items)

# Query the encrypted index
query_vector = [0.2] * 128  # 128 dimensions
results = index.query(query_vectors=query_vector, top_k=5)

# Print the results
for result in results:
    print(f"ID: {result['id']}, Distance: {result['distance']}")
# ID: doc1, Distance: 1.1314
# ID: doc2, Distance: 1.1314

Run batch queries

# Search with multiple query vectors simultaneously
query_vectors = [[0.1] * 128, [0.2] * 128]

batch_results = index.query(query_vectors=query_vectors, top_k=5)

# Print the results (batch queries return list of lists)
for i, query_results in enumerate(batch_results):
    print(f"\nResults for query {i}:")
    for result in query_results:
        print(f"  ID: {result['id']}, Distance: {result['distance']}")
# Results for query 0:
#   ID: doc1, Distance: 0.0000
#   ID: doc2, Distance: 0.0000
#
# Results for query 1:
#   ID: doc1, Distance: 1.1314
#   ID: doc2, Distance: 1.1314

Filter results by metadata

# Search with metadata filters
query_vector = [0.1] * 128
results = index.query(
    query_vectors=query_vector,
    top_k=10,
    n_probes=1,
    greedy=False,
    filters={"category": "greeting", "language": "en"},
    include=["distance", "metadata"],
)

# Print the results
for result in results:
    print(
        f"ID: {result['id']}, Distance: {result['distance']}, Metadata: {result['metadata']}"
    )
# ID: doc1, Distance: 0.0000, Metadata: {'category': 'greeting', 'language': 'en'}

Bring Your Own Key (BYOK) via KMS

When the service is configured with a kms.registry entry, the SDK can delegate key management entirely to the server-side KMS. The service generates the data encryption key, wraps it under the named KMS slot, and persists the envelope — the SDK never sees or holds the key.

# Create a KMS-backed index — no index_key from the SDK side.
# 'vendor-kms-slot' must match an entry in the service's cyborgdb.yaml.
index = client.create_index(
    index_name="kms-backed-index",
    kms_name="vendor-kms-slot",
    dimension=128,
    metric="euclidean",
)

# Reopening the index later doesn't require a key either; the service
# resolves the data key from the index's stored KMS envelope.
loaded = client.load_index(index_name="kms-backed-index")
loaded.upsert(items)

Alternatively, the SDK can supply the key itself — pass index_key and omit kms_name. This is the no-KMS path, which the service records internally as provider: none:

index = client.create_index(
    index_name="sdk-keyed-index",
    index_key=index_key,
    dimension=128,
)

Supply exactly one of index_key / kms_name — passing both is rejected by the service with a 400, since the named slot already determines the key source.

Control access with per-user keys

When the service runs with a root admin key (CYBORGDB_SERVICE_ROOT_KEY) set, RBAC is enabled. The root can mint per-user API keys scoped to a single index, each with a read / write permission set. Permissions are enforced cryptographically: a user's wrapped data-encryption keys are their permission set. A read-only user cannot decrypt for a write operation; revoking a user erases their keys.

# Admin (root) client: mint users on an existing index.
admin = Client(base_url, api_key=SERVICE_ROOT_KEY)
index = admin.load_index(index_name="kms-backed-index")  # KMS-backed (see BYOK)

reader = index.create_user(permissions=["read"])
writer = index.create_user(permissions=["read", "write"])
# Each returns {'user_id': '<hex>', 'api_key': 'cdbk_...'} — the api_key is
# shown ONCE and never stored by the service. Hand it to the user securely.

index.list_users()  # [{'user_id': ..., 'permissions': [...]}, ...]
index.delete_user(reader["user_id"])  # revoke; the key stops working immediately

A user authenticates with their cdbk_ key and needs no index key of their own — they load the index by name and the service resolves its key:

user = Client(base_url, api_key=reader["api_key"])
idx = user.load_index(index_name="kms-backed-index")  # no index_key
idx.query(query_vectors=[...], top_k=5)  # allowed for 'read'
idx.upsert(items)  # raises ValueError for read-only users

User keys resolve the index key server-side, so they work against KMS-backed indexes. SDK-supplied-key indexes (provider: none) have no server-side key for the service to resolve on a user's behalf. See the service's rbac.md for the full design.

Documentation

For more information on CyborgDB, see the Cyborg Docs.

License

The CyborgDB Python SDK is licensed under the MIT License.

Metadata

Release files for cyborgdb 0.18.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cyborgdb 0.18.0
File Size Uploaded
cyborgdb-0.18.0.tar.gz 245.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cyborgdb 0.18.0
File Interpreter ABI Platform
cyborgdb-0.18.0-py3-none-any.whl Python 3 none any Details

Total release size: 388.7 kB

Release files / cyborgdb-0.18.0.tar.gz

Download URL cyborgdb-0.18.0.tar.gz
Size 245.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c2339ac36ec3ff428f85a02f741aa520b1c0359790afd983963a6d40a638bf96
BLAKE2b-256 checksum
How to use checksums
a6a5144d247ff98ce9bb4ae130aa6b47c30465d42a8a903763228e3c7f35a23b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / cyborgdb-0.18.0-py3-none-any.whl

Download URL cyborgdb-0.18.0-py3-none-any.whl
Size 143.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f4ca8a4ac55b7eb197ecc40528effa6e59d9fee2b4d82f3610a378841b8d94aa
BLAKE2b-256 checksum
How to use checksums
8f934f7ea8713420e27800a49c21e721c55ed85190655c7d26d8de169171460d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.18.0 This release

2 release files

0.17.0

2 release files

0.15.0

2 release files

0.14.0

2 release files

0.13.1

2 release files

0.13.0

2 release files

0.12.0

2 release 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