Cluster workflow¶
The Slurm workflow schedules complete, declarative run configs. A campaign
manifest chooses which run configs start in parallel; each selected run config
then executes its experiments list serially through heams run.
cluster/campaigns/<campaign>.sh
-> one Slurm job per listed configs/runs/<run>.yaml
-> heams run --config configs/runs/<run>.yaml --output-dir <campaign-root>/<campaign-instance>/<index>_<run-stem>
-> experiments execute serially
The cluster scripts supply only the artifact output directory. Model, memory, benchmark, limit, and concurrency settings remain authoritative in the referenced YAML component and run configs.
Define a campaign¶
Create a file under cluster/campaigns/. This is the single, human-editable
list of run configs that should execute in parallel. The bundled
cluster/campaigns/smoke_campaign.sh:
CAMPAIGN_NAME="smoke_campaign"
SLURM_TIME="04:00:00"
CPUS_PER_TASK=1
MEM_PER_TASK="16G"
RUN_CONFIGS=(
"smoke_campaign/no_memory.yaml"
"smoke_campaign/in_context.yaml"
"smoke_campaign/milamem.yaml"
"smoke_campaign/mem0.yaml"
)
Campaign submissions always pass --requeue to sbatch. This enables the
Slurm requeue behavior supported by the site. HEAMS does not add time-limit
signal handling or automatic retries for application errors.
RUN_CONFIGS entries reference YAML files only under configs/runs/. Paths
such as ../run.yaml and missing files are rejected. Each entry is checked just
before its job is submitted, so an invalid entry stops the loop after the
earlier entries were already submitted. The
campaign definition sets one shared resource profile for all of its run configs:
SLURM_TIME, CPUS_PER_TASK, MEM_PER_TASK, and optional GRES (for example
gpu:1). Define a separate campaign when runs need different resource
profiles. An optional RUN_WRAPPER names a script under cluster/ that each job
runs instead of uv run heams run, with the same arguments; Letta campaigns use
cluster/letta/run_with_postgres.sh to start a job-local Postgres (one-time setup:
cluster/letta/setup_postgres.sh).
Cluster settings¶
Settings that depend on your cluster are not stored in campaign files. Set them in your environment, for example in your shell profile on the cluster:
| Variable | Meaning |
|---|---|
PARTITION |
Slurm partition for every job. When unset, Slurm uses the cluster's default (or SBATCH_PARTITION) |
SLURM_ACCOUNT |
Slurm account to charge. When unset, no --account is passed |
GRES |
Generic resources passed as --gres, for example gpu:1 for runs that embed on a GPU. When unset, no --gres is passed |
RUN_WRAPPER |
A script under cluster/ that each job runs instead of uv run --python 3.12 heams run; it receives the same --config and --output-dir arguments and runs heams itself. For example, cluster/letta/run_with_postgres.sh starts a private Postgres for Letta jobs |
A campaign file may still set these itself; a value set there overrides the environment.
Prepare the cluster checkout¶
On the cluster, clone the repository and create the untracked .env
file in that checkout.
git clone <repository-url> ~/heams
cd ~/heams
cp .env_template .env
$EDITOR .env
cd python_package
make setup
The .env file supplies credentials such as OPENAI_API_KEY; it is ignored by
Git and belongs only on the cluster checkout that will submit and execute the
jobs. Complete setup before submitting a campaign, then do not run make setup,
uv sync, or uv pip install in that checkout while its jobs are pending or
running. Campaign submission and jobs use the existing environment without
synchronizing it.
Before submitting a full campaign, run a small config-driven job from the login node to verify credentials, dependency installation, and download access:
uv run --python 3.12 heams run --config configs/runs/testing/locomo_smoke.yaml --output-dir results/locomo_smoke
The Slurm compute nodes must have outbound access to the model provider and the LoCoMo dataset URL if the dataset is not already cached. On clusters where compute nodes cannot download data, ask the cluster administrator for a shared dataset location or materialize the dataset from a networked login node before submitting jobs.
Submit a campaign¶
cd /path/to/heams/python_package
PARTITION=my-partition cluster/submit_campaign.sh cluster/campaigns/smoke_campaign.sh /scratch/$USER/heams
Or use the Make wrapper, which defaults to the smoke_campaign campaign
and an output root of results/campaigns (under python_package/):
Both the Make target and direct invocations of submit_campaign.sh use the
same unconditional requeue behavior.
Set CAMPAIGN or CAMPAIGN_OUTPUT_DIR to choose a different campaign or output
root.
The script submits one Slurm job per run-config entry, checking each entry just
before submitting it. It does not install or synchronize dependencies. The second argument
is a campaign output root. At submission time, the script creates one shared
campaign directory named
<campaign-name>_<UTC timestamp>-<short UUID> beneath that root. Each listed
config receives one distinct stable exact run directory named
<index>_<run-stem> below the campaign instance. Requeued or manually repeated
attempts must use that same command and directory.
Each job runs:
exec srun uv run --python 3.12 heams run --config configs/runs/<run>.yaml --output-dir /scratch/$USER/heams/smoke_campaign_20260727-163603-a1b2c3d4/01_<run-stem>
For example, a campaign submitted to /scratch/$USER/heams
produces this layout:
/scratch/$USER/heams/
└── smoke_campaign_20260727-163603-a1b2c3d4/
├── 01_smoke_campaign_no_memory/
│ ├── run_config.20260727-163611-8df325f0.yaml
│ └── gpt56_luna_no_memory_locomo/
│ ├── experiment_config.20260727-163611-8df325f0.yaml
│ └── workspace/
├── 02_smoke_campaign_in_context/
│ ├── run_config.20260727-163614-3c7e91ab.yaml
│ └── gpt56_luna_in_context_locomo/
│ ├── experiment_config.20260727-163614-3c7e91ab.yaml
│ └── workspace/
├── 03_smoke_campaign_milamem/
├── 04_smoke_campaign_mem0/
└── logs/
└── ...
The smoke campaign is organized around memory systems rather than benchmarks.
It submits four run-config jobs: no_memory, in_context, milamem, and
mem0. Each job runs nine benchmark experiments, for 36 experiments total.
Slurm stdout and stderr logs are stored in the campaign instance's logs/
directory alongside the run artifacts. Override REMOTE_REPO when the checkout
layout differs. Credentials
remain in the repository-root .env and are never copied into a campaign
definition or Slurm command.
Results and retention¶
Scratch directories are temporary. Copy final result directories and logs to durable storage according to cluster policy after the campaign completes.
Browse results¶
To review campaign results without copying them off the cluster, run
heams browse as a CPU job and open it from your laptop through an SSH tunnel:
see Viewing cluster results from your laptop.