Case study

NoETL as the orchestration harness for verifiable quantum circuit compilation

A circuit search driven by an AI model needs a record of every attempt, limits on what the model can do, retries for long verifier runs, and a way to spread those runs across machines. NoETL provides those. kickmix and the competition’s verifiers do the quantum work.

Scope

What NoETL does here, and what it doesn’t

NoETL does

  • Run each step of the search as a playbook step: ask the model, build, verify, score, package, gate.
  • Append every step’s start and result to the execution’s event log, including each candidate’s settings, artifact hash and verifier verdict.
  • Retry a generator or verifier that crashes, with the backoff the playbook declares.
  • Spread the verifier runs across a worker pool, and let workers leave without dropping a run.
  • Keep the model inside the routes and ranges the playbook declares.

NoETL does not

  • Compile, optimise or rewrite circuits. Your generator scripts do that with kickmix.
  • Verify circuits or compute the competition score. The competition’s verifiers and Kaggle do that.
  • Upload to Kaggle. The example stops at a bundle marked ready for a person to review.
  • Make a retried step safe on its own. Delivery is at-least-once, so writes in the example are keyed so that a repeat adds nothing.
The competition

Smaller circuits that still pass the verifier

Google Quantum AI’s Verifiable Quantum Circuit Compilation competition on Kaggle opened on 22 October 2026, and final submissions are due on 20 January 2027. Entrants build circuits with kickmix, the open-source C++20 and Python library in Qualtran. A submission must pass the verifiers and is scored on qubit and gate counts.

Three benchmarks

Fusion energy: an inverse square root, applied as a phase. Optimization: a Reed–Solomon decoder for Decoded Quantum Interferometry. Chemistry: a factorised FeMoCo Hamiltonian with compact lookup circuits.

One bundle per submission

invsqrt.kmb or .kmx, dqi.kmb or .kmx, and a dfthcsos/ folder holding angle_k_0 to angle_k_n-1 plus submission.npz.

Slow, approximate verification

The verifiers fuzz-test circuits on random inputs, which shows approximate correctness rather than exact equivalence. Scoring a submission takes about 45 minutes, so every bundle should pass locally before it is uploaded.

Sources: the competition page on Kaggle and Google’s announcement. Use the competition page for the exact file format and scoring rules.

The harness

One playbook, six steps, one event log

Every step uses a tool kind the server accepts: http, python or postgres. The server decides what runs next; workers run the steps.

  1. propose_candidatesThe model proposes generator settings as JSON. A python task keeps only settings inside the declared ranges.http, python
  2. build_and_verifyA parallel loop. Each iteration builds one circuit with kickmix, hashes it, runs the verifier, and writes one row.python, postgres
  3. score_roundReads the cheapest verified candidate per benchmark and computes a local proxy score.postgres, python
  4. package_submissionAssembles the bundle, checks the angle numbering and the npz arrays, then zips and hashes it.python
  5. leaderboard_gateA better bundle is marked ready for review. Otherwise the search runs another round.python, postgres
  6. finishSummarises the run. A person reviews the bundle and uploads it.python

The search loops back to propose_candidates through a next arc that increments ctx.round, and stops at max_rounds. The previous round’s best candidates go into the next prompt.

Why a playbook

What the runtime adds to a circuit search

These are the same properties described in Why NoETL, applied to this search. Each card links to where the behaviour lives in the source.

Every candidate is on the log

The model’s reply, the settings that survived the bounds check, the artifact hash and the verifier’s verdict are each a step result on the execution’s append-only event log. A restarted server rebuilds the run from those events and carries on, and the table rows give you a query over every attempt.

orchestrate-core · Orchestrator::evaluate

The model works inside the playbook

The model is reached with an http task and only returns JSON. A python task drops any setting outside the declared generators and ranges before anything runs, and max_rounds caps the search. agent and mcp are not tool kinds: registration refuses them, and an agent that needs an MCP server reaches it over HTTP.

server · validate_tool_kinds

kickmix runs in script steps with retry

A python task can name its interpreter, so it runs in the environment where kickmix is installed, and it takes its own timeout for long verifier runs. The task’s policy retries a crash with linear or exponential backoff and can jump to the record task once retries run out. A circuit that fails verification is recorded and never retried.

tools · task_sequence policy actions

Fan out the verifier, scale in safely

A parallel loop with max_in_flight turns each candidate into a command any worker in the pool can claim. On shutdown a worker stops claiming and finishes what it is running. A command that was never acknowledged goes to another worker, and a redelivered event is recognised by its id. Each row is written with ON CONFLICT DO NOTHING, so a repeated iteration adds nothing.

worker · drain on SIGTERM

Keys by reference, versions by path

The model API key is a keychain entry resolved when the step runs. Registration refuses a playbook that contains secret material inline, because the event log is append-only and never purged. Registering the playbook’s path again adds a version, so each search configuration you ran stays in the catalog under its own version.

server · registration checks

Delivery is at-least-once: redelivered events are deduplicated by id within a bounded window, and steps that call external systems should be written to tolerate a retry.

Example

The build-and-verify step, from the example playbook

This excerpt is shortened. The full file is an example, not a tested entry: it has not been run against the competition, and the script paths, generator settings and cost proxy are placeholders.

examples/quantum-circuit-search/playbook.yamlEXAMPLE
# EXAMPLE. NoETL runs these programs; it does not compile or verify circuits.
- step: build_and_verify
  loop:
    in: "{{ ctx.candidates }}"
    iterator: cand
    spec: { mode: parallel, max_in_flight: 8 }
  tool:
    - name: generate
      kind: python
      python: "{{ kickmix_python }}"   # interpreter with kickmix installed
      timeout_seconds: 1200
      # ... runs your generator script, then hashes what it wrote
      spec:
        policy:
          rules:
            - when: "{{ output.status == 'error' and _attempt < 2 }}"
              then: { do: retry, attempts: 3, backoff: linear, delay: 30.0 }
            - when: "{{ output.status == 'error' }}"
              then: { do: jump, to: record }   # record it as generator_failed
            - else:
                then: { do: continue }
    - name: verify
      kind: python
      python: "{{ kickmix_python }}"
      timeout_seconds: 4200
      # ... runs your wrapper around the official verifier.
      # No verdict means a crash, which is retried. A failed verdict is recorded.
    - name: record
      kind: postgres
      auth: "{{ pg_auth }}"
      command: |
        INSERT INTO vqcc_candidate (...) SELECT ...
        ON CONFLICT (execution_id, candidate_id) DO NOTHING;
  next:
    spec: { mode: exclusive }
    arcs:
      - { step: score_round, when: "{{ event.name == 'loop.done' }}" }

How it was checked: the file was deserialised into the Playbook type from orchestrate-core and given the same checks as the server’s playbook parser: a start step, unique names, known next targets, known policy actions and known tool kinds. Every template also compiles. That confirms the shape, not an end-to-end run.

Sources

Where each claim comes from