open-standards/wai/wai-quantum-qpu/bring-your-own-quantum.md
Transaction Science 065840b2d7
Some checks failed
WAI operation catalogue / does this change touch it (push) Successful in 22s
wai-quantum clippy / does this change touch it (push) Successful in 26s
wai-quantum command line / does this change touch it (push) Successful in 35s
wai-quantum contract / does this change touch it (push) Successful in 21s
wai-quantum docs, course and locales / does this change touch it (push) Successful in 22s
wai-quantum for JavaScript / does this change touch it (push) Successful in 20s
wai-quantum resource estimation / does this change touch it (push) Successful in 24s
wai-quantum other formats / does this change touch it (push) Successful in 26s
wai-quantum OpenQASM reader / does this change touch it (push) Successful in 17s
wai-quantum for Python / does this change touch it (push) Successful in 16s
wai-quantum extension points / does this change touch it (push) Successful in 19s
wai-quantum error correction and mitigation / does this change touch it (push) Successful in 23s
wai-quantum pulse and dynamics / does this change touch it (push) Successful in 22s
wai-audit collector and player integration / does this change touch it (push) Successful in 3m29s
wai-quantum editors / does this change touch it (push) Successful in 2m26s
wai-quantum variational and algorithm library / does this change touch it (push) Successful in 25s
wai-quantum verdicts and repairs / does this change touch it (push) Successful in 23s
wai-quantum studio and desktop / does this change touch it (push) Successful in 29s
wai-quantum service / does this change touch it (push) Successful in 30s
wai-sink-android native sink library / does this change touch it (push) Successful in 1m24s
wai-sink-swift native sink package / does this change touch it (push) Successful in 1m22s
wai-quantum views in agent hosts / does this change touch it (push) Successful in 1m25s
WAI Studio / does this change touch it (push) Successful in 1m18s
wai-quantum service / service energy · linux packages (push) Failing after 11s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 10s
WAI examples / WAI examples · does this change touch them (push) Successful in 15s
wai-quantum wasmQ / does this change touch it (push) Successful in 10s
wai-quantum contract / the policy is linked, and the deprecations page reads (push) Successful in 11s
wai-quantum docs, course and locales / the Studio's words in every locale · linux (push) Successful in 13s
WAI operation catalogue / the catalogue and every door · linux (push) Failing after 3m52s
wai-quantum other formats / the set under wasm32-wasip2 (wasmtime) (push) Successful in 2m17s
wai-quantum clippy / clippy, warnings denied, every feature set · linux (push) Successful in 5m4s
wai-quantum OpenQASM reader / corpus under wasm32-wasip2 (wasmtime) (push) Successful in 1m8s
wai-quantum extension points / the registry under wasm32-wasip2 (wasmtime) (push) Successful in 3m6s
wai-quantum docs, course and locales / the course and the command line's languages · linux (push) Successful in 7m43s
wai-quantum OpenQASM reader / reader and corpus · linux (push) Successful in 6m9s
wai-quantum other formats / readers, writers and the set · linux (push) Successful in 8m22s
wai-quantum for Python / python · linux (push) Successful in 6m17s
wai-quantum pulse and dynamics / reader, simulator and pulse jobs · linux, release (push) Successful in 2m29s
wai-quantum contract / API compatibility · linux (push) Successful in 10m27s
wai-quantum extension points / the registry and the example · linux (push) Successful in 6m39s
wai-quantum pulse and dynamics / reader, simulator and pulse jobs under wasm32-wasip2 (wasmtime) (push) Successful in 2m24s
wai-quantum error correction and mitigation / codes, decoders, texts and mitigation · linux, release (push) Successful in 6m12s
wai-quantum for JavaScript / javascript · linux (push) Successful in 11m28s
wai-quantum resource estimation / estimation and calibration · linux, release (push) Successful in 13m21s
wai-audit collector and player integration / collector · linux (push) Successful in 2m48s
wai-quantum verdicts and repairs / the intent set and the verdict under wasm32-wasip2 (wasmtime) (push) Successful in 3m2s
wai-quantum editors / editors · linux (push) Successful in 4m20s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Successful in 59s
wai-quantum contract / schemas and the committed tool lists · linux (push) Successful in 16m11s
wai-quantum verdicts and repairs / verdicts, repairs and the intent set · linux (push) Successful in 4m46s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux, release (push) Successful in 4m5s
wai-quantum studio and desktop / studio · browser (push) Successful in 6m49s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 8m20s
wai-quantum service / service · linux (push) Successful in 11m47s
wai-quantum views in agent hosts / views · the page and its engine (push) Successful in 9m50s
wai-quantum views in agent hosts / views · a scripted host (push) Successful in 11m14s
wai-quantum command line / command line · linux (push) Successful in 26m22s
WAI Studio / Studio in WebKit · linux (push) Failing after 23m36s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (push) Failing after 1h5m32s
wai-quantum extension points / the registry and the example · linux-arm64 (push) Successful in 7m19s
wai-quantum pulse and dynamics / the same bits · linux-arm64 (push) Successful in 7m28s
wai-quantum pulse and dynamics / the same bits · macos (push) Successful in 1m37s
wai-quantum for Python / python · macos (push) Successful in 4m24s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Failing after 18m39s
wai-quantum command line / command line · macos (push) Successful in 5m9s
wai-quantum editors / editors · macos (push) Successful in 1m52s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Successful in 3m45s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (push) Successful in 6m53s
wai-quantum studio and desktop / desktop app · macos (push) Successful in 4m16s
wai-quantum service / service · macos (push) Successful in 9m30s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Successful in 14m42s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Successful in 9m55s
WAI Studio / Studio in Chromium and Firefox · macos (push) Failing after 11m30s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Failing after 45m47s
wai-quantum wasmQ / profile, engines, reference modules, adversarial, vectors · linux (push) Has been cancelled
wai-quantum wasmQ / profile, engines, reference modules, adversarial, vectors · macos (push) Has been cancelled
wai-quantum wasmQ / the reference modules rebuild to their modules of record · linux (push) Has been cancelled
wai-quantum wasmQ / interpreter and vectors under wasm32-wasip2 (wasmtime) (push) Has been cancelled
wai-quantum studio and desktop / desktop app · windows (push) Has been cancelled
WAI examples / WAI examples · portable · linux (push) Has been cancelled
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (push) Has been cancelled
WAI examples / WAI examples · android-app · linux-arm64 (push) Has been cancelled
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Has been cancelled
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Has been cancelled
WAI Quantum: a sixth basis, rz sx x cz rx rzz, for the fractional rx and rzz; sampler-v2 pinned by its calibration's values
A processor that takes rx(θ) and rzz(θ) runs an angle between two qubits in
one two-qubit gate where rz sx x cz takes two cz.

- quantum_toolchain::native::Basis::RzSxXCzRxRzz (label rzsxxczrxrzz): a
  controlled phase, a run of them on one pair, and cx·p(θ)·cx with only Z
  rotations between are each one rzz; h·p(θ)·h is one rx, ry one rx between
  frames; rx(π/2) and rx(π) are sx and x. rzz is held to 0 < θ ≤ π/2, the
  range the service publishes, an angle outside folded in by Z⊗Z and an X on
  either side; the check before sending refuses an rzz of no turn or past a
  quarter turn and an rx with a phase. A three-qubit Fourier transform takes
  three rzz where rz sx x cz takes six cz.
- Proved by the engine's equivalence check (controlled phases each side of
  zero and past a quarter turn, the folds, rotations between qubits, X and Y
  rotations, the transform, random programs, none with more two-qubit gates
  than in rz sx x cz); six native vectors pinned and proved, four refusals.
- layout::native_in and place_in place a program in the basis its device's
  client compiles to; on a target of rz sx x cz rx rzz, rx and rzz are costed
  as themselves. native_of still reads such a target as rz sx x cz.
- sampler-v2 compiles to it with the setting basis=rzsxxczrxrzz, only where
  basis_gates list rx and rzz, on pairs both maps list; tested against the
  fake built from the service's own answers, which holds every rzz to the
  published range. The protocol (§4, §8.4) carries the set as a built-in
  client's: no description is compiled to it, so no provider is sent one;
  both verifiers read it in compiled.basis.
- The pin, by values: the backend's snapshot was dated anew three times in
  three and a half hours on 2026-11-12 with no value a placement reads
  changed (only thresholds and initialisation errors), so a date comparison
  would refuse nearly every job that waits. The placement now names the hash
  of the values it read (Target::values_hash), the client states the values
  in force when the job began running (Stated::ran_under), and a job whose
  values differ is refused, in the sending process and in a collecting one.

Workflow pins: the two engine tests in the registry workflow, the sampler-v2
binary's count (10) and its new test in the qpu workflow.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 23:27:59 -05:00

363 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bring your own quantum
WAI gives you the engine, the free job service and the verifier at no cost.
It does not sell time on anyone's hardware, and it never pays for yours. You
bring your own quantum hardware: a device on your bench, an on-premises
system, an account with a provider, or a simulator you trust. Every surface
then treats a run on it as it treats a WAI run:
- it is **planned**: the circuit is compiled exactly to the device's own gates
and connectivity, and the compiled program is checked against the circuit by
simulation before anything is sent;
- its **cost is shown before it is submitted**, and a run that is not free
(or whose cost is unknown) runs only when you confirm it;
- its counts are **sealed in a receipt** with your key, which the existing
verifier checks.
Your credentials stay with you, in the operating system's keychain. They never
go to a browser page, a log, a receipt, or the hosted service.
## What is free
```sh runnable
wai-quantum providers free
```
lists what anyone can use at no cost:
- the engine's own methods on your machine, each with the most qubits it holds
in a job's memory;
- the free job service, `https://wai.transaction.science/quantum-jobs`, with no
account (its limits are per client; `GET …/v1` states them);
- each of your providers whose own description states free use, with the
limits it states. No provider is named in WAI's code: a provider says what
it offers, about itself.
## Adding a provider
A provider is one of six kinds:
| kind | what it is | the credential |
|---|---|---|
| `http` | any provider of the [open provider protocol](../extensions/quantum-providers.md) at an HTTPS URL | `Authorization: Bearer` |
| `process` | any program on your machine that speaks the protocol on its standard input and output | its environment (`WAI_PROVIDER_CREDENTIAL`) |
| `sampler-v2` | a Sampler V2 job service (OpenQASM 3 on physical qubits, rz sx x cz) | an API key, exchanged for a bearer token |
| `prx-circuits` | a circuit service of phased-X and CZ instructions, star devices (qubits round a computational resonator, reached by `move`) among them | the token you generate in the service's dashboard |
| `native-turns` | a native-gate service with angles in turns (gpi gpi2 zz, or gpi gpi2 ms where the backend, or its noise model's device, runs only ms) | an API key |
| `cloud-tasks` | a cloud service of quantum tasks, on your own account, its results in your own storage bucket | your account's keys, `id:secret` or `id:secret:token`, or its usual environment variables |
```sh runnable
# A program of your own, or the reference provider, on this machine:
wai-quantum providers add lab --kind process -- wai-quantum providers reference --stdio
# A provider at a URL, its credential read from standard input into the keychain:
wai-quantum providers add cloud --kind http --endpoint https://quantum.example/provider --credential-stdin < token.txt
# A built-in protocol, its settings beside it, its credential in the keychain:
wai-quantum providers add mine --kind sampler-v2 --set crn=… --set backend=… --credential-stdin < key.txt
# A cloud service of tasks: a device by its name there, your own results bucket and your own keys:
wai-quantum providers add tasks --kind cloud-tasks --set region=us-east-1 --set device=… --set bucket=your-results-bucket --credential-stdin < keys.txt
# Or a credential read from an environment variable whenever it is used, kept nowhere:
wai-quantum providers add turns --kind native-turns --set backend=simulator --credential-env MY_TURNS_KEY
```
A credential is never given on a command line (where other users of the
machine could read it). `--credential-stdin` keeps it:
- on macOS, in the keychain, through the system `security` tool;
- on Linux, in the desktop secret service, through `secret-tool`, when it is
installed and answers;
- elsewhere (Linux with no secret service, Windows), in a file only you can
read (`~/.config/wai/quantum-provider-credentials/NAME`, mode 0600), and
every listing says so. `WAI_QUANTUM_CREDENTIALS=file` chooses the file;
`WAI_QUANTUM_CREDENTIALS=keychain` accepts nothing but the keychain.
The list itself (`~/.config/wai/quantum-providers.json`, or the file
`$WAI_QUANTUM_PROVIDERS` names) holds no credential: only each provider's
kind, endpoint or command, non-secret settings, and where its credential is.
A setting whose name looks like a credential (`token`, `key`, `secret`, …) is
refused. The built-in kinds still read their environment variables
(`WAI_QPU_SAMPLER_API_KEY` and the rest, in the [README](README.md)) when no
credential is kept for them.
```sh runnable
wai-quantum providers list # each provider, and where its credential is
wai-quantum providers describe lab # its qubits, gates, connectivity, calibration and prices
wai-quantum providers test lab # the protocol's conformance vectors; jobs only when free, or with --yes
wai-quantum providers remove turns # and the credential kept for it
```
## Running on it
```sh runnable
wai-quantum run bell.qasm --provider lab --dry-run # the plan, the check and the estimate; nothing sent
wai-quantum run bell.qasm --provider lab # free: it runs
```
On a provider that charges (here `cloud`, reached with your own account):
```sh norun=account
wai-quantum run bell.qasm --provider cloud # not free: refused, with the estimate (exit 3)
wai-quantum run bell.qasm --provider cloud --yes # you confirmed it: it runs
wai-quantum run bell.qasm --provider cloud --json > job.json && wai-quantum verify job.json
```
A run on a provider asks for counts (`--shots`, 1024 by default) of a program
whose measurements all come at the end and whose every angle is a dyadic
multiple of 2π (`pi/4`, `3*pi/8`, …), so it compiles exactly. A job that asks
for expectation values, amplitudes, a noise model or one of the engine's
methods is refused; those are the engine's.
An agent has the same through `wai-quantum mcp`:
- `providers_list` lists your providers (and, with `free: true`, what is free);
- `provider_estimate` is the dry run;
- `run_on_provider` runs, and says in its description that it can spend your
money. It refuses a run that is not free unless `confirm_cost: true`, which
an agent sets only after you have seen the estimate and agreed.
The desktop app lists your providers under **Your hardware**, asks for the
estimate first, and shows a dialog before a run that is not free. The
browser Studio cannot: a browser tab must not hold a credential, so there the
switch says that such runs go through the desktop app or the command line.
The hosted job service never routes a job to a provider and never takes a
credential; a request that names a provider is refused there.
## When the queue is long
A device's queue can take days, and nothing has to stay running for it. A job
is written down before it is sent, in `provider-jobs` beside your registry
(readable only by you, with no credential in it), and the provider's id beside
that as soon as the provider gives one.
```sh norun=account
wai-quantum run bell.qasm --provider lab --no-wait # sends it, and answers with its handle
wai-quantum providers jobs # every job recorded here, and where it last stood
wai-quantum providers collect pj-0123456789abcdef # asks, and seals its result when it has one
wai-quantum providers cancel pj-0123456789abcdef
```
A plain `run` waits two hours and then stops waiting, with the job left at the
provider and its handle on the screen. Only your asking cancels a job. If the
command, the terminal or the machine stops, the job goes on, and `collect`
picks it up: exit 0 done, 1 ended otherwise, 2 still at the provider, 75 could
not ask, which says nothing of the job. An agent has the same in
`get_provider_job`, `cancel_provider_job` and `list_provider_jobs`, and the job
from `run_on_provider` is the same job.
The counts are read against the program that was sent, and the receipt states
that program and what the provider said when it was sent, whatever its
calibration has become since. A request that did not complete may have reached
the provider, so it is never sent again, since that could be a second bill: the
record says so, and you look in the provider's own list. A provider you run as
a local process has to keep its jobs itself, or they end with it.
## The protocol, and the reference as your template
The [open provider protocol](../extensions/quantum-providers.md) is six
operations as JSON messages, over HTTP or a local process: `describe`
(native gates, connectivity, qubits, durations, a calibration snapshot id with
optional per-qubit and per-pair errors, and the billing: `free`, a unit and
its price, or not free with no price set, so that a job's cost is unknown and
it runs only when you confirm it), `estimate`, `submit`, `status`, `result`
(counts keyed by classical bits) and `cancel`. A program travels in your
device's own gates, every angle an exact fraction of a turn, with the same
program as OpenQASM 3 beside it.
The reference provider is the protocol around WAI's exact simulator:
```sh runnable
wai-quantum providers reference --stdio # on standard input and output
wai-quantum providers reference --help-args # its device: qubits, basis, connectivity, a price, a readout error
```
```sh norun=server
wai-quantum providers reference --http 127.0.0.1:8090 # over HTTP, until stopped
```
To bring a device, copy [`src/reference.rs`](src/reference.rs): keep the
message handling, the checks of a program against the device, and the two
servers, and replace `Reference::simulate` with your device's run (and
`describe` with your device's description). Then hold it to the vectors:
```sh norun=account
wai-quantum providers add mine --kind process -- ./my-provider --stdio # your own provider's program
wai-quantum providers test mine
```
A device whose gates are a phased `X` rotation, a `Z` rotation and `XX(θ)`,
reached through a service with an interface of its own (its angles in units of
π, say), is brought the same way. Its provider describes `"native_gates":
["prx", "rz", "xx"]` and is sent programs in `prxrzxx`, which it writes in the
service's terms: `prx(t, p)` as the rotation by 2t and the phase 2p in units
of π (0 to 1, and 0 to 2), `rz(t)` as 2t (less 2 past 1, where the service
takes −1 to 1), and `xx(t)`, which is exp(−iπt·X⊗X), as 2t (0 to ½: every
`cz` arrives as `xx(¼)`, so ½). Each angle is a dyadic fraction and stays
exact as a number of that form. The provider turns off whatever the service
would compile, remap or mitigate, and says what it sent in the answer's
`execution`; and where the service deletes a result a day after it is read, it
keeps each result as it reads it. A sign or a unit wrong in its `xx` leaves the
probe's counts as they are: run a circuit whose outcome turns on the entangling
gate's phase, as the certification's do, before trusting other results. A star
device describes its `resonators` and the `moves` into them, and is sent
`move` in `prxcz` or `rzsxxcz`.
The first job on a new provider is the probe, an `X` on qubit 0 whose counts
must all land on `…01`. It settles the bit order before any other result is
trusted.
## Programs that call WebAssembly between gates
A wasmQ envelope ([quantum-wasmq](../extensions/quantum-wasmq.md)) calls its WebAssembly
modules between gates: a decoder between a syndrome and its correction, a planner between
loading atoms and moving them. A provider's program is a fixed sequence of native gates
measured at the end, so it cannot carry that, and `run ENVELOPE.wai --provider NAME` is
refused; the envelope runs on this machine, its quantum part simulated. Nothing about
bringing your own quantum changes for it. What a hardware run of such a program would
need, and what replays from its record, is §7 of that extension.
## What the receipt proves, and what it does not
A processor's result is labelled `measured`. A result from a provider's
simulator or emulator is labelled `simulated`, since no device measured it,
and `approximate` too when the provider says its simulator is. Its receipt
binds the request, the provider's name, kind and protocol, the device and its
provenance, the hash of the provider's own description, the calibration
snapshot, the compiled program's text and its hash, the counts, the cost (the
estimate, the charge, and whether you confirmed it), and the counts set beside
the circuit's exact distribution with the distance between them.
It also says two things a later receipt could not add:
- **Where the counts come from** (`counts_source`): tallied from the device's
records, one a shot (`shots`); the provider's own counts (`vendor_counts`);
or rebuilt from probabilities (`probabilities`). Rebuilt counts are derived,
not shot records. `native-turns` reads its job's shot records where the
service lists them (as a noisy simulation does), else the service's own
counts, and rebuilds them only from probabilities, as on an ideal
simulator; it holds every form the job lists to the others, and the shots
the service flags as leaked are counted as read, and their number sealed
beside them (`leakage`). A result the service narrows to the qubits up to
the last its gates touch is read with the qubits above it 0. A job the
service finished whose result does not read (keys of no form it writes,
forms that disagree, or a width it does not write) ends `failed`, with the
reason, and is not asked again. `cloud-tasks` reads a task's rows and rebuilds only when its
result has none.
- **What was set at the provider** (`execution`), built from the very request
the client sends: each of mitigation, twirling, dynamical decoupling,
remapping and optimisation as `off`, `on`, or `default` when the request sets
nothing for it, and whether the gates were to run as written. `sampler-v2`
turns decoupling and twirling off; `native-turns` turns debiasing off, and
sends its simulator, under a device's noise model, the job's seed, so a
noisy simulation is the same at each run of that seed, and its note ends
with what the service says it compiled (precision, gate basis, version) and
whether the circuit it lists as compiled is the one sent;
`cloud-tasks` puts a processor's gates in the service's verbatim box;
`prx-circuits` pins the job to the calibration set it was compiled against
and sends dynamical decoupling disabled, with the service's other modes as it
wants them. A provider of the open protocol states its own (§5.5 of the
protocol), and a wrapper around another service must.
`wai-quantum verify` checks the seal and every rule a receipt keeps, and names
each one it breaks (the protocol's §8.4); `--json` gives the verdict as data.
It proves that your key signed this result for this request: what it says
your host received from the provider and device it names, sent and checked
is your host's word, and the counts are the provider's. It does not prove
that the device ran that program, or ran anything. The counts are not
reproducible by recomputation; the same job run again gives other counts. The
distance from the exact distribution tells you how far they are from what the
circuit gives: a distance well above what the shots alone leave is the
device's or the simulator's error, or a program not run as sent.
A receipt seals the provider's id for the job. For `cloud-tasks` that is the
task's identifier, which names your account's number: sharing the receipt
shares it.
## A first run on a phased-X circuit service's mock quantum computer
A `prx-circuits` service may list, beside each quantum computer, a mock of it:
the same name with `:mock` after it, a server with no quantum hardware that
answers random bits. It checks the whole wire (your token, the device's
description, the job, the cancel, the counts) before any processor runs
anything. Its results are sealed as `simulated`, never as `measured`.
1. In the service's dashboard, generate your token. Generating it again makes
the old one stop working.
2. Keep it where `wai-quantum` keeps every credential, read from standard input
(paste it, then press Ctrl-D), never from the command line:
```sh norun=account
wai-quantum providers add mock --kind prx-circuits --set qc=NAME:mock --credential-stdin
```
On macOS that is the keychain: an item whose service is
`wai-quantum-provider` and whose account is the provider's name, here
`mock`. On Linux it is the desktop secret service, and elsewhere a file only
you can read; `wai-quantum providers list` says which. A token you keep
already, under another item of the keychain, goes over without being shown:
```sh norun=account
security find-generic-password -s YOUR-ITEM -w | wai-quantum providers add mock --kind prx-circuits --set qc=NAME:mock --credential-stdin
```
`WAI_QPU_PRX_TOKEN` is read instead when a provider names no credential.
3. Read the device, its calibration and its errors, with nothing sent:
```sh norun=account
wai-quantum providers describe mock # qubits, gates, pairs, and the calibration set it is under
wai-quantum providers test mock # the device and its calibration's errors; the programs only with --yes
wai-quantum targets import --provider mock --name mock # the calibration's quality metrics, kept as a target
wai-quantum run probe.qasm --provider mock --dry-run # the compile, the placement, the calibration it is pinned to
```
4. Run the probe, then the conformance programs. The service sets no price
through its interface, so each is confirmed with `--yes`; look at your
account's usage before and after to see what the mock cost:
```sh norun=account
wai-quantum run probe.qasm --provider mock --yes --json > probe.json && wai-quantum verify probe.json
wai-quantum providers test mock --yes
```
Each job is sent pinned to the calibration set the device was read under, so
the receipt's `calibration` is the set the service says it compiled the job
against, and a run is refused rather than sealed when the service says it
compiled against another. If the service recalibrated and no longer runs the
pinned set, it fails the job (calibration set not found), its record stating no
billed time, and the next run reads the current one. A
service that publishes no quality metrics for its calibration leaves the
compiler's own layout, and the plan's `placement` says so.
A `sampler-v2` backend's calibration is its published properties, read after
the device and named by their `last_update_date`: the job is placed by them,
and once it has run the client reads the properties in force when it began
running, so a job that ran under another calibration than the one it was
placed by is refused rather than sealed. On a free plan the estimate says how
many seconds of the plan's limit are left, and the receipt seals what the job
was charged, in `qpu-seconds`.
## Connecting a real device: what is yours to do
WAI ships no account and no key. To run on a real device:
1. Open an account with the provider, or set up your own device, and accept
its terms. Any price, quota or free tier is between you and the provider.
2. Mint a credential (an API key or a token) in the provider's own console.
3. Add it: `wai-quantum providers add NAME --kind … --credential-stdin`, with
the settings its kind takes (`crn` and `backend` for `sampler-v2`, and
`basis=rzsxxczrxrzz` to compile to its `rx` and `rzz` too where the backend
lists them; `qc` for
`prx-circuits`, `backend` for `native-turns`, `region`, `device` and `bucket`
for `cloud-tasks`), or `--kind http` for a provider of the open protocol.
For `cloud-tasks`, first turn the service on in your account. The bucket must
be in the device's region, its name must begin `amazon-braket-`, and its policy must let the service write to it. A name with a dot works: it is read by path. A region or a bucket that is not a name is refused when the provider is added, and this kind takes no `--endpoint`. <!-- allow-name: the prefix the service requires of a results bucket -->
On one of its simulators, `--set basis=gpizz` (or `prxcz`, or `prxrzxx` for a processor of `prx`, `xx` and `rz`) compiles to that processor basis, so you can check the gates before paying for the processor.
4. Run `wai-quantum providers describe NAME`, then `wai-quantum run
probe.qasm --provider NAME --dry-run` to see the compile and the estimate,
then the probe itself, confirmed with `--yes` if it is not free.
Nothing in WAI's tests spends money: they run against the reference provider,
whose price, when it has one, is a number in its configuration.