Getting Started
Set up SWE-Lego-RL and launch your first training run
Every workload — training, evaluation, or batch inference — follows the same five steps:
1. build the venv bash scripts/setup_env.sh (once per machine)
2. describe the cluster cp lib/site.example.env lib/site.env (once per cluster)
3. copy a template cp train/templates/X.env train/configs/mine.env
4. validate PREFLIGHT_ONLY=1 then DRY_RUN=1 (checks only, nothing launches)
5. launch bash scripts/train/train.sh train/configs/mine.envReplace train with eval (score a checkpoint) or infer (batch trajectory
generation) for the other two workloads.
Launch paths
Steps 1–3 are identical either way. Steps 4–5 have two equivalent paths: run the
runner by hand, or pass the config to the
agent plugin (/rl:* skills for
Claude Code), which validates it, requires an
explicit confirmation, and launches the same runner.
| Manual | Through the agent | |
|---|---|---|
| Validate | PREFLIGHT_ONLY=1 bash scripts/train/train.sh <config> | /rl:check <config> |
| Launch | bash scripts/train/train.sh <config> | /rl:run <config> |
| Watch | tail -F logs/<exp>.log | /rl:status |
| Serve the dashboard | bash webui/start_dashboard.sh | /rl:dashboard |
Both paths run the same scripts/lib/preflight.sh. The agent adds live-machine
checks — a run already in flight, foreign GPUs, a taken port — and a structured
verdict; see Agent Plugin.
Prerequisites
- 8× GPU (A100/H100-class) on the training node — on the single-node path vLLM serves the policy and verl runs the trainer on the same host.
- A sandbox backend — a reachable Kubernetes cluster (production) or a Docker daemon (local or remote) for Harbor to run each trial in.
- uv — used by
scripts/setup_env.shto build the training venv. - A policy checkpoint — e.g. an SFT-trained Qwen3 model on local disk.
- Train/val task indexes: thin parquet
pointer tables the trainer samples from —
build one with
utils/create_task_index.py, or produce a difficulty-filtered one with batch inference. - Task environment images, prebuilt and pushed to a registry the cluster can
reach. An unreachable image source is the most common cause of a first run that
produces nothing but
env_setup_failed— see Site variables.
Run inside tmux
A training run lasts hours. Launch it in a tmux session, or with nohup setsid,
so it survives a shell disconnect.
1. Venv
scripts/setup_env.sh builds the venv at .venv via uv, and clones + editably
installs harbor and verl (plus pinned vllm / flash_attn / transformers / cupy).
It is idempotent:
bash scripts/setup_env.shKey overrides (env vars): VENV_PATH, HARBOR_DIR / VERL_DIR (clone locations),
HARBOR_REF / VERL_REF (branches), PYTHON_VERSION (default 3.12.3), and the
SKIP_CLONE / SKIP_FLASH_ATTN / SKIP_CUPY flags. Confirm the editable installs
resolve to the trees you expect:
.venv/bin/python -c "import harbor, verl, verl_patch; print(harbor.__file__)"2. Site config
Everything cluster-specific lives in one file, never in a run config:
cp scripts/lib/site.example.env scripts/lib/site.env
$EDITOR scripts/lib/site.envSet at least MODEL_ROOT (checkpoint location) and K8S_KUBECONFIG, plus
HARBOR_OPENSWE_IMAGE_REGISTRY if a prebuilt-image registry exists. An empty value
is legal and falls back to the portable, slower path.
Site variables lists the full surface.
Once per cluster
Every runner sources site.env automatically. No file below this step holds a cluster
address, so a run config is portable to a colleague's cluster once they write their
own site.env.
3. Run config
Templates are named by their axes: <mode>_<backend>_<scaffold>_<model>.env.
Copy the one matching the run into configs/:
ls scripts/train/templates/
# async_k8s_ohsdk_qwen35a3b.env sync_k8s_ohsdk_qwen35a3b.env
# async_k8s_cc_qwen3-30b-a3b.env sync_docker_oh_qwen3-30b-a3b.env ...
cp scripts/train/templates/sync_k8s_ohsdk_qwen35a3b.env \
scripts/train/configs/my_first_run.envEdit only the CHANGEME lines — experiment name, data indexes, topology:
PROJECT_NAME=my-project
EXP_TAG=first-run
MODEL_PRESET=qwen35a3b # fills MODEL_PATH / TOOL_PARSER / ENGINE / SP_SIZE / window
TRAIN_INDEX=/data/harbor_indexes/train.parquet
VAL_INDEX=/data/harbor_indexes/val.parquet
NNODES=1Everything else has a default. A knob the template does not mention takes one
KEY=VALUE line — see parameter tiers.
Smoke first
On a new model, scaffold, or cluster, start from a smoke config (TRAIN_BSZ=8
N_RESP=4): ~8× faster per step, and it exercises the whole path. Its gradients are
noisy and its reward groups degenerate, so it is a plumbing check only, never a
learning-quality signal.
4. Validation
Every runner understands two switches. Both resolve the config, print a report, and exit without touching a GPU or a cluster. Run them in this order:
# 1. config validation — 9 classes of fatal assertion, no cluster needed
PREFLIGHT_ONLY=1 bash scripts/train/train.sh train/configs/my_first_run.env
# 2. print the fully expanded launch command without running it
DRY_RUN=1 bash scripts/train/train.sh train/configs/my_first_run.envPreflight stops on any ✗ FATAL. It catches the mistakes that otherwise cost a
multi-hour run: a tool_parser that does not match the model × scaffold pair, node
counts that do not add up, an SP_SIZE that does not divide the training world, R3
without the new verl tree, no reachable image source.
Preflight lists all nine assertion classes.
The agent equivalent is /rl:check <config>: the same assertions plus live-machine
checks.
5. Launch
bash scripts/train/train.sh train/configs/my_first_run.envThe agent equivalent is /rl:run train/configs/my_first_run.env, which launches in
the background after an explicit confirmation.
The runner brings up Ray, boots vLLM, starts the in-process proxy, and drives the
PPO/GRPO/GSPO loop. On a 30B MoE at TP=4, vLLM CUDA-graph capture takes 10–20 minutes
before the first replica registers; this is expected. If a previous run left Ray or
vLLM processes behind, clear them first with bash scripts/cleanup_before_run.sh.
6. Monitoring
tail -F logs/<exp>.log
bash webui/start_dashboard.sh # http://<host>:8090 (+ public tunnel)Checkpoints land under checkpoints/<project>/<exp>/global_step_N/. See
Results & Artifacts and
Dashboard.
Other workloads
The other two workloads use the same contract: copy a template, fill the
CHANGEME lines, validate, run.
| Goal | Runner | Guide |
|---|---|---|
| Train a policy | scripts/train/train.sh | this page |
| Score a checkpoint on a held-out set | scripts/eval/eval.sh | Evaluation |
| Batch-generate trajectories over an index | scripts/infer/infer.sh | Batch Inference |
When one host is no longer enough — large MoE policies, ~131k contexts, or
rollout-bound throughput — switch to an async_* template and add nodes; see
Scaling Up.