Skip to navigation

Configuration Reference

View as Markdown

A submit config is a YAML file with the top-level sections services, compute, driver, job, and optionally otel. All models are strict: an unknown key anywhere is an error, which is how typos surface. Top-level keys that start with _ are the exception; they are scratch namespaces for interpolation and are dropped before validation.

Fields without a default are required.

env values

env appears on every service and on the driver. Every value must start with one of three prefixes; a missing or misspelled prefix is an error, not a guess.

PrefixMeaning
lit:VALUEThe literal VALUE.
host:VARThe value of VAR in the shell running gym eval submit. The submit fails if VAR is unset. The value is baked into the job script.
runtime:VARNot resolved at submit time. The job script references $VAR, so the compute node uses whatever the job’s environment holds when the command starts.
env:
HF_TOKEN: host:HF_TOKEN
TRUST_REMOTE_CODE: lit:1
CUDA_VISIBLE_DEVICES: runtime:CUDA_VISIBLE_DEVICES

VAR must be a valid environment variable name. host: values are resolved when the config is validated, so they must be set for --resolve-only too. In the persisted resolved-config.yaml and gym-job.json the original host:VAR reference is written back, not the secret.

services

A mapping from service name to a service definition. The type field selects the kind: vllm, vllm_pd, or ray. Service names are free-form, but they become part of log file names and shell variable names.

Fields common to every service

FieldDefaultDescription
containerrequiredContainer image the service runs in (srun --container-image).
placementthe only compute resourceName of the compute entry to run on. Filled in automatically; there can only be one compute resource.
node_poolnullName of a pool in the compute’s node_pools. Pins the service to that pool’s nodes. null means the whole allocation. See Node pools.
health_checksee per typepath (default /health), port, and timeout_seconds (default 60). The job waits for this endpoint before starting the driver, polling every 5 seconds.
env{}Environment for the service. See env values.
mounts[]Pyxis bind mounts, each src, src:dst, or src:dst:flags (for example /data:/data:ro). Source paths are checked for existence before anything is copied.
pre_command""Shell statements run in the same shell, before the service command. Use it for export/unset or values like $(hostname -I) that env cannot express.

type: vllm

A vLLM server, started with vllm serve.

FieldDefaultDescription
modelrequiredModel name or path passed to vllm serve.
port8000Port the server listens on.
served_model_namenullName the model is served under. Defaults to model when used as the policy.
tensor_parallel_size1Tensor-parallel size of one instance.
pipeline_parallel_size1Pipeline-parallel size of one instance.
number_of_instances1Data-parallel replicas. Must be at least 1.
trust_remote_codefalseAdds --trust-remote-code.
use_ray_servefalseForce the Ray Serve gateway to manage instances and routing.
extra_args""Raw flags appended verbatim to vllm serve, for example --max-model-len 8192.
data_parallel_rpc_port13345Port the data-parallel ranks of a multi-node service coordinate on.

If health_check is not set, it defaults to /health on port. If it is set without a port, the service’s port is used.

type: vllm_pd

Prefill/decode disaggregated vLLM: two vLLM tiers behind a vllm-router. A single vllm_pd entry named X deploys three services: X-prefill, X-decode, and the router X. Set driver.policy_model to X. The router’s container must provide vllm-router. See the how-to.

FieldDefaultDescription
container, model, served_model_namecontainer and model requiredInherited by both tiers unless a tier sets its own.
port8000The router’s port. Prefill defaults to port + 1 and decode to port + 2.
prefill, decoderequiredA vllm service definition for each tier. Each tier needs its own node_pool.
server_per_nodefalseRun an independent server on every node of each tier instead of one data-parallel engine across them. The router then lists each node as an endpoint. Set on the vllm_pd entry, not on a tier.
nixl_side_channel_port5600Prefill’s NIXL side-channel port. Decode uses this plus 1. Set on the vllm_pd entry, not on a tier.
prefill_policy, decode_policycache_awareRouter routing policies.
intra_node_data_parallel_size1Passed to the router.
request_timeout_secs86400Router request timeout. Long because agentic benchmarks hold requests open.
log_levelerrorRouter log level.
kv_connectorNixlConnectorKV-transfer connector for both tiers.
kv_load_failure_policyfailfail surfaces a broken KV transfer instead of silently recomputing the prefill.

type: ray

A Ray cluster. The head starts on the driver’s node and every other node of the spanned pools joins it as a worker.

FieldDefaultDescription
node_pools[]Pools the cluster spans (note the plural; node_pool is rejected on a ray service). Empty means a single-node cluster. A pool may be listed once.
port6379Head port.
resources{}Custom Ray resources per pool, for example {aux: {extra_gpu: 4}}. Every pool named here must also be in node_pools.
num_cpus, num_gpusnullPassed to ray start.
extra_args""Raw flags appended to ray start on every node. Head-only flags (--port, --redis-shard-ports, --include-dashboard) are dropped for workers.

A ray service is not a model service: it cannot be driver.policy_model for URL injection, and it has no default health check. The head’s address is exported to the job as GYM_RAY_ADDRESS_<SERVICE> (service name upper-cased, non-alphanumerics replaced by _).

compute

A mapping with exactly one entry; its key is a name you choose (the examples use cluster). More than one is an error.

type: slurm

FieldDefaultDescription
accountrequiredSlurm account (--account).
hostnamenullLogin node to submit through over SSH. null, or the name of the machine you are on, means run sbatch locally with no SSH.
walltimenullJob time limit (--time).
forward_env[]Environment variable names to forward from the submitting shell to sbatch. Missing variables fail submission before staging. Values are sent over SSH stdin and are not stored in job artifacts.
node_pools{}Named groups of nodes. See below.
extra_args{}Extra job-level #SBATCH directives, written without leading dashes: {comment: my-run} becomes #SBATCH --comment=my-run.

Use forward_env with runtime: for credentials needed by a remote job:

compute:
cluster:
type: slurm
hostname: login.example.com
account: my-account
forward_env: [HF_TOKEN, INFERENCE_API_KEY]
driver:
env:
HF_TOKEN: runtime:HF_TOKEN
INFERENCE_API_KEY: runtime:INFERENCE_API_KEY

Only listed names are forwarded. Leave scheduler-provided values such as CUDA_VISIBLE_DEVICES out of this list. --resolve-only and dry runs do not require forwarded values to be set. Slurm must export the submission environment to the job; an explicit --export=NONE prevents that inheritance.

Node pools

FieldDefaultDescription
partitionrequiredSlurm partition.
nodes1Number of nodes in the pool.
ntasks_per_node1Tasks per node.
gpus_per_nodenullGPUs per node (--gpus-per-node). Also used to size and check vLLM deployments.
extra_args{}Extra #SBATCH directives, written without leading dashes.

A benchmark is one Slurm job. Pools do not create separate Slurm requests; they divide the one allocation between services. The job requests the sum of every pool’s nodes, and pool i owns the contiguous node range after all pools before it, in declaration order. Because Slurm takes one value per job, pools must agree on partition, ntasks_per_node, and gpus_per_node, and may not set the same extra_args key to different values. Disagreement is an error.

driver

The driver runs the benchmarks against the services.

FieldDefaultDescription
containerpython:3.12Image the driver runs in.
gym_installnullrepo (default https://github.com/NVIDIA-NeMo/gym) and ref (required; a git tag or commit). When set, the driver installs Gym from that checkout into a fresh virtual environment, with uv, before running. When unset, the image must already contain Gym.
policy_modelnullName of a service to use as the policy model. See Policy wiring.
policy_hostlocalhostHost used in the injected policy_base_url. Use an address routable from elsewhere when an agent runs remotely, for example ${oc.env:HEAD_NODE_IP}, which is resolved when the driver runs.
policy_model_typeopenai_modelThe responses_api_models asset passed to gym eval run as --model-type. Set it to "" to pass none, for a benchmark whose own config already declares a complete policy model.
benchmarksrequiredMapping from benchmark name to its run config.
env{}Environment for the driver. See env values.
mounts[]Extra bind mounts for the driver. The benchmark’s own job directory is always mounted at the same path.

Policy wiring

When policy_model names a vllm or vllm_pd service, each benchmark’s run config receives:

  • policy_base_url: http://<policy_host>:<service port>/v1
  • policy_model_name: the service’s served_model_name, or its model
  • policy_api_key: a dummy value (vLLM does not require authentication)

If a benchmark’s run already sets any of these keys, validation fails: remove one or the other. policy_model must name an existing service.

benchmarks

Each key under driver.benchmarks is a benchmark name. It must match ^[A-Za-z0-9._-]+$, because it is used in job names and in the line each sbatch reports back.

FieldDefaultDescription
prepare{}Overrides forwarded to gym eval prepare. When non-empty, gym eval prepare runs in the driver before the benchmark.
run{}Overrides forwarded to gym eval run.
commandnullA shell script that runs instead of gym eval run. See Custom Harness. Cannot be combined with run or resumable.
resumablefalsetrue for auto-resume with defaults, or {max_retries, max_walltime} to tune it. See Resumable Runs.

prepare and run are nested mappings that are flattened to Hydra overrides: {split: benchmark, config_paths: [a.yaml, b.yaml]} becomes +split=benchmark and +config_paths=[a.yaml,b.yaml], and nested keys become dotted paths.

Submit sets a few defaults on run that you can override:

KeyDefaultEffect
output_jsonl_fpath<benchmark dir>/artifacts/rollouts.jsonlAlways set by submit as an absolute path.
require_completetrueFail the evaluation if any samples are incomplete.
observability_enabledtrueCapture rollout evidence.
model_call_capture_dir<benchmark dir>/model-callsWhere captured model calls are written, when observability is on.
resume_from_cachetrue when resumable is setLets a resumed job continue from the cache.

resumable

FieldDefaultDescription
max_retries3How many times a non-timeout failure is resubmitted, so a broken benchmark does not requeue forever.
max_walltimenullCap on the chain’s total accumulated walltime as a Slurm-style duration (MM, MM:SS, HH:MM:SS, D-HH, D-HH:MM, D-HH:MM:SS). null means no cap.

Asking for resumable on an executor that does not support it is an error rather than a silent no-op.

job

FieldDescription
output_pathBase directory on the cluster. Each submit creates a timestamped subdirectory here.

otel

The OpenTelemetry collector that runs beside every benchmark job. It is enabled by default, and an enabled collector requires endpoint, service_name, and the token variable (token_env, default OTEL_TOKEN) to be set in the submitting shell. Set enabled: false to opt out. All fields, and what is exported, are described in Collector for Submitted Jobs.

Cross-field validation

Schema validation runs when the config is composed, before anything is rendered or contacted. --resolve-only performs these checks and stops. The pool-agreement checks listed at the end are made later, while the script is rendered, so use --dry-run to verify them:

  • One compute resource. More than one is rejected. A service’s placement must name it.
  • Node pool references. A service’s node_pool, and every pool in a ray service’s node_pools, must exist in the compute’s node_pools.
  • Tier name collisions. A vllm_pd service X deploys X-prefill and X-decode; services must not already contain those names.
  • Prefill/decode tiers each need a node_pool, must use different data_parallel_rpc_port values, and with server_per_node must have number_of_instances: 1. The router, if pinned, must be pinned to the first pool, since the driver reaches it over localhost on the first node.
  • vLLM GPU footprint (when pools declare gpus_per_node). The GPUs a service needs are compared with what it can use. Too few is an error that names the footprint; too many is a warning that GPUs would idle. The calculation depends on the deployment shape:
    • single node: tensor_parallel_size x pipeline_parallel_size x number_of_instances against one node’s GPUs;
    • one instance across nodes: tensor_parallel_size x pipeline_parallel_size against all GPUs of the nodes;
    • multi-node data parallel: the per-node share of replicas against one node’s GPUs; and
    • Ray Serve gateway: the total footprint against all GPUs.
  • Multi-node data parallelism requires number_of_instances to be evenly divisible by the number of nodes, unless the Ray Serve gateway is in use.
  • Policy wiring conflicts, as described above.
  • Benchmark command combined with run or resumable is rejected.
  • Pool agreement (checked at render time, not by --resolve-only). Pools used together by one job must agree on partition, tasks, GPUs, and extra directives. A mismatch fails --dry-run and the real submit.

Mount source existence, SSH reachability, and OTel destination checks happen later, at submit time.