# SDK reference

> Overview of the qsolve-sdk Python package: install, import map of every module, how the pieces fit together, and which names are public API and which are internal.

Source: https://qsolve.omlabs.co/docs/build/sdk-reference
Updated: 2026-11-13

`qsolve-sdk` is the bridge between a plain Qiskit workflow and the Qsolve platform. It contains no quantum algorithm. You bring circuits, error mitigation and classical methods; the SDK runs them on Qsolve's backends, records every circuit that leaves your code, re-evaluates every answer and measures the numbers. The platform runs this same package inside its sandbox, so a workflow that passes `qsolve test` on your machine behaves the same on Qsolve.

This page is the map. Each area has its own reference page with every public name, its signature, parameters, return value, exceptions and an example.

## Install

```bash
pip install qsolve-sdk            # the package; Python 3.12 or newer, Qiskit 2.x
pip install "qsolve-sdk[ibm]"     # also the IBM runtime: device noise models and IBM hardware
```

The package installs the `qsolve` command (see [The qsolve command line](/docs/build/cli)) and the Python package `qsolve`. The `ibm` extra is needed for `fake:<device>` noise-model targets as well as for real IBM hardware, so install it if you use either (the scaffold's third benchmark case uses a noise model).

```python
import qsolve
print(qsolve.__version__)      # for example "1.0.0"; "0.0.0+local" when run from an uninstalled source tree
```

## What you import

Everything a workflow needs is exported from the top-level package. These 24 names are the whole of `qsolve.__all__`:

| Name | Kind | Reference page |
|---|---|---|
| `Workflow` | base class you subclass | [The Workflow class](/docs/build/sdk-workflow-class) |
| `Outcome` | dataclass every method returns | [The Workflow class](/docs/build/sdk-workflow-class) |
| `Context` | dataclass passed to every method | [The Workflow class](/docs/build/sdk-workflow-class) |
| `WorkflowError` | exception | [The Workflow class](/docs/build/sdk-workflow-class) |
| `InvalidSolution` | exception | [The Workflow class](/docs/build/sdk-workflow-class) |
| `MethodUnavailable` | exception | [The Workflow class](/docs/build/sdk-workflow-class) |
| `QuantumNotAllowed` | exception | [The Workflow class](/docs/build/sdk-workflow-class) |
| `Estimate` | pydantic model (pre-run estimate) | [Results and events](/docs/build/sdk-results-and-events) |
| `Result` | pydantic model | [Results and events](/docs/build/sdk-results-and-events) |
| `Provenance` | pydantic model | [Results and events](/docs/build/sdk-results-and-events) |
| `Quality` | pydantic model | [Results and events](/docs/build/sdk-results-and-events) |
| `Mitigation` | pydantic model | [Results and events](/docs/build/sdk-results-and-events) |
| `Uncertainty` | pydantic model | [Results and events](/docs/build/sdk-results-and-events) |
| `MethodResult` | pydantic model (one method's measured result) | [Results and events](/docs/build/sdk-results-and-events) |
| `Metrics` | pydantic model (headline accuracy) | [Results and events](/docs/build/sdk-results-and-events) |
| `CircuitStats` | pydantic model (circuit size and shots) | [Results and events](/docs/build/sdk-results-and-events) |
| `RunOutput` | pydantic model returned by `run_workflow` | [Runner and manifest](/docs/build/sdk-runner-and-manifest) |
| `MAX_SHOTS_PER_CIRCUIT` | constant, `100000`: the most shots the platform runs per circuit | [The manifest](/docs/build/manifest) |
| `Manifest` | pydantic model of `qsolve.yaml` | [Runner and manifest](/docs/build/sdk-runner-and-manifest) |
| `load_workflow` | function | [Runner and manifest](/docs/build/sdk-runner-and-manifest) |
| `run_workflow` | function | [Runner and manifest](/docs/build/sdk-runner-and-manifest) |
| `estimate_run` | function | [Runner and manifest](/docs/build/sdk-runner-and-manifest) |
| `__version__` | string | this page |

A workflow's own code normally needs only the first seven names plus `Estimate`:

```python
from qsolve import Context, Estimate, InvalidSolution, MethodUnavailable, Outcome, Workflow, WorkflowError
```

## Module map

Names outside `qsolve.__all__` are importable from their module (`from qsolve.metering import fidelity`) and are documented in the pages below, but they are the harness's own machinery, not the contract with your workflow. See [What is stable](#what-is-stable).

| Module | What it holds | Page |
|---|---|---|
| `qsolve.workflow` | `Workflow`, `Outcome`, `Context` and the four exceptions: the contract | [The Workflow class](/docs/build/sdk-workflow-class) |
| `qsolve.runner` | `run_workflow`, `estimate_run`, `validate_input`, `RunOutput`: the harness the platform runs | [Runner and manifest](/docs/build/sdk-runner-and-manifest) |
| `qsolve.manifest` | `Manifest` and its parts, `load_workflow`, `LoadedWorkflow`: the parsed `qsolve.yaml` | [Runner and manifest](/docs/build/sdk-runner-and-manifest) |
| `qsolve.comparison` | `run_methods`, `headline`, `implementation`: runs every declared method and computes accuracy | [Runner and manifest](/docs/build/sdk-runner-and-manifest) |
| `qsolve.results` | `Result`, `Provenance`, `Estimate`, `Quality`, `Mitigation`, `CircuitStats`, `MethodResult`, `Metrics`, `Uncertainty` | [Results and events](/docs/build/sdk-results-and-events) |
| `qsolve.events` | `emit`, `capture`, `Sink`: progress events | [Results and events](/docs/build/sdk-results-and-events) |
| `qsolve.circuit_record` | `circuit_ops`, `circuit_summary`, `active_qubits`, `lowered`, `DRAWABLE`: circuits as drawable records | [Results and events](/docs/build/sdk-results-and-events) |
| `qsolve.backends` | `Backend`, `AsyncBackend`, `SampleResult`, `ProviderJobFailed`, `AerBackend`, `get_backend`, plus the `fake`, `ibm`, `remote` and `hardware` submodules | [Backends and the Qiskit bridge](/docs/build/sdk-backends-and-bridge) |
| `qsolve.bridge` | `QsolveBackend`, `QsolveSampler`, `QsolveEstimator`: the Qiskit-native objects in `ctx` | [Backends and the Qiskit bridge](/docs/build/sdk-backends-and-bridge) |
| `qsolve.sim` | simulator threading and run-time prediction | [Metering and cost](/docs/build/sdk-metering-and-cost) |
| `qsolve.metering` | `Recorder` and everything measured at the backend boundary | [Metering and cost](/docs/build/sdk-metering-and-cost) |
| `qsolve.benchmark` | `run_benchmarks` and the gate and case models | [Testing, linting and the sandbox](/docs/build/sdk-testing-and-benchmarks) |
| `qsolve.lint` | `lint_workflow`, `Finding`, `has_errors` | [Testing, linting and the sandbox](/docs/build/sdk-testing-and-benchmarks) |
| `qsolve.sandbox_entry` | the process the platform runs in the sandbox (`python -m qsolve.sandbox_entry`) | [Testing, linting and the sandbox](/docs/build/sdk-testing-and-benchmarks) |
| `qsolve.cli` | the `qsolve` command (a Typer app named `app`) | [The qsolve command line](/docs/build/cli) |
| `qsolve._version` | `__version__`, read from the installed package metadata | this page |

## How the pieces fit

```text
qsolve.yaml  ->  load_workflow()  ->  Manifest + two JSON Schemas
                      |
input.json  ->  validate_input()      (jsonschema; WorkflowError on a mismatch)
                      |
        _instantiate(): import entrypoint, YourWorkflow(input, params), size() vs envelope
                      |
   run_methods(): every declared method, reference and classical first, quantum last
        |                  |
        | classical ctx    | quantum ctx
        | backend refuses  | QsolveBackend -> Backend (Aer | fake | IBM | executor)
        |                  |          every circuit, shot and count -> metering.Recorder
        v                  v
   evaluate(solution) recomputes each objective      -> MethodResult (recomputed | reported)
        |
   headline(): accuracy, +/-, matches                -> Metrics
   metering.quality(): fidelity, depth, 2q gates     -> Quality
   answer(outcome) + output schema check             -> Result.answer
        |
   RunOutput(result=Result, provenance=Provenance)
```

In words:

1. **You write** a `Workflow` subclass ([The Workflow class](/docs/build/sdk-workflow-class)) and a manifest ([The manifest](/docs/build/manifest)).
2. **The runner** (`run_workflow`) loads and validates everything, builds your class, and calls `run_methods` ([Runner and manifest](/docs/build/sdk-runner-and-manifest)).
3. **Each method gets a `Context`.** The quantum method's `ctx.sampler`, `ctx.estimator` and `ctx.backend` are the bridge objects, which send circuits to a backend; the classical methods get a context whose backend refuses ([Backends and the Qiskit bridge](/docs/build/sdk-backends-and-bridge)).
4. **Everything that crosses the backend is recorded** by `metering.Recorder`, from which Qsolve computes circuit size and fidelity without trusting your code ([Metering and cost](/docs/build/sdk-metering-and-cost)).
5. **The comparison** recomputes each objective with your `evaluate`, flags contradictions and computes accuracy against the reference.
6. **The output** is a `Result` and a `Provenance` ([Results and events](/docs/build/sdk-results-and-events)).
7. **`qsolve test`** (`run_benchmarks`) runs this pipeline for every benchmark case and adds the validation gates; `qsolve lint` is the static check ([Testing, linting and the sandbox](/docs/build/sdk-testing-and-benchmarks)).

## When the platform calls what, and when you do

| Call | Who calls it | When |
|---|---|---|
| `Workflow.__init__`, `size`, `quantum`, `reference`, `classical_<id>`, `evaluate`, `answer`, `estimate`, `summary` | the SDK, never you | during `run_workflow` and `estimate_run` |
| `ctx.sampler`, `ctx.estimator`, `ctx.backend`, `ctx.emit`, `ctx.report_mitigation` | you, from your methods | whenever your method needs them |
| `run_workflow`, `estimate_run`, `load_workflow`, `run_benchmarks`, `lint_workflow` | the CLI and the platform; you may call them from your own tests | `qsolve run`, `estimate`, `test`, `lint`, or a pytest file ([Your first workflow](/docs/build/your-first-workflow) shows the scaffold's test) |
| `Backend`, `QsolveBackend`, `Recorder`, `serve_executor` | the SDK and the platform executor | not part of a workflow; you subclass `Backend` only to test the harness |

## Environment variables

| Variable | Read by | Meaning |
|---|---|---|
| `QSOLVE_IBM_TOKEN` | `IBMBackend` | Your IBM Quantum token. Required for `--target ibm:<device>`; never put it in workflow code. |
| `QSOLVE_IBM_INSTANCE` | `IBMBackend` | Optional IBM instance. |
| `QSOLVE_SIM_THREADS` | `qsolve.sim.sim_threads` | Threads a simulation may use. Positive integer; otherwise every core available to the process. |
| `QSOLVE_EXECUTOR_ADDR` | `get_backend`, `RemoteBackend` | Set by the platform inside the sandbox (`unix:<path>` or `tcp:<host>:<port>`). When set, `get_backend` returns the credential-free remote backend whatever the target string says. You never set it. |
| `QSOLVE_EXECUTOR_TOKEN` | `RemoteBackend` | Shared secret for the executor. Set by the platform. |

## What is stable

Compatibility policy, in one place:

| Level | Names | Promise |
|---|---|---|
| Public, stable | everything in `qsolve.__all__`; the Qiskit-facing behaviour of `ctx.sampler`, `ctx.estimator`, `ctx.backend`; the `qsolve` commands and their exit codes; the lint codes (a code keeps its meaning) | Changes are backward-compatible within a major version. Something is removed or changed incompatibly only in a new major version, after at least one minor release that deprecates it, and the change is listed in `CHANGELOG.md`. |
| Documented, importable, not in `__all__` | `qsolve.results` models other than the exported ones, `qsolve.sim`, `qsolve.circuit_record`, `qsolve.events`, `qsolve.benchmark`, `qsolve.lint`, `qsolve.metering`, `qsolve.comparison`, `qsolve.backends` | Safe to read and to use in tests. May change in a minor version; read `CHANGELOG.md` when you upgrade. |
| Internal | `qsolve.backends.remote` (the executor protocol), `qsolve.sandbox_entry` (the sandbox process), anything whose name starts with an underscore | May change in any release without notice. Do not import them in a workflow. |

Versioning: the SDK follows semantic versioning (`MAJOR.MINOR.PATCH`): a patch fixes bugs only, a minor adds features without breaking public names, a major may break them. The workflow manifest has its own `schema_version` (currently `1`); see [Versioning](/docs/build/versioning).

## Reference pages

- [The Workflow class](/docs/build/sdk-workflow-class): `Workflow`, `Outcome`, `Context`, the exceptions.
- [Runner and manifest](/docs/build/sdk-runner-and-manifest): `run_workflow`, `estimate_run`, `validate_input`, `load_workflow`, `Manifest`, `run_methods`, `headline`.
- [Backends and the Qiskit bridge](/docs/build/sdk-backends-and-bridge): targets, `get_backend`, every backend class, `QsolveBackend`, `QsolveSampler`, `QsolveEstimator`.
- [Metering and cost](/docs/build/sdk-metering-and-cost): `Recorder`, fidelity, `Estimate`, run-time prediction in `qsolve.sim`.
- [Results and events](/docs/build/sdk-results-and-events): every field of `Result`, `Provenance` and friends; `emit`; circuit records.
- [Testing, linting and the sandbox](/docs/build/sdk-testing-and-benchmarks): `run_benchmarks`, case and gate models, `lint_workflow`, `sandbox_entry`.
- [The qsolve command line](/docs/build/cli): every command and flag.

Schema and manifest details live in their own references: [The manifest](/docs/build/manifest), [Parameters](/docs/build/parameters), [Input schema reference](/docs/build/input-schema-reference), [Output schema reference](/docs/build/output-schema-reference), [Benchmarks](/docs/build/benchmarks) and [Lint codes](/docs/build/lint-codes).
