Capsule Specification
Capsule Specification
A Capsule is Marqov’s core abstraction for defining reproducible, portable compute workloads. Think of it as a declarative specification that captures everything needed to execute a hybrid quantum-classical computation: the code, dependencies, data, target hardware, and execution parameters.
Philosophy
The Problem with Ad-Hoc Execution
Traditional approaches to running quantum workloads suffer from several issues:
# The typical workflow (problematic)
$ pip install qiskit pennylane # Which versions?
$ python my_circuit.py # Which backend?
$ # ... weeks later ...
$ python my_circuit.py # Different results. Why?
Without explicit specification, experiments become unreproducible. Dependencies drift, backends change, parameters get lost in notebooks, and the “it worked on my machine” problem multiplies across quantum providers.
Capsules as the Solution
A Capsule captures the complete execution context in a single, versioned document:
apiVersion: marqov.com/v1
kind: Capsule
metadata:
name: my-vqe-experiment
version: 1.0.0
tags: [quantum, optimization, vqe]
spec:
backend:
type: quantum
providers: [ibm_quantum, aws_braket]
requirements:
qubits: 4
connectivity: linear
environment:
python: "3.11"
dependencies:
- qiskit>=1.0
- pennylane>=0.35
artifacts:
- path: circuit.py
type: source
- path: params.json
type: data
execution:
entrypoint: python circuit.py
timeout: 3600
This specification embodies three core principles:
- Reproducibility: Every execution of this Capsule will use identical dependencies, parameters, and configurations
- Portability: The same Capsule runs on IBM Quantum, AWS Braket, or local simulators without modification
- Declarative Intent: You specify what you want to run, not how to configure each provider’s SDK
Schema Reference
Document Structure
Every Capsule document has four top-level fields:
| Field | Required | Description |
|---|---|---|
apiVersion | Yes | Schema version (currently marqov.com/v1) |
kind | Yes | Resource type (must be Capsule) |
metadata | Yes | Identification and organizational data |
spec | Yes | The workload specification |
Metadata
The metadata section identifies and organizes your Capsule:
metadata:
name: my-vqe-experiment
version: 1.0.0
tags: [quantum, optimization, vqe]
labels:
team: research
project: hydrogen-simulation
annotations:
description: "VQE for H2 ground state energy"
paper: "https://arxiv.org/abs/..."
Metadata Fields
| Field | Required | Type | Description |
|---|---|---|---|
name | Yes | string | Unique identifier (lowercase, alphanumeric, hyphens) |
version | Yes | string | Semantic version (e.g., 1.0.0, 2.1.0-beta) |
tags | No | array | Searchable keywords for discovery |
labels | No | object | Key-value pairs for organization and filtering |
annotations | No | object | Arbitrary metadata (descriptions, links, etc.) |
Naming Conventions
Names must follow DNS subdomain rules:
- Lowercase letters, numbers, and hyphens only
- Must start with a letter
- Maximum 63 characters
# Valid names
name: vqe-h2-simulation
name: qaoa-maxcut-v2
name: grover-search-4qubit
# Invalid names
name: VQE_Experiment # Uppercase and underscore
name: 123-circuit # Starts with number
name: my circuit # Contains space
Spec: Backend
The backend section specifies where your workload should execute:
spec:
backend:
type: quantum
providers: [ibm_quantum, aws_braket, ionq]
requirements:
qubits: 4
connectivity: linear
errorRate: 0.01
preferences:
priority: cost # cost | performance | availability
region: us-east
Backend Fields
| Field | Required | Type | Description |
|---|---|---|---|
type | Yes | string | quantum, classical, or hybrid |
providers | No | array | Allowed providers (any if omitted) |
requirements | No | object | Hard constraints the backend must satisfy |
preferences | No | object | Soft preferences for backend selection |
Backend Types
Quantum - Executes on quantum hardware or simulators:
backend:
type: quantum
providers: [ibm_quantum]
requirements:
qubits: 8
connectivity: heavy-hex
Classical - Executes on classical compute (HPC, GPU clusters):
backend:
type: classical
requirements:
memory: 64GB
gpu: true
gpuMemory: 24GB
Hybrid - Requires coordinated quantum and classical resources:
backend:
type: hybrid
quantum:
providers: [ibm_quantum, aws_braket]
requirements:
qubits: 4
classical:
requirements:
memory: 32GB
cpu: 8
Requirements
Hard constraints that backends must satisfy:
| Field | Type | Applies To | Description |
|---|---|---|---|
qubits | integer | quantum | Minimum qubit count |
connectivity | string | quantum | linear, ring, all-to-all, heavy-hex |
errorRate | float | quantum | Maximum single-qubit gate error |
t1 | string | quantum | Minimum T1 coherence time (e.g., 100us) |
t2 | string | quantum | Minimum T2 coherence time |
memory | string | classical | Required RAM (e.g., 64GB) |
cpu | integer | classical | Minimum CPU cores |
gpu | boolean | classical | GPU required |
gpuMemory | string | classical | Required GPU memory |
Preferences
Soft preferences that influence backend selection when multiple options satisfy requirements:
preferences:
priority: performance # cost | performance | availability
region: us-east # Prefer specific region
queue: express # Queue/tier preference
Spec: Environment
The environment section defines the software runtime:
spec:
environment:
python: "3.11"
dependencies:
- qiskit>=1.0,<2.0
- pennylane>=0.35
- numpy>=1.24
- scipy>=1.11
system:
- libopenblas-dev
variables:
QISKIT_IN_PARALLEL: "TRUE"
OMP_NUM_THREADS: "4"
Environment Fields
| Field | Required | Type | Description |
|---|---|---|---|
python | No | string | Python version (default: 3.11) |
dependencies | No | array | Python packages (pip format) |
system | No | array | System packages (apt format) |
variables | No | object | Environment variables |
requirements | No | string | Path to requirements.txt file |
Dependency Specification
Dependencies use standard pip version specifiers:
dependencies:
# Exact version
- qiskit==1.0.2
# Minimum version
- pennylane>=0.35
# Version range
- numpy>=1.24,<2.0
# Any version
- matplotlib
# Git dependency
- git+https://github.com/org/repo.git@v1.0.0
# Local wheel (relative to Capsule)
- ./wheels/custom_package-1.0-py3-none-any.whl
Using requirements.txt
For complex dependency sets, reference an external file:
environment:
python: "3.11"
requirements: requirements.txt
The requirements.txt is then included as an artifact.
Spec: Artifacts
The artifacts section declares files included with the Capsule:
spec:
artifacts:
- path: circuit.py
type: source
description: "Main VQE circuit implementation"
- path: params.json
type: data
description: "Initial variational parameters"
- path: results/
type: output
description: "Directory for output files"
- path: requirements.txt
type: config
Artifact Fields
| Field | Required | Type | Description |
|---|---|---|---|
path | Yes | string | Relative path to file or directory |
type | Yes | string | Artifact type (see below) |
description | No | string | Human-readable description |
checksum | No | string | SHA-256 hash for integrity verification |
Artifact Types
| Type | Description | Examples |
|---|---|---|
source | Source code files | .py, .qasm, .ipynb |
data | Input data files | .json, .csv, .h5 |
config | Configuration files | .yaml, .toml, requirements.txt |
model | Trained models or parameters | .pkl, .pt, .safetensors |
output | Output directories (created at runtime) | results/, logs/ |
Integrity Verification
For reproducibility, include checksums:
artifacts:
- path: pretrained_params.pkl
type: model
checksum: sha256:a1b2c3d4e5f6...
Marqov verifies checksums before execution, ensuring you run exactly what you expect.
Spec: Execution
The execution section defines how to run the workload:
spec:
execution:
entrypoint: python circuit.py
args:
- --shots=8192
- --optimizer=COBYLA
timeout: 3600
retries: 3
resources:
shots: 8192
maxCircuits: 100
Execution Fields
| Field | Required | Type | Description |
|---|---|---|---|
entrypoint | Yes | string | Command to execute |
args | No | array | Command-line arguments |
timeout | No | integer | Maximum execution time in seconds |
retries | No | integer | Retry count on failure |
resources | No | object | Resource limits and quotas |
hooks | No | object | Lifecycle hooks |
Entrypoint Patterns
The entrypoint can be specified several ways:
# Direct Python script
entrypoint: python circuit.py
# Module execution
entrypoint: python -m mypackage.main
# Jupyter notebook
entrypoint: papermill input.ipynb output.ipynb
# Shell script
entrypoint: bash run.sh
# With inline arguments
entrypoint: python circuit.py --config config.yaml
Resource Limits
Control quantum resource consumption:
resources:
shots: 8192 # Shots per circuit execution
maxCircuits: 100 # Maximum circuits per job
maxQubits: 8 # Maximum qubits to use
estimatedRuntime: 30m # Hint for scheduling
Lifecycle Hooks
Execute code at specific points:
hooks:
preExecution:
- python setup.py prepare
postExecution:
- python collect_results.py
onFailure:
- python notify.py --status=failed
Advanced Features
Parameterization
Capsules support parameter injection for experimentation:
apiVersion: marqov.com/v1
kind: Capsule
metadata:
name: vqe-sweep
version: 1.0.0
spec:
parameters:
- name: num_layers
type: integer
default: 4
description: "Ansatz circuit depth"
- name: optimizer
type: string
default: COBYLA
enum: [COBYLA, SPSA, ADAM]
- name: shots
type: integer
default: 8192
execution:
entrypoint: python circuit.py
args:
- --layers={{ num_layers }}
- --optimizer={{ optimizer }}
- --shots={{ shots }}
Execute with different parameters:
marqov run vqe-sweep.yaml --set num_layers=8 --set optimizer=SPSA
Multi-Stage Workflows
Define complex workflows with multiple stages:
apiVersion: marqov.com/v1
kind: Capsule
metadata:
name: vqe-full-pipeline
version: 1.0.0
spec:
stages:
- name: prepare
backend:
type: classical
execution:
entrypoint: python prepare_hamiltonian.py
outputs:
- hamiltonian.json
- name: optimize
backend:
type: hybrid
dependencies:
- prepare
execution:
entrypoint: python run_vqe.py
outputs:
- optimal_params.json
- name: analyze
backend:
type: classical
dependencies:
- optimize
execution:
entrypoint: python analyze_results.py
Provider-Specific Overrides
When backends require specific configuration:
spec:
backend:
type: quantum
providers: [ibm_quantum, aws_braket]
overrides:
ibm_quantum:
instance: "ibm-q/open/main"
resilience_level: 1
transpilation:
optimization_level: 3
aws_braket:
device: "arn:aws:braket:us-east-1::device/qpu/ionq/Aria-1"
disable_qubit_rewiring: false
Overrides are applied only when executing on the matching provider, keeping your Capsule portable while allowing provider-specific optimization.
Versioning
Semantic Versioning
Capsules use semantic versioning (MAJOR.MINOR.PATCH):
metadata:
name: my-experiment
version: 1.2.3
- MAJOR: Breaking changes (different algorithm, incompatible outputs)
- MINOR: New features (additional outputs, new parameters)
- PATCH: Bug fixes (same inputs produce same outputs)
Version Constraints
Reference specific versions or ranges:
# Exact version
marqov run my-experiment@1.2.3
# Latest patch
marqov run my-experiment@1.2
# Latest minor
marqov run my-experiment@1
# Latest
marqov run my-experiment@latest
Immutability
Published Capsule versions are immutable. Once my-experiment@1.0.0 exists:
- It cannot be modified or overwritten
- The same specification always produces the same execution
- Results are traceable to exact Capsule versions
To make changes, increment the version number.
Complete Example
Here’s a production-ready Capsule for a VQE chemistry simulation:
apiVersion: marqov.com/v1
kind: Capsule
metadata:
name: h2-ground-state-vqe
version: 2.1.0
tags: [quantum-chemistry, vqe, hydrogen]
labels:
team: chemistry
project: molecular-simulation
annotations:
description: "VQE calculation for H2 ground state energy"
paper: "https://arxiv.org/abs/2024.xxxxx"
contact: "quantum-team@example.com"
spec:
parameters:
- name: bond_distance
type: float
default: 0.735
description: "H-H bond distance in Angstroms"
- name: ansatz_layers
type: integer
default: 2
description: "Number of variational layers"
- name: shots
type: integer
default: 8192
description: "Measurement shots per circuit"
backend:
type: hybrid
quantum:
providers: [ibm_quantum, aws_braket]
requirements:
qubits: 4
connectivity: linear
preferences:
priority: performance
classical:
requirements:
memory: 8GB
cpu: 4
environment:
python: "3.11"
dependencies:
- qiskit>=1.0,<2.0
- qiskit-nature>=0.7
- pyscf>=2.4
- numpy>=1.24
- scipy>=1.11
- h5py>=3.9
variables:
QISKIT_IN_PARALLEL: "TRUE"
OMP_NUM_THREADS: "4"
artifacts:
- path: src/vqe_runner.py
type: source
description: "Main VQE implementation"
- path: src/ansatz.py
type: source
description: "Ansatz circuit definitions"
- path: src/hamiltonian.py
type: source
description: "Molecular Hamiltonian construction"
- path: config/default_params.json
type: config
description: "Default initial parameters"
- path: results/
type: output
description: "Output directory for results"
execution:
entrypoint: python src/vqe_runner.py
args:
- --bond-distance={{ bond_distance }}
- --layers={{ ansatz_layers }}
- --shots={{ shots }}
- --output=results/
timeout: 7200
retries: 2
resources:
shots: 8192
maxCircuits: 200
hooks:
postExecution:
- python src/validate_results.py results/
overrides:
ibm_quantum:
resilience_level: 2
transpilation:
optimization_level: 3
approximation_degree: 0.95
Validation
Before execution, Marqov validates Capsules against the schema:
marqov validate my-capsule.yaml
Common validation errors:
| Error | Cause | Fix |
|---|---|---|
Invalid name | Name contains invalid characters | Use lowercase, numbers, hyphens only |
Missing required field | Required field not specified | Add the missing field |
Unknown field | Typo or unsupported field | Check spelling, consult schema |
Invalid version | Version not semantic | Use MAJOR.MINOR.PATCH format |
Artifact not found | Referenced file doesn’t exist | Verify file path and existence |
Best Practices
1. Pin Dependencies
# Good: Reproducible
dependencies:
- qiskit==1.0.2
- numpy==1.24.3
# Risky: May change
dependencies:
- qiskit
- numpy
2. Use Checksums for Critical Files
artifacts:
- path: trained_model.pkl
type: model
checksum: sha256:a1b2c3...
3. Document Parameters
parameters:
- name: learning_rate
type: float
default: 0.01
description: "Classical optimizer learning rate. Lower values converge slower but more reliably."
4. Set Reasonable Timeouts
execution:
timeout: 3600 # 1 hour
# Not: timeout: 86400 # 24 hours (too long, hides problems)
# Not: timeout: 60 # 1 minute (too short for real quantum)
5. Organize Artifacts
my-capsule/
capsule.yaml
src/
main.py
utils.py
config/
params.json
data/
input.csv
results/ # Output directory
Ready to create your first Capsule? Get started with Marqov or explore example Capsules.