AQTProvider
Runtime integration for direct access to AQT trapped-ion quantum processors via the arnica cloud.
API Reference: qbraid.runtime.aqt
Overview
The qbraid.runtime.AQTProvider provides direct access to
Alpine Quantum Technologies (AQT) trapped-ion quantum systems through the
arnica cloud. You can write quantum circuits in
Qiskit (or any other qBraid-supported framework); the provider
transpiles them to AQT’s native gate set and executes them on AQT hardware such as the IBEX QPU,
all from within the qBraid Runtime framework.
AQT devices are also available through the qBraid platform — accessed with
QbraidProvider and billed in qBraid credits — as well as through Amazon
Braket and Open Quantum. Each is a separate access point with its own device
ids.
Getting started
Before you begin, make sure you have:
- An AQT arnica account with machine-to-machine (OIDC client-credentials) access.
- Your arnica client ID and client secret.
- Python >= 3.10
Set up the qBraid-SDK
Install qBraid with the aqt extra from PyPI using pip:
pip install 'qbraid[aqt]'This installs the required dependencies: aqt-connector and qiskit.
Note: The qBraid-SDK requires Python 3.10 or greater. You can check your
Python version by running python --version from the command line.
Authentication
The AQTProvider authenticates to the arnica cloud non-interactively using OIDC client
credentials (machine-to-machine) — the interactive device/login flow is never triggered. Provide
your credentials via environment variables:
export AQT_CLIENT_ID="your-client-id"
export AQT_CLIENT_SECRET="your-client-secret"Then initialize the provider:
from qbraid.runtime.aqt import AQTProvider
provider = AQTProvider()You can also pass credentials — or a pre-obtained access token — directly instead of using environment variables:
# client-credentials
provider = AQTProvider(client_id="your-client-id", client_secret="your-client-secret")
# or a pre-obtained bearer token
provider = AQTProvider(access_token="your-access-token")List available devices
Use the AQTProvider to list the devices to which you have access:
from qbraid.runtime.aqt import AQTProvider
provider = AQTProvider()
devices = provider.get_devices()
print(devices)AQT devices are addressed by a "<workspace>/<resource>" identifier. Get a specific device by its id:
device = provider.get_device("<workspace>/<resource>")
print(device.status())
# <DeviceStatus.ONLINE>Use get_devices() to discover the "<workspace>/<resource>" ids you have access to — for
example, the IBEX QPU is exposed under its arnica workspace and resource.
Submitting jobs
The AQTProvider accepts circuits written in any qBraid-supported framework. device.run()
transpiles the circuit to AQT’s native basis (RZ, R, RXX) via the qiskit -> aqt_connector
conversion, then submits it.
AQT enforces per-job limits: up to 2000 shots per job and up to 2000 operations (gates) per circuit. Jobs that exceed either limit are rejected. The IBEX QPU provides 12 qubits; a circuit wider than the device is rejected before submission.
Create a circuit
from qiskit import QuantumCircuit
# Bell state circuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()Run a job
Use device.run() to transpile and submit a circuit:
from qiskit import QuantumCircuit
from qbraid.runtime.aqt import AQTProvider
provider = AQTProvider()
device = provider.get_device("<workspace>/<resource>")
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
job = device.run(circuit, shots=1000)
print(f"Job ID: {job.id}")Batch submission
Submit multiple circuits in a single call. All circuits are bundled into one arnica job:
from qiskit import QuantumCircuit
from qbraid.runtime.aqt import AQTProvider
provider = AQTProvider()
device = provider.get_device("<workspace>/<resource>")
qc1 = QuantumCircuit(1)
qc1.h(0)
qc1.measure_all()
qc2 = QuantumCircuit(2)
qc2.h(0)
qc2.cx(0, 1)
qc2.measure_all()
job = device.run([qc1, qc2], shots=500)
print(f"Job ID: {job.id}")When submitting a list of circuits, all are executed as a single batch job on arnica. The returned measurement counts will be a list of dictionaries, one per circuit.
Retrieving results
result = job.result()
# Measurement counts (little-endian: qubit 0 is the rightmost bit)
print(result.data.get_counts())
# {'00': 512, '11': 488}
# Job metadata
print(f"Device: {result.device_id}")
print(f"Job ID: {result.job_id}")
print(f"Success: {result.success}")Check job status
from qbraid.runtime.enums import JobStatus
status = job.status()
print(status)
# <JobStatus.COMPLETED>Cancel a job
job.cancel()Cancellation targets queued or ongoing jobs. Jobs already in a terminal state
(COMPLETED, FAILED, CANCELLED) cannot be cancelled.
Execution time
Retrieve the wall-clock run time (in seconds) for a completed job:
print(f"Execution time: {job.execution_time_s()} seconds")execution_time_s() is derived from the arnica timing_data as the ongoing
→ finished span (the time the job spent running, excluding queue wait). It
returns None until the job has completed, and raises AQTJobError if a
completed job’s timing data is incomplete.
Configuration options
The device.run() method accepts the following keyword arguments:
| Parameter | Type | Default | Description |
|---|---|---|---|
shots | int | 100 | Number of measurement shots per circuit (max 2000). |
name | str | "qbraid" | Optional human-readable job label. |
Credentials are configured via environment variables:
| Variable | Description |
|---|---|
AQT_CLIENT_ID | OIDC client ID for the arnica client-credentials flow. |
AQT_CLIENT_SECRET | OIDC client secret for the arnica client-credentials flow. |
Full example
A complete end-to-end workflow submitting a GHZ state to an AQT device:
from qiskit import QuantumCircuit
from qbraid.runtime.aqt import AQTProvider
# 1. Initialize provider (reads AQT_CLIENT_ID / AQT_CLIENT_SECRET from the environment)
provider = AQTProvider()
# 2. Get a device by its "<workspace>/<resource>" id
device = provider.get_device("<workspace>/<resource>")
print(f"Device status: {device.status()}")
# 3. Define a GHZ state circuit
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure_all()
# 4. Submit the job
job = device.run(circuit, shots=1000)
print(f"Submitted job: {job.id}")
# 5. Retrieve results
result = job.result()
print(f"Counts: {result.data.get_counts()}")
# Expected output (approximate): {'000': ~500, '111': ~500}Related links
Thanks for your feedback.

