Kino.Qx
Livebook Smart Cells + pipeline functions for running quantum circuits on real IBM hardware via the Qx Portal.
Two cells ship in this package:
- Qx Snippet — browse the snippets you've saved on the portal, pick one from a dropdown, and inject the OpenQASM 3.0 (or converted Elixir/Qx) source straight into a notebook cell.
- Qx Credentials(new in 0.2.0) — collects portal URL, region,
backend, optimization level, and shots; emits a
%Qx.Hardware.Config{}binding (qx) that downstream cells pipe circuits throughKino.Qx.run!/2.
End-to-end pipeline:
circuit
|> Kino.Qx.run!(qx)
|> Qx.Draw.plot_counts(title: "Bell state")Status
v0.2.0 is a breaking architectural reset. The previous
Kino.Qx.TranspileCell (paste-QASM + Submit button + inline result
rendering) is replaced by Kino.Qx.CredentialsCell + a Kino.Qx.run!/2
pipeline function. The transpile / submit / poll core moved upstream
into Qx.Hardware in the :qx library (0.7.0); kino_qx becomes a
thin UX layer that adds a live Kino.Frame status panel.
The portal-side JSON API is locked at /api/v1 — see the
API reference. The IBM Quantum
REST API is documented at
quantum.cloud.ibm.com.
Installation
In a Livebook setup cell:
Mix.install([
{:kino_qx, "~> 0.2"},
{:qx, "~> 0.7"}
])Click + Smart at the bottom of any notebook cell. You'll see both cells in the menu — pick the one you need.
Cell 1 — Qx Snippet (unchanged from 0.1)
Needs:
- A
qx_live_*portal token.Dashboard → API Keys → Generate Key. - Portal URL (defaults to
https://qxportal.dev).
The token is stored only in transient cell state and never
serialized into the .livemd file.
Cell 2 — Qx Credentials + Kino.Qx.run!/2
Livebook secrets (one-time per notebook)
The cell never asks for tokens directly. It reads three Livebook secrets at Connect / run time:
| Secret name | What it is |
|---|---|
LB_PORTAL_TOKEN |
qxportal qx_live_… bearer (Dashboard → API Keys → Generate Key) |
LB_IBM_API_KEY | IBM Cloud API key (https://quantum-computing.ibm.com/ → Account) |
LB_IBM_CRN |
IBM Service-CRN (crn:v1:bluemix:public:quantum:…) |
Add each via the lock icon in Livebook's left sidebar before clicking
Connect. The .livemd file never carries any token — sharing a
notebook leaks nothing.
Cell UI
- Portal URL — defaults to
https://test.qxquantum.com. Validated against a host allowlist (*.qxquantum.comover https;localhost/127.0.0.1over http for dev) so a malicious shared notebook cannot redirect your token. - Region —
us-south(default) oreu-de. Must match the region encoded in your CRN. - Connect — reads the three secrets, validates auth, populates the backend dropdown.
- Backend / Optimization / Shots — chosen per cell run.
Pipeline
circuit =
Qx.create_circuit(2, 2)
|> Qx.h(0)
|> Qx.cx(0, 1)
|> Qx.measure(0, 0)
|> Qx.measure(1, 1)
circuit
|> Kino.Qx.run!(qx)
|> Qx.Draw.plot_counts(title: "Bell state")
A live Kino.Frame status panel renders above the result while the
job moves through transpile → submit → queued → running → done. If
you click Livebook's "Stop" button mid-run, a best-effort
Qx.Hardware.cancel/3 fires for the in-flight job.
Kino.Qx.run!/2 raises Kino.Qx.RunError on failure (pipe-friendly).
The tuple-returning Kino.Qx.run/2,3 is also available for
production-style with chains.
Outside Livebook
The hardware-execution core lives in Qx.Hardware. CLI scripts,
Phoenix apps, and OTP services can run circuits without a Livebook
runtime:
config = %Qx.Hardware.Config{
portal_url: "https://test.qxquantum.com",
portal_token: System.fetch_env!("PORTAL_TOKEN"),
ibm_api_key: System.fetch_env!("IBM_API_KEY"),
ibm_crn: System.fetch_env!("IBM_CRN"),
ibm_region: "us-south",
backend: "ibm_brisbane"
}
{:ok, result} = Qx.Hardware.run(circuit, config)Kino.Qx.run/2,3 adds the status frame and cancel watcher around the
same Qx.Hardware.run/3 call.
What's NOT in v1
- Estimator primitive — Sampler only (Estimator deferred; base64 tensor decoding deserves its own iteration).
- Multi-circuit batches — one circuit per
run!/2call. - OpenQASM 2.0 input — qxportal accepts 3.0 only; convert client-side first.
Compatibility
kino_qx | qx | Kino | Elixir |
|---|---|---|---|
| 0.2.x | ~> 0.7 | ~> 0.19 | >= 1.17 |
| 0.1.x | n/a | ~> 0.19 | >= 1.17 |
Troubleshooting
Qx Snippet
| Symptom | Likely cause |
|---|---|
unauthorized (401) | Token is wrong, revoked, or for a different portal |
| Empty dropdown | You haven't saved any snippets to the portal yet |
rate_limited (429) | More than 60 requests per minute on this key — wait + retry |
| Network timeout | Wrong portal URL, or the portal is unreachable from this host |
Qx Credentials + Kino.Qx.run!
| Symptom | Likely cause |
|---|---|
Missing Livebook secret LB_PORTAL_TOKEN | Add the secret via the lock icon in Livebook's sidebar |
Auth rejected (401) from Connect | Secret values wrong, or IBM region doesn't match the CRN |
Qx.Hardware.NoMeasurementsError |
Circuit has no Qx.measure/3 calls — Sampler V2 requires them |
Portal rejected the QASM (422) | OpenQASM 2.0 input or syntax error; convert to 3.0 |
Portal transpile failed (502) |
Circuit too wide for the backend; try a smaller backend or optimization_level: 0 |
Kino.Qx.Interrupted | You clicked Livebook's Stop button mid-run; cancel was issued |
| Cell stuck on "queued" | IBM queue can be very long; the pipeline polls until terminal status |
Connect succeeds but no backends | Your IBM instance has no backends provisioned for this region |
Portal URL must be https://… |
The URL is not on the allowlist (*.qxquantum.com over https) |