Skip to main content

cavs — Python SDK for CAVS Hub

Official Python client for CAVS Hub, the content-addressed, deduplicating artifact store for AI, CI/CD and build pipelines. It speaks the same canonical API the CLI uses — one API, one permission model, one data plane. The wire behaviour is defined in ../CONTRACT.md and pinned by the shared vectors in ../spec/contract/.

  • Requires Python 3.9+.
  • Only runtime dependency: httpx.

Install

pip install cavs

From this monorepo checkout:

cd python
pip install -e ".[dev]"

Quickstart

from cavs import CAVS

client = CAVS.from_env()          # reads CAVS_TOKEN + CAVS_API

artifact = client.artifacts.upload(
    path="./model",
    project="vision-models",
    name="resnet50",
    kind="model",
    version="1.4.0",
    metadata={"framework": "pytorch", "accuracy": 0.942},
)
print(artifact.reference)          # cavs://acme-ai/vision-models/model/resnet50:1.4.0
print(artifact.deduplication_ratio)

client.artifacts.download(artifact.reference, dest="./restored")

Track training runs and lineage:

run = client.runs.create(project="vision-models", name="nightly", system="mlflow")
client.runs.update("vision-models", run.id, status="completed")

Authentication

Create a service account in the CAVS dashboard and export its key. Tokens are resolved in this order: an explicit token= argument, then $CAVS_TOKEN.

export CAVS_TOKEN=cavs_sk_...
export CAVS_API=https://cavsnode.com        # default; use http://localhost:8080 for dev

Other environment variables:

Variable Purpose
CAVS_TOKEN Auth token (cavs_sk_…, cavs_pat_…, …)
CAVS_API Base URL (default https://cavsnode.com)
CAVS_ORG Default organization slug
CAVS_CA_BUNDLE Path to a custom CA bundle for TLS verification

Or construct explicitly:

client = CAVS(token="cavs_sk_...", api="https://cavsnode.com", org="acme-ai")

project and org resolution

project is an alias for a repository. It is resolved within an org by matching the value against each repository's id, slug or name (GET /organizations/{org}/repositories); if nothing matches, the value is used verbatim as a repository id. The org comes from an explicit argument, then CAVS_ORG, then the caller's default org from GET /users/me.

Security

Following ../CONTRACT.md §2, this SDK:

  • never prints the token in repr, exceptions, or logs — it is redacted to e.g. cavs_sk_…abcd;
  • never logs presigned URLs or full request headers;
  • verifies TLS and honours CAVS_CA_BUNDLE; caps redirects at 5;
  • always sets connect + read timeouts;
  • verifies sha256 == oid on every download and refuses to write a mismatched file (ChecksumError), cleaning up the temp file;
  • guards against path traversal when expanding directories / archive members;
  • honours Retry-After and cleans up temp files on failure;
  • supports cancellation via a threading.Event (or any object with is_set()).

Uploads and downloads

Large files never travel through the control plane — they stream directly to object storage via presigned URLs (CONTRACT §5).

  • Upload: hash every file (streamed sha256, 64 KiB chunks) → open a session with an Idempotency-Key → authorize objects (the Hub reports which already exists, so dedup and resume are automatic) → PUT the missing bytes → complete each object → finalize (idempotent), which returns dedup stats.
  • Download: authorize → stream to a deterministic temp file while hashing → verify sha256 == oid → atomically rename into place.

Progress and cancellation:

import threading

cancel = threading.Event()
client.artifacts.upload(
    path="./big-dataset",
    project="datasets",
    name="imagenet",
    kind="dataset",
    version="2026.07.24",
    on_progress=lambda done, total: print(f"{done}/{total}"),
    cancel=cancel,
)

cavs:// URIs

from cavs import parse, format_uri

p = parse("cavs://acme-ai/vision-models/model/resnet50:1.4.0")
p.org, p.name, p.version        # 'acme-ai', 'resnet50', '1.4.0'
format_uri(p)                    # round-trips to the canonical form

Errors

All exceptions derive from cavs.CAVSError. The HTTP → exception mapping follows CONTRACT §8:

HTTP Exception
401 AuthenticationError
403 AuthorizationError
404 NotFoundError
409 ConflictError
413 / 402 QuotaExceededError
429 RateLimitError (honours Retry-After)
5xx / network TemporaryServiceError (retried, ≤4 attempts)
client-side checksum mismatch ChecksumError
upload / download transport UploadError / DownloadError
from cavs import CAVS, NotFoundError, RateLimitError

try:
    client.artifacts.get("does-not-exist")
except NotFoundError as e:
    print(e.code, e.status)
except RateLimitError as e:
    print("retry after", e.retry_after)

Development

cd python
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
ruff check . && mypy src && pytest --cov=cavs --cov-fail-under=90

Tests mock httpx with respx — no network is used. See ../CONTRIBUTING.md and the docs in ../docs/.

License

Apache 2.0 — see ../LICENSE.

Metadata

Release files for cavs 0.2.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 cavs 0.2.0
File Size Uploaded
cavs-0.2.0.tar.gz 26.6 kB Details

Built distribution (wheel)

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

Total release size: 52.2 kB

Release files / cavs-0.2.0.tar.gz

Download URL cavs-0.2.0.tar.gz
Size 26.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f00572805f61caf8d82710cdaa934c8c9b4b87d6fc56d4326db60d0f906f8048
BLAKE2b-256 checksum
How to use checksums
1b5cc218f2500b990157a0748875c0568b71a9a503acabbcffb1639ffe367c08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / cavs-0.2.0-py3-none-any.whl

Download URL cavs-0.2.0-py3-none-any.whl
Size 25.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6d770394cc2163379a3cdeafc9b99a6a887cd2796818fd77093be6e986bab84e
BLAKE2b-256 checksum
How to use checksums
0e2633aac92a19fa615f3a4c72f3c9c8f16cbc324ffd5524ecc23135a0d83ec8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.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