open-standards/wai/extensions/quantum-providers.md
Transaction Science 15b3deac34 wai-quantum-qpu: a provider's described calibration places the program
When a provider's describe answer states errors per qubit or per pair, the
host reads it as a device target and places the program on the qubits and
routes most likely to succeed (engine::targets::layout::place), in the
device's own gates; otherwise the compiler's own layout is kept. The program
is checked against the circuit on the device's connectivity before it is
sent, as before. The plan and the sealed result's compiled block say how it
was placed, with the target's hash and the expected success beside the
fewest-swaps layout's.

The provider protocol now states the durations field's form, and that a
client may place by the described calibration.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 23:44:27 -04:00

16 KiB
Raw Permalink Blame History

WAI Extension: Quantum Providers (wai.quantum.provider/1)

Status: Draft. Client, reference provider and conformance checker: wai-quantum-qpu (src/open_provider.rs, src/reference.rs, src/conformance.rs); vectors: wai-quantum-qpu/conformance/provider-v1.json. The engine's side of a provider job: wai-quantum/src/engine/provider.rs.

Keywords MUST, MUST NOT, SHOULD and MAY are RFC 2119/8174.

0. What this extension adds

Bring your own quantum. WAI provides the engine, the free job service and the verifier at no cost, and never pays for or resells time on anyone's hardware. A person connects their own quantum hardware, provider accounts, on-premises devices or simulators, and every surface treats a provider's result as it treats a WAI result: planned, its cost shown before it is submitted, checked, and sealed in a receipt.

This text is the protocol a device speaks so that it can be brought without a client written for it: JSON messages, one request and one answer at a time, over HTTP or to a local process (§2). Six operations (§5) describe the device, estimate a job, submit it, follow it, read its counts and cancel it. A program travels in the device's own native gates, with every angle an exact fraction of a turn (§4), so the program the device runs is the one the client compiled and checked.

A provider is the program or service that answers the messages. A device is what it runs programs on: a processor, an emulator or a simulator. A client is what sends the messages; a host is the client's process, which holds the person's credential and signing key (the command line, the desktop app).

1. Principles

  1. The credential stays with the person. A host keeps a provider's credential in the operating system's keychain (or, where there is none, a file only its owner can read, labelled as such) and sends it only to that provider (§2). A credential MUST NOT appear in a browser page, a log, a receipt, a command line, an answer the host prints, or the hosted job service. The job service never routes a job to a provider and never takes a credential: a request that names a provider is refused there.
  2. Cost before submit. A client MUST show a job's estimate (§5.2) before it submits the job, and MUST NOT submit a job that is not free without the person's explicit confirmation (§7). An unknown cost is not free.
  3. Exact programs. A client compiles a circuit exactly to the device's native gates and connectivity and checks the compiled program against the circuit before sending it. Angles cross the wire exactly (§4).
  4. Measured, not recomputed. A provider's counts are sealed as measured on the device it names (§8). Nothing recomputes them.

2. Transports

Every message is a JSON object, and so is every answer. A client sends one message and reads its answer before it sends the next on the same transport.

2.1 HTTP

A message is the body of a POST to the provider's endpoint (one URL for every operation), with Content-Type: application/json. The answer is the body of a 200 response, also for an answer with "ok": false (§3). Any other status is a transport failure, not an answer.

A credential, when there is one, goes in Authorization: Bearer <credential>. A client MUST NOT send a credential over http:// to any host but this machine (localhost, a loopback address); over the network it uses https://.

2.2 A local process

The provider is a program the person names, with its arguments, started by the client without a shell. Each message is one line of JSON on the program's standard input; each answer is one line of JSON on its standard output, in order. The program MUST write nothing else to its standard output. Its standard error is its own log, and a client MAY discard it. The program runs until its standard input ends.

A credential, when there is one, is in the program's environment as WAI_PROVIDER_CREDENTIAL, never on its command line. A client SHOULD NOT pass the program another provider's credential.

3. Messages and errors

Every message carries:

field
protocol "wai.quantum.provider/1"
op describe, estimate, submit, status, result or cancel
settings optional: the person's non-secret settings for this provider (a device name, a region), passed as they are

and the operation's own fields (§5). Every answer carries "ok": true and the operation's fields, or:

{ "ok": false, "error": { "code": "not_found", "message": "no job j-17" } }

The message is for a person; it MUST NOT quote a credential. The codes:

code when
invalid the message is malformed: a field missing or of the wrong type, a program that does not read (§4), zero shots, a message without protocol
unsupported an operation the provider does not offer (cancel, estimate), or an op it does not know
unsupported_version a protocol other than this one
unauthorized no credential, or one the provider does not accept
not_found a job the provider does not hold
refused a well-formed program the device cannot run: a gate outside its basis, a qubit it does not have, a pair it does not connect, too many shots; or a result asked of a job that has not finished or was cancelled
quota the person's account cannot pay for or schedule the job
unavailable the device is offline or in maintenance
internal anything else

4. The program

estimate and submit carry a program in the device's own gates, on its physical qubits:

{
  "format": "wai.native/1",
  "basis": "rzsxxcz",
  "bits": 2,
  "gates": [
    { "gate": "rz", "qubits": [0], "turns": [[1, 2]] },
    { "gate": "sx", "qubits": [0] },
    { "gate": "cz", "qubits": [0, 1] }
  ],
  "measure": [{ "qubit": 0, "bit": 0 }, { "qubit": 1, "bit": 1 }],
  "qasm3": "OPENQASM 3.0; …"
}
  • basis is one of three gate sets, and every gate is of it:

    basis gates
    rzsxxcz rz(t), sx, x, cz
    prxcz prx(t, p), cz
    gpizz gpi(p), gpi2(p), zz(t)
  • An angle is a fraction of a full turn, [m, k] meaning m/2^k of 2π, with 0 ≤ m < 2^k and k ≤ 32, so every angle crosses the wire exactly. The gates, as operators on the named qubits, up to a global phase:

    • rz(t) = exp(−iπt·Z); sx = √X; x = X; cz = diag(1, 1, 1, −1);
    • prx(t, p) = Rz(2πp)·Rx(2πt)·Rz(−2πp);
    • gpi(p) = Rz(2πp)·X·Rz(−2πp); gpi2(p) = Rz(2πp)·Rx(π/2)·Rz(−2πp);
    • zz(t) = exp(−iπt·Z⊗Z).
  • measure gives, for each classical bit 0 … bits − 1, the physical qubit it reads at the end of the program. Every bit reads exactly one qubit, and no qubit is read twice.

  • qasm3 is the same program as OpenQASM 3 on physical qubits ($p), the prxcz and gpizz gates defined in it from the standard gates, for a provider that reads OpenQASM. It is informative: where the two differ, the gates are the program.

A provider MUST refuse (invalid) a program of another format, a gate outside its basis, an angle out of range, or a bit that reads no qubit; and (refused) a program in a basis its device does not run, or on qubits or pairs it does not have.

5. Operations

5.1 describe

No fields. The answer describes the device:

field
protocol "wai.quantum.provider/1"
provider, device the provider's name for itself, and the device's
provenance silicon (a processor), emulator, or simulator; with simulator (or emulator) a sentence naming what it is
qubits the device's qubit count
native_gates the gates it runs; a client compiles to the first of the bases of §4 whose every gate is listed
connectivity "all", or the pairs [a, b] a two-qubit gate may act on, in either order
durations optional: {"unit", "gates", "measure"}: the unit (ns, us, ms or s), each native gate's duration wherever it runs ({"sx": 35, "cz": 68}), and the measurement's
calibration {"id"}, the calibration snapshot the device is under; optionally qubits ({"qubit", "readout_error", "error_1q", "t1_us", "t2_us"}) and edges ({"qubits": [a, b], "error"}), each error from 0 to 1
billing {"free": true}, or {"unit", "price", "currency"}: the billing unit (shot, job, second, …), the price of one as a decimal string ("0.0003"), and the currency or credit it is in; optionally free_tier, the free use offered and its limits, as the provider states them
max_shots optional: the most shots a job may ask
seeded optional: true when a job's seed makes its counts reproducible (a simulator)

A client MUST NOT take a device to be free unless billing says "free": true, or an estimate says so (§5.2).

A client MAY read a describe answer whose calibration states errors as a device target (wai.quantum.target/1, wai-quantum/src/engine/targets) and place the program on the qubits and pairs most likely to succeed. The program it sends is checked against the circuit as every program is (§1), and the receipt names how it was placed (§8).

5.2 estimate

Fields: program (§4), shots. The answer, before anything is submitted:

field
free whether this job is free
amount, currency when it is not: the cost, the amount as a decimal string
unit optional: the billing unit the cost counts
seconds optional: how long it is expected to take, queue included
note optional

A provider that cannot estimate answers unsupported; the client then treats the cost as unknown (§7).

5.3 submit

Fields: program, shots, and optionally seed (a seeded simulator uses it; a device ignores it). The answer's job is the job's id.

5.4 status

Field: job. The answer's status is queued, running, done, failed or cancelled, with an optional reason.

5.5 result

Field: job. The answer, once the job is done:

field
counts an object from outcomes to counts (§6), summing to the shots
shots the shots
calibration optional: the calibration snapshot the job ran under, when it is not the one describe names
charged optional: {"amount", "currency"}, what the job cost
energy optional: {"kwh"}, the provider's own figure for the job's energy

A result asked twice of the same job MUST give the same counts.

5.6 cancel

Field: job. The answer's status is cancelled, or done for a job that had already finished. A provider that cannot cancel answers unsupported.

6. Counts and bit order

An outcome is a string of bits characters, 0 or 1, the highest bit first: its last character is bit 0. "01" is bit 0 read as 1 and bit 1 read as 0. This is OpenQASM's order, and the job service's.

The client compiles each logical qubit i of the person's circuit to end on the physical qubit that bit i measures, and reads the counts back onto the program's own classical bits. The first job on a new provider SHOULD be the probe (an X on qubit 0, every qubit measured), whose counts must all land on …01; the conformance vectors begin with it (§9).

7. Cost and confirmation

A job is free when the provider's estimate says "free": true, or, for a provider that gives no estimate, when its billing says so. Every other job, an unknown cost included, is not free. A client:

  • MUST show the estimate (or that the cost is unknown) before submitting;
  • MUST NOT submit a job that is not free without the person's explicit confirmation for that run: a command-line flag (wai-quantum run --provider NAME --yes), an agent tool's argument the agent sets only after the person agreed (run_on_provider with confirm_cost: true), or a dialog (the desktop app);
  • MUST NOT hold a standing confirmation across runs.

A tool that can submit a job that is not free MUST say in its description that it can spend the person's money.

8. The receipt

The host seals each provider job as the job service seals its own: an Ed25519 signature, by the host's key, over the request as submitted and the result as returned, each in its RFC 8785 canonical text, verified by the same verifier. The result's method is provider and its accuracy class is measured. It carries:

  • provider: the person's name for it, its kind, its protocol, the device, its provenance, and the BLAKE3 hash of its describe answer;
  • calibration: the calibration snapshot the job ran under;
  • compiled: the basis, the BLAKE3 hash of the compiled program's OpenQASM 3 text, its gate and swap counts, its initial and final layout, the check it passed before it was sent, and how it was placed (placement: with a calibration read as a target, the target's hash, the layout's expected success and the fewest-swaps layout's);
  • job: the provider's job id and the status checks before it finished;
  • counts, keyed by the program's classical bits (§6);
  • ideal: the circuit's exact distribution set beside the counts (up to 22 qubits): the total variation distance, the Hellinger fidelity, and the distance the shots alone would leave on average;
  • cost: the estimate shown before submitting, what the provider says it charged, and whether the person confirmed a run that was not free;
  • energy: unmetered here, with the provider's own figure, labelled as its own, when it gives one.

What the receipt proves: that this result, with these counts, is what the signer's host received for this request from the provider and device it names, under the calibration snapshot named, for the compiled program whose hash it carries; and that the host compiled that program exactly and checked it against the circuit before sending it. What it does not prove: that the device ran that program, or ran anything. The counts are the provider's word, and they are not reproducible by recomputation: the same job run again gives other counts. The ideal distance says how far they are from what the circuit gives; a distance well above the sampling distance is the device's error, or a program the device did not run as sent.

9. Conformance

wai-quantum-qpu/conformance/provider-v1.json holds the vectors:

  • messages, sent as they are: an unknown operation (unsupported), another version (unsupported_version), a message without its protocol (invalid), a job that does not exist (not_found), malformed programs (invalid);
  • programs, each compiled to the device, estimated, run with seed 1, and checked by its counts: the probe, bits named out of order, a phase only interference shows, a phase kicked back by two quarter-turn controlled phases, a Bell pair, and a triangle of two-qubit gates that needs routing on a line. The thresholds leave room for a device's noise;
  • reference: the counts the reference provider gives for each program at seed 1, so its determinism is held on every platform.

The checker (wai-quantum providers test NAME) also checks the describe answer in full, that zero shots are invalid, and that a program in another basis is refused. It runs the programs only when every estimate says free, or the person allows the spend (--yes).

The reference provider (wai-quantum providers reference --stdio, or --http ADDR) is this protocol around WAI's exact simulator. It is the provider the tests run against over both transports, and the template to copy: a provider for any device is the reference with its simulation replaced by the device.

10. Versioning

wai.quantum.provider/1 is this text. A later version is a new protocol string; a provider that speaks only this one answers unsupported_version to another. Fields marked optional may be added to answers without a new version, and a client MUST ignore fields it does not know.