Documentation
Get started with QObserva in minutes. Complete guides, examples, and API reference.
Quick Start
Get QObserva running in 3 steps:
1. Install QObserva
pip install qobserva
Or install from source:
git clone https://github.com/your-org/qobserva.git
cd qobserva
pip install -e packages/qobserva_agent
pip install -e packages/qobserva_collector
pip install -e packages/qobserva_local
pip install -e packages/qobserva
2. Start QObserva
qobserva up
This starts the collector and dashboard. Open http://localhost:3000 in your browser.
3. Instrument Your Code
from qobserva import observe_run
@observe_run(
project="my_project",
tags={"sdk": "qiskit", "algorithm": "bell_state"}
)
def my_quantum_algorithm():
# Your quantum code here
result = execute_circuit()
return result
Always include tags={"sdk": "..."} in your decorator for reliable adapter selection. Supported values: "qiskit", "braket", "cirq", "pennylane", "pyquil", "dwave".
Python Version Compatibility
Recommended: Python 3.12 (supports all 6 SDKs)
| SDK | Python Version | Notes |
|---|---|---|
| Qiskit | 3.10+ | Works with Python 3.10-3.14 |
| Braket | 3.10 - 3.13 | Python 3.14+ NOT supported (Braket SDK uses Pydantic v1) |
| Cirq | 3.10+ | Works with Python 3.10-3.14 |
| PennyLane | 3.10+ | Works with Python 3.10-3.14 |
| pyQuil | 3.10 - 3.12 | Python 3.13+ NOT supported (PyQuil 4.x uses PyO3 0.20.3) |
| D-Wave | 3.10+ | Works with Python 3.10-3.14 |
SDK Examples
QObserva works with all major Python quantum SDKs. Here are quick examples:
Qiskit
from qobserva import observe_run
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler
@observe_run(
project="qiskit_test",
tags={"sdk": "qiskit", "algorithm": "bell_state"}
)
def run():
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
sampler = StatevectorSampler()
return sampler.run([qc], shots=1024).result()
Requirements: qiskit>=1.2.0
Amazon Braket
from qobserva import observe_run
from braket.circuits import Circuit
from braket.devices import LocalSimulator
@observe_run(
project="braket_test",
tags={"sdk": "braket", "algorithm": "bell_state"}
)
def run():
bell = Circuit().h(0).cnot(0, 1)
device = LocalSimulator()
return device.run(bell, shots=1024).result()
Requirements: amazon-braket-sdk>=1.80.0, Python 3.13 or earlier
Cirq
from qobserva import observe_run
import cirq
@observe_run(
project="cirq_test",
tags={"sdk": "cirq", "algorithm": "bell_state"},
measurement_key="result" # Required!
)
def run():
q0, q1 = cirq.LineQubit(0), cirq.LineQubit(1)
circuit = cirq.Circuit()
circuit.append(cirq.H(q0))
circuit.append(cirq.CNOT(q0, q1))
circuit.append(cirq.measure(q0, q1, key='result'))
return cirq.Simulator().run(circuit, repetitions=1024)
Requirements: cirq>=1.3.0. Note: Must specify measurement_key parameter.
PennyLane
from qobserva import observe_run
import pennylane as qml
@observe_run(
project="pennylane_test",
tags={"sdk": "pennylane", "algorithm": "bell_state"}
)
def run():
dev = qml.device("default.qubit", wires=2, shots=1024)
@qml.qnode(dev)
def circuit():
qml.Hadamard(wires=0)
qml.CNOT(wires=[0, 1])
return qml.counts()
return circuit()
Requirements: pennylane>=0.40.0
pyQuil
from qobserva import observe_run
from pyquil import Program, get_qc
from pyquil.gates import H, CNOT, MEASURE
@observe_run(
project="pyquil_test",
tags={"sdk": "pyquil", "algorithm": "bell_state"}
)
def run():
program = Program()
ro = program.declare("ro", "BIT", 2)
program += H(0)
program += CNOT(0, 1)
program += MEASURE(0, ro[0])
program += MEASURE(1, ro[1])
qc = get_qc("2q-qvm")
program.wrap_in_numshots_loop(1024)
return qc.run(program)
Requirements: pyquil>=4.0.0, Python 3.12 or earlier, Rust/Cargo
D-Wave
from qobserva import observe_run
import dimod
@observe_run(
project="dwave_test",
tags={"sdk": "dwave", "algorithm": "qubo"}
)
def run():
Q = {(0, 0): -1, (0, 1): 1, (1, 2): 1}
bqm = dimod.BinaryQuadraticModel.from_qubo(Q)
return dimod.ExactSolver().sample(bqm)
Requirements: dimod>=0.12.20
API Reference
@observe_run Decorator
@observe_run(
project: str, # Project name (e.g., "my_project")
tags: dict, # Tags dict (must include "sdk")
benchmark_id: str = None, # Optional benchmark identifier
benchmark_params: dict = None, # Optional benchmark parameters
measurement_key: str = None # Required for Cirq
)
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
project |
str | Yes | Project name for grouping runs (e.g., "qiskit_test") |
tags |
dict | Yes | Tags dict. Must include "sdk" key. Recommended: "algorithm", "test" |
benchmark_id |
str | No | Benchmark identifier for comparison |
benchmark_params |
dict | No | Algorithm-specific metrics (e.g., energy values, success rates) |
measurement_key |
str | Cirq only | Measurement key matching cirq.measure() key |
Common Use Cases
Algorithm Tagging
Tag your runs with algorithm names to enable algorithm-specific dashboards:
tags={
"sdk": "qiskit",
"algorithm": "vqe", # Enables algorithm comparison
"test": "variational"
}
Common algorithm tags: "bell_state", "grover", "vqe", "qaoa", "qubo", "qft"
Benchmark Parameters
Include algorithm-specific metrics for better analysis:
@observe_run(
project="vqe_experiment",
tags={"sdk": "qiskit", "algorithm": "vqe"},
benchmark_id="h2_ground_state",
benchmark_params={
"energy": -1.137,
"convergence_iterations": 10
}
)
Viewing Results
After running your instrumented code:
- Open
http://localhost:3000in your browser - Filter by project name (e.g.,
qiskit_test) - View run details, compare runs, and analyze trends
More Documentation
For comprehensive guides, examples, and troubleshooting:
- Testing Guide: Complete setup, deploy, and viewing instructions
- Examples: Full SDK examples with proper project names and tags
- API Reference: Detailed decorator and adapter documentation
- Troubleshooting: Common issues and solutions