JobSpec

Every job is a JobSpec (API version gpulayer.dev/v1alpha1). The SDK builders, the Trainer and launch() create them for you; you can also write one as JSON and run gpulayer submit -f job.json. Unknown fields are rejected.

json
{
"name": "finetune",
"workload": {"kind": "command", "command": ["python", "train.py"], "source": null},
"resources": {"accelerator": "cuda", "gpu_count": 2, "gpu_memory_gb": 40,
"frameworks": {"torch": ">=2.2"}},
"placement": {"target": "remote", "worker_labels": {"pool": "a100"},
"on_unschedulable": "fail"},
"env": {"EPOCHS": "10"},
"secrets": [{"name": "HF_TOKEN", "source": "env", "key": "HF_TOKEN"}],
"timeout_seconds": 7200,
"retry": {"max_attempts": 2, "retry_on": ["worker_lost"]}
}

Top level

FieldTypeDefaultNotes
namestring"job"letters, digits, _ . -; up to 63 characters
workloadobjectrequiredone of the three kinds below
resourcesResourceRequestCPU, 1 coreper node
placementPlacementPolicytarget local
envmap{}not secret; GPULAYER_* and torchrun names are reserved
secretslist of SecretRef[]resolved on the worker from its own environment
inputslist of {artifact, path}[]staged under $GPULAYER_INPUT_DIR/path
timeout_secondsnumbernone
retry{max_attempts, retry_on}1, ["worker_lost"]not allowed for distributed jobs
labelsmap{}free-form

Workloads

kindFields
commandcommand (argv; a leading python means the worker's interpreter), source
functionentrypoint (module:function), args, kwargs (JSON), source
distributedentrypoint (script path in the bundle) and args, or function, function_args, function_kwargs; source, num_workers, procs_per_worker, comm_backend (gloo/nccl), rendezvous (port, join_timeout_seconds)

ResourceRequest

FieldDefaultNotes
profilenoneruntime profile (see below); fills in accelerator and frameworks
acceleratorcpucpu, cuda, mps, rocm (rocm is never scheduled yet)
gpu_count0 (1 for GPU accelerators)devices per node
gpu_memory_gbnoneminimum per device
gpu_memory_kindnonededicated or unified
min_cuda_compute_capabilitynonee.g. "8.0"
cpu_cores, memory_gb, disk_gb1, none, noneplacement constraints, not enforced limits
os, cpu_arch[]e.g. ["linux"], ["x86_64"]
frameworks{}PEP 440 specifiers, e.g. {"torch": ">=2.2"}
pythonnonePEP 440 specifier for the worker's Python

Runtime profiles

A profile is a shorthand for common requirements. Explicit frameworks entries override the profile's, and an explicit accelerator must match it. Workers are still matched on what they report, so a profile never makes an incompatible worker eligible.

ProfileAcceleratorFrameworks
pytorch-cpucputorch>=2.1
pytorch-cudacudatorch>=2.1, torch.cuda
pytorch-mpsmpstorch>=2.1, torch.mps
jax-cudacudajax>=0.4, jaxlib>=0.4
cupy-cudacudacupy>=12
mlxmpsmlx>=0.10
python
@gl.remote(profile="pytorch-cuda", gpus=2)
def finetune(...): ...
bash
gpulayer submit --profile mlx -- python bench.py

PlacementPolicy

FieldDefaultNotes
targetlocallocal, remote, cloud
fallback_targets[]tried in order after target
worker_ids, worker_labels[], {}pin to specific workers
providers, regions[]restrict provider-backed workers
strategyspreadspread: least-loaded worker first; first_fit: lowest worker id with a free slot (packs work); most_free_memory
on_unschedulablequeuefail rejects jobs no registered worker could ever run
max_hourly_cost, currencynone, USDoffers without a price are rejected when set
provisioningnone{provider, release, provisioning_timeout_seconds}