Configuration
sflow uses a YAML config file (default name: sflow.yaml). Top-level structure:
version: "0.1"
variables: ...
artifacts: ...
backends: ...
operators: ...
storage: ... # optional: post-run upload targets (S3), paired with task `uploads:`
workflow: ...
This page follows the current schema in code (src/sflow/config/schema.py).
Looking for a quick lookup of all config fields? See the Quick Reference table.
version
Currently supported:
version: "0.1"
variables
Variables can be written as a dict or a list (they are normalized internally).
Dict form (recommended):
variables:
SLURM_PARTITION:
description: "Slurm partition"
value: debug
List form:
variables:
- name: SLURM_PARTITION
description: "Slurm partition"
value: debug
How to use:
- In YAML expressions:
${{ variables.SLURM_PARTITION }} - In task scripts (as env var):
${SLURM_PARTITION}
Override variables via CLI (--set)
sflow run --file sflow.yaml --set SLURM_PARTITION=debug --set NUM_GPUS=4
Notes:
--setcan only override variables that already exist in the config; otherwise it errors.- Values use simple type inference (int/float/bool/list/string).
- List values set the variable domain for replica sweeps, and the variable value becomes the first item.
You can also read a variable's domain inside expressions:
script:
- echo "all concurrencies=${{ variables.CONCURRENCY.domain }}"
- echo "max concurrency=${{ variables.CONCURRENCY.domain | max }}"
artifacts
artifacts are “named resources” you can reference via ${{ artifacts.NAME.path }} in expressions.
The uri scheme determines how an artifact resolves to path:
fs://<path>/file://<path>: resolved to a local filesystem path (relative paths are relative to the workspace).http:///https://: downloaded to a local cache, andpathis set to the cached file.s3://(and any other unregistered scheme): passthrough — no local materialization, so${{ artifacts.NAME.path }}falls back to theuristring itself.hf:///huggingface://anddocker://: the scheme is registered, but materialization is not yet implemented and raisesNotImplementedError(see Known Limitations). Reference a localfile:///fs://path, or pull the model/image inside your task for now.
Example:
artifacts:
model_dir:
uri: fs://./models/qwen
Override artifacts via CLI (--artifact)
sflow run --file sflow.yaml --artifact model_dir=fs:///mnt/models/qwen
Same requirement: the artifact must already be defined in artifacts, otherwise it errors.
backends
sflow ships four backend types — local, slurm, docker, and kubernetes. Every
backend shares a few common fields, including gpus_per_node (GPU capacity per node for
planning/packing) and the node filters include_nodes / exclude_nodes (also settable
via the --include-nodes / --exclude-nodes CLI flags). This page is a summary; see
Backends for the full field reference for each type.
local backend
backends:
local:
type: local
default: true
nodes: 1
slurm backend
backends:
slurm_cluster:
type: slurm
default: true
account: ${{ variables.SLURM_ACCOUNT }}
partition: ${{ variables.SLURM_PARTITION }}
time: 00:30:00
nodes: 2
gpus_per_node: 8 # sflow planning only
extra_args:
- "--gpus-per-node=8" # passed to salloc
gpus_per_node tells sflow how many GPU indices each node has for planning and
packing. It does not add --gpus-per-node to salloc; include that flag in
extra_args when your cluster requires it.
The Slurm backend requires account, partition, time, nodes, and gpus_per_node
(set gpus_per_node: 0 for CPU-only partitions).
If you are already inside a Slurm allocation (e.g. via salloc or sbatch), you can use:
sflow run --file sflow.yaml
This skips salloc and attempts to infer node info from the current environment (SLURM_JOB_ID/SLURM_JOB_NODELIST).
docker backend
The docker backend runs each task in a container via the docker_run operator. Set
image and gpus_per_node; an optional hosts: pool spreads tasks across remote Docker
daemons. See Backends.
kubernetes backend
The kubernetes backend reserves real nodes and runs each task as scheduler-placed
pod(s). The backend carries cluster/access config (namespace, nodes, gpus_per_node,
scheduling); the workload image lives on a k8s operator, not the backend. Cluster
selection and credentials are sflow run CLI flags, not YAML. See
Backends.
operators
An operator defines how a task is launched. sflow ships seven operator types:
bash: run locally via bashsrun: run via Slurmsrun(supports common Pyxis--container-*flags)docker_run: run inside a container viadocker runpython: run the script through a Python interpreterssh: run on a remote host over SSHk8s: run as a Kubernetes pod (the workloadimagelives on this operator)k8s_mpi: run any MPI (mpirun) job on Kubernetes — single- or multi-node (writempirunexplicitly)
If a task does not set operator:, the backend picks a default: local → bash,
slurm → srun, docker → docker_run, kubernetes → none (you must declare a k8s
operator). Note the Docker naming: the backend is type: docker, but its launch
operator is type: docker_run. See
Operators for per-type fields and examples.
Example (bash):
operators:
local_bash:
type: bash
Example (srun + container):
operators:
runtime:
type: srun
container_image: nvcr.io/xxx/yyy:tag
container_mount_home: false
container_mounts:
- "/mnt:/mnt:rw"
extra_args:
- "--shm-size=64g"