Commutator Studios Python SDK
Commutator SDK is the official Python client for the Commutator Studios quantum ecosystem. It provides a seamless, developer-friendly interface to integrate quantum workloads, optimization engines, and identity management natively into your Python tech stack.
By connecting to the Centralized API Gateway (commutator.app), this SDK handles authentication, rate-limiting, and billing checks automatically, allowing you to focus on building quantum-accelerated applications.
Features
- Quantum Fleet Management: Discover, list, and check the status of available quantum backends (e.g.,
ibm_berlin,ibmq_qasm_simulator). Automatically synchronizes hardware catalog using the authenticated user's quantum provider credentials. - Hardware & Algorithmic Recommendations: Interface directly with
cs-optimizerto get smart recommendations for hardware and optimization levels (e.g., VQE) before you run your circuits. - Job Execution & Polling: Submit quantum circuits, execute jobs on actual quantum hardware, and download results natively into Python objects.
- Standardized Error Handling: Detailed, structured exceptions (
APIError,ValidationError,AuthenticationError) for predictable and easy debugging. - ...and more!
Installation
The SDK requires Python 3.11+. You can install it directly from PyPI using pip:
pip install commutator-sdk
Install the optional Qiskit interoperability layer when constructing jobs from
native QuantumCircuit and SparsePauliOp objects:
pip install "commutator-sdk[qiskit]"
Quick Start
Here is a simple example showing how to authenticate, create a job, execute a circuit, and fetch the results.
1. Authentication
You can authenticate using your API Key or Username/Password.
from commutator.client import CommutatorClient
# Initialize the client (Environment is auto-detected)
client = CommutatorClient(api_key="your_api_key_here")
2. Submitting a Quantum Job
Submit your quantum circuit JSON and execute it on a selected backend.
import time
from commutator import (
ClassicalOptimizer,
CommutatorClient,
CSAlgorithmName,
CSRunOptions,
CSVQEOptions,
)
client = CommutatorClient() # Reads COMMUTATOR_API_KEY
backend = client.backends.get("ibm_berlin")
# 1. Create the job with a built-in algorithm enum.
job = client.jobs.create(
name="My First VQE Run",
algorithm=CSAlgorithmName.VQE1,
file_path="circuit.json"
)
print(f"Job created successfully: {job.id}")
# 2. Persist algorithm controls and submit execution settings.
job = job.run(
execution_options=CSRunOptions(backend=backend, optimization_level=3),
algorithm_options=CSVQEOptions(
optimizer=ClassicalOptimizer.COBYLA,
max_iterations=5,
max_evaluations=12,
convergence=0.005,
optimizer_options={"rhobeg": 0.5},
),
)
while not job.done:
time.sleep(5)
job = job.refresh()
print(job.results())
3. Optimizer Recommendations
Not sure which backend or optimization level to use? Ask the Recommendation Engine!
job = job.recommend(
target_backends=[backend, "ibm_brisbane"], # CSBackend objects and slugs are accepted.
timeout=300,
)
print(job.recommendations_table())
execution_options = job.best_recommendation(
backend=backend,
dynamic_decoupling=True,
)
if execution_options is None:
raise RuntimeError("No completed recommendation matches those filters")
# recommendations() returns every completed CSRunOptions choice and always
# reads current platform state without starting another recommendation run.
other_options = job.recommendations()[1]
job = job.run(
execution_options=execution_options,
algorithm_options=CSVQEOptions(max_iterations=100, convergence=0.001),
)
Error Handling & Exception Reference
When executing quantum simulation jobs, the SDK automatically inspects the API response errorCode and raises typed Python exceptions providing human-readable diagnostic remedies:
from commutator.client import CommutatorClient
from commutator.exceptions import (
SimulationOOMError,
SimulationTimeoutError,
ProviderAuthenticationError,
JobFailedError
)
client = CommutatorClient(api_key="your_api_key")
try:
job_details = client.jobs.get(job_id="5bacd027-267d-4c8e-94c4-5348c48880b3")
except SimulationOOMError as e:
print(f"❌ Memory Error [{e.error_code}]: {e.message}")
print(f"💡 Actionable Remedy: {e.remedy}")
except SimulationTimeoutError as e:
print(f"⏱️ Job Timed Out [{e.error_code}]: {e.message}")
print(f"💡 Actionable Remedy: {e.remedy}")
except JobFailedError as e:
print(f"⚠️ Job Execution Failed [{e.error_code}]: {e.message}")
Supported Exception Mapping
API errorCode Enum |
Raised SDK Exception Class | Python Import Path |
|---|---|---|
SIMULATION_OOM |
SimulationOOMError |
from commutator.exceptions import SimulationOOMError |
SIMULATION_TIMEOUT |
SimulationTimeoutError |
from commutator.exceptions import SimulationTimeoutError |
PROVIDER_AUTH_FAILED |
ProviderAuthenticationError |
from commutator.exceptions import ProviderAuthenticationError |
OPTIMIZATION_DIVERGED |
OptimizationDivergedError |
from commutator.exceptions import OptimizationDivergedError |
| Fallback / System Faults | JobFailedError |
from commutator.exceptions import JobFailedError |
Advanced Usage
Backend and job resources
The SDK returns validated Commutator Studios resource objects by default:
import time
from commutator import (
CommutatorClient,
CSAlgorithm,
CSAlgorithmName,
CSBackend,
CSBackends,
CSJob,
CSJobs,
CSProvider,
CSRunOptions,
CSVQEAlgorithm,
CSVQEOptions,
)
client = CommutatorClient() # Reads COMMUTATOR_API_KEY
cs_backends: CSBackends = client.backends
algorithms: list[CSAlgorithm] = client.jobs.list_algorithms()
backend: CSBackend = cs_backends.get("ibm_fez")
job: CSJob = client.jobs.create(
name="My first VQE run",
algorithm=CSAlgorithmName.VQE1,
file_path="circuit.json",
)
job = job.run(
execution_options=CSRunOptions(
backend=backend,
optimization_level=2,
predicted_shots=1024,
),
algorithm_options=CSVQEOptions(max_iterations=100, convergence=0.001),
)
while not job.done:
time.sleep(5)
job = job.refresh()
result = job.results()
CSBackends supports listing, local filters, lookup, refresh, discovery,
and explicit enable/disable operations:
available = client.backends.list(
provider=CSProvider.IBM,
enabled=True,
operational=True,
min_qubits=100,
)
backend = backend.refresh()
backend = backend.disable()
backend = backend.enable()
backend = client.backends.disable("ibm_fez")
backend = client.backends.enable("ibm_fez")
CSJobs supports create, get, list, keyword search and destructive deletion.
list_algorithms() returns validated CSAlgorithm objects with id, name,
full_name and is_available fields. Algorithm-specific entries use subclasses:
VQE catalog rows are CSVQEAlgorithm objects, while algorithms without a typed
SDK contract remain CSAlgorithm objects. create() accepts one of these objects,
a CSAlgorithmName enum member, or a string identifier.
The public types have distinct responsibilities:
| Type | Responsibility |
|---|---|
CSAlgorithm / CSVQEAlgorithm |
Catalog metadata / VQE input construction, options and result parsing |
CSVQEInput |
Ansatz, Hamiltonian and optimizer initial point |
CSVQEOptions |
Classical optimization settings |
CSRunOptions |
Backend and quantum execution settings |
CSVQEResult |
Scientific results and legacy artifact compatibility |
Implementation lives in algorithms.py, inputs.py, and results.py, with
resource snapshots in models.py. Existing top-level and commutator.models
imports remain supported. Algorithm metadata supplied at creation or read by
list_algorithms() remains available to subsequent jobs on that client. Without
catalog metadata, the SDK uses the legacy VQE* identifier fallback.
For VQE, the selected algorithm can construct the matching input model directly from Qiskit objects:
algorithm: CSVQEAlgorithm = next(
item
for item in client.jobs.list_algorithms()
if isinstance(item, CSVQEAlgorithm) and item.id == "VQE1"
)
vqe_input = algorithm.create_input(
circuit=ansatz,
hamiltonian=hamiltonian,
# These values are the optimizer's initial point. Omit them to generate
# and retain one random point for recommendations and final execution.
parameters=[0.1, -0.2],
)
job = client.jobs.create(name="Hydrogen VQE", algorithm=algorithm, input=vqe_input)
For an ansatz whose parameters are named theta_1 and theta_2, you can
also bind the initial point by name. The mapping must contain every circuit
parameter exactly once; dictionary insertion order does not affect the binding:
vqe_input = algorithm.create_input(
circuit=ansatz,
hamiltonian=hamiltonian,
parameters={
"theta_1": 0.1,
"theta_2": -0.2,
},
)
file_path="circuit.json" remains supported. Provide either input or
file_path, but not both. The typed route validates Qiskit object types, qubit
counts, finite real Hamiltonian coefficients and the number of initial parameter
values before creating the job. It generates omitted parameters once when the
input object is constructed; reusing that input reuses the same initial point.
OpenQASM export uses ordered parameter identifiers so engine import preserves
positional binding. parameter_names retains the original circuit names in that
same order. A named result binds values by name and rejects a mismatched circuit.
The legacy file route checks the JSON container only; it does not yet provide
the typed route's semantic validation or initialization.
CSJob supports refresh(), recommend(), recommendations(),
recommendations_table(), filtered best_recommendation(), run(), results() and
get_backend(). recommend() returns a fresh snapshot of the same remote job,
and both recommendation accessors return CSRunOptions. Each bound
recommendations() call reads the latest completed rows from the platform
without submitting new optimizer work, so repeated calls can reveal a growing
table without restarting it. Call recommend() explicitly to start generation.
Job names cannot
currently be changed after creation because the platform execution endpoint
does not update the circuit name.
Resource methods return new snapshots, so assign their return values.
best_recommendation() accepts optional backend, optimization_level, and
dynamic_decoupling filters and returns None when no completed option matches.
recommendations_table() produces a dependency-free ASCII table ordered by
predicted score.
CSRunOptions holds only backend and quantum execution settings. It validates
optimization level (0–3), booleans and positive shot counts. with_overrides()
makes a validated copy when you want to adjust a recommended execution option.
CSAlgorithmOptions is the base for algorithm-specific settings;
CSVQEOptions provides independent positive limits: max_iterations caps
classical optimizer iterations and max_evaluations caps objective evaluations
submitted to the quantum backend. Optimization stops when either limit or the
selected optimizer's convergence condition is reached first. Omitting
max_evaluations leaves evaluations uncapped; the iteration limit and
convergence condition still apply. convergence is
the positive convergence tolerance. optimizer accepts
ClassicalOptimizer.COBYLA or ClassicalOptimizer.SIMPLEX; the strings
"cobyla" and "simplex" are also accepted at runtime.
optimizer_options accepts rhobeg, catol, and f_target for COBYLA. For
Simplex it accepts init_simplex_size, tol_std, tol_size, reflect, and
shrink. shrink is a reciprocal scale factor greater than one: expansion
multiplies by its coefficient, while contraction and shrinking divide by their
coefficients. An unset optimizer is omitted from requests so it does not replace
a stored choice.
Pass these options to job.run(algorithm_options=...); the SDK persists them
before it submits execution_options. job.algorithm_options returns the
effective algorithm-specific model (CSVQEOptions for a VQE job).
The two writes are not atomic: if dispatch fails after saving settings, refresh
the job to inspect its current state before retrying.
If future recommendation rows contain VQE controls, they fill only fields that
are unset on the job; explicitly stored values win.
For VQE jobs, job.results() returns CSVQEResult. It accepts both current
partial/list artifacts and the structured result, so absent fields such
as optimal_parameters, iterations, or convergence_reason remain None
instead of breaking older jobs. When parameter names and optimal values are
available, use result.optimal_parameter_map or
result.bind_optimal_parameters(circuit).
Unknown explicit result schema versions require an SDK update; additive fields
within the supported version remain available. Full optimizer metrics and optimal
parameters still depend on the service emitting the structured result contract.
Additional service options require the explicit experimental={...} escape
hatch and cannot replace validated options, identity, backend or status.
Use job.refresh() for read-only status polling and stop when job.done is true.
GET requests retain bounded rate-limit retries, while mutating requests are not
replayed automatically. COMMUTATOR_TIMEOUT controls the request timeout and
defaults to 300 seconds.
There is no CSJob.cancel() yet. The legacy client.jobs.cancel() aliases the
destructive job-and-artifact deletion endpoint, so it is not exposed as a
resource convenience method.
Resource snapshots retain additive response fields and support Pydantic serialization.
model_dump(mode="json", by_alias=True) uses API field names. A model loaded
from JSON is detached; retrieve it through the client before calling a network
method. Resources from another client are rejected before submission.
Backend, RunOptions, BackendsModule, JobsModule and client.fleet
remain as compatibility aliases. Explicit list_raw() methods are available
for integrations that still need the original response dictionaries.
Interactive walkthrough
Open example.ipynb from the python directory using the SDK
virtual environment. The notebook has short, sequential examples for backend
selection, fleet management, job creation, execution, polling and results. It
uses a local sample API by default; its authentication cell explains how to
switch to staging for a real run.
Install the checkout and notebook dependencies first:
cd python
.venv/bin/python -m pip install -e . -r requirements-dev.txt
The development dependencies include Qiskit and its OpenQASM 3 importer so the
VQE contract tests always run under python -m pytest tests/. These remain
optional for SDK users; the base package does not require Qiskit.
For comprehensive documentation, including detailed API reference, Identity Management (list_api_keys, get_audit_logs), and advanced configuration options, please refer to the official Commutator Studios Documentation.
License
Copyright © 2026 Commutator Studios GmbH. All rights reserved.
Metadata
Release files for commutator-sdk 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| commutator_sdk-0.3.2.tar.gz | 56.1 kB | Without provenance | Details for commutator_sdk-0.3.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| commutator_sdk-0.3.2-py3-none-any.whl | Python 3 | none | any | Details for commutator_sdk-0.3.2-py3-none-any.whl |
Total release size: 96.4 kB
Release files / commutator_sdk-0.3.2.tar.gz
| Download URL | commutator_sdk-0.3.2.tar.gz |
|---|---|
| Size | 56.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a947be39b089081f85fdf4193c7eeb31cab098beaacf958e47f8e37dc5061fe8
|
|
BLAKE2b-256 checksum How to use checksums |
cb4337528ed8f1dd7c699f196f769d9aaef001fa95e98837d48bad3e28ac4633
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / commutator_sdk-0.3.2-py3-none-any.whl
| Download URL | commutator_sdk-0.3.2-py3-none-any.whl |
|---|---|
| Size | 40.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
aade0fc4d952de26a1e0dd71dae8fb9b54dbd8321c86fef899da32688a97214c
|
|
BLAKE2b-256 checksum How to use checksums |
6fad4ccc427ed45a448ee5d1500e754f50894f767631c59473cee84486d54bae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Security for commutator-sdk 0.3.2
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.