Skip to main content
The rLLM framework provides a unified configuration system that separates backend-agnostic settings from backend-specific configurations. This design allows you to switch between different RL backends (Tinker, Verl) while maintaining consistent core training logic.

Configuration structure

The configuration system is organized into three main components:
  1. rLLM backend-agnostic configs: Core training settings shared across all backends
  2. Backend-specific configs: Settings specific to Tinker or Verl backends
  3. Forwarding mechanism: Allows backend-specific configs to override rLLM configs for backward compatibility
All configuration files are located in rllm/experimental/config/:
  • rllm/experimental/config/rllm/base.yaml: Backend-agnostic rLLM configurations
  • rllm/experimental/config/rllm/backend/tinker.yaml: Tinker-specific configurations
  • rllm/experimental/config/rllm/backend/verl.yaml: Verl-specific configurations
  • rllm/experimental/config/unified.yaml: Main entry point that combines all configs

rLLM backend-agnostic configurations

These configurations are defined in rllm/base.yaml and are used across different backends.

Agent configuration

Settings for the agent that interacts with the environment.

Environment configuration

Settings for the environment where the agent operates.

Workflow configuration

Settings for workflow-based training (alternative to agent-based training).

Rollout configuration

Settings for trajectory rollouts during training and validation.
These settings are primarily for logging purposes. The actual rollout behavior is determined by backend-specific configurations.

Trainer configuration

Core training loop settings.

Algorithm configuration

RL algorithm and advantage estimation settings.

Stepwise advantage configuration

Settings for computing advantages at each step in multi-step trajectories.

Trajectory processing flags

Top-level flags for trajectory processing and filtering.

Compact filtering configuration

Fine-grained filtering of trajectories based on various termination conditions.

Rejection sampling configuration

Settings for rejection sampling to improve training data quality.

SDK configuration

Settings for the rLLM SDK, including trace storage and proxy server.

Episode logging configuration

Settings for logging full episode trajectories to disk.

Backend-specific configurations

Tinker backend

Tinker-specific settings live in rllm/experimental/config/rllm/backend/tinker.yaml. This file contains:
  1. Tinker service and execution settings
  2. Model/LoRA training settings
  3. Sampling and rollout-engine settings
  4. Tinker-native training/data blocks
  5. Forwarding into rllm.* common config keys

Top-level Tinker-specific keys

Model block

Training block (Tinker-native)

Validation, sampling, rollout, and data blocks

Forwarding to common rllm.*

Tinker backend forwards group-size settings into backend-agnostic rollout config:
  • rllm.rollout.n <- training.group_size
  • rllm.rollout.n_val <- validation.group_size

Verl backend

Verl-specific settings live in rllm/experimental/config/rllm/backend/verl.yaml. This file is intentionally thin and composes Verl’s native PPO config via:
For detailed semantics of Verl-native fields, see the Verl configuration docs. In rLLM, the verl.yaml only does two things:
  1. Sets a small number of required overrides for unified-trainer compatibility (e.g. actor_rollout_ref.rollout.mode=async, actor.use_rollout_log_probs=True).
  2. Pins one rllm-namespaced default that diverges from verl’s (rllm.algorithm.rollout_correction.bypass_mode=False).
Everything else — propagating values between the verl-native namespace and the rllm.* namespace — happens at runtime via sync_config in rllm/experimental/verl/utils.py.

Key fields in verl.yaml

All other shared knobs (algorithm.adv_estimator, actor.kl_loss_coef, trainer.total_epochs, …) live in their natural locations — verl-native keys come from ppo_trainer.yaml, rllm-namespace keys from base.yaml — and are reconciled at startup by sync_config.

Bidirectional config sync

For a fixed table of “shared keys” (the same value, different paths in the two namespaces), sync_config mirrors the value between the verl-native side and the rllm.* side at trainer startup. New configs should use the rllm.* path. Existing Verl-style CLI overrides still work for backward compatibility, but they log a deprecation warning. Per-key precedence:
  1. rllm.* value explicitly set on the Hydra CLI
  2. Verl-native value explicitly set on the Hydra CLI
  3. rllm.* value from base.yaml (when non-null)
  4. Verl-native value from ppo_trainer.yaml
Verl-native shared-key CLI overrides are deprecated. If you set a shared key on the Verl-native side, rLLM will still sync it for now and log a warning. If both sides set conflicting values, the rllm.* value wins and rLLM logs a conflict warning. Passing an extra yaml/config group to override shared keys is not a supported migration path; pass shared values as individual Hydra overrides instead.
The shared-keys table: Two extra rules sit alongside this table:
  • actor.use_kl_loss is derived from kl_beta: if you do not explicitly set actor_rollout_ref.actor.use_kl_loss on the CLI, sync_config sets it to (kl_beta > 0). Setting rllm.algorithm.kl_beta also mirrors into actor_rollout_ref.actor.kl_loss_coef. Setting the Verl-native coefficient still backfills rllm.algorithm.kl_beta for now, with a deprecation warning.
  • clip_ratio family. rllm.algorithm.eps_clip mirrors to actor_rollout_ref.actor.clip_ratio and actor_rollout_ref.actor.clip_ratio_low. If rllm.algorithm.eps_clip_high is set, it mirrors to actor_rollout_ref.actor.clip_ratio_high; otherwise the upper bound mirrors eps_clip. Verl-native clip_ratio, clip_ratio_low, and clip_ratio_high still backfill the rLLM values for now when the rLLM side is not set, with deprecation warnings.
It also extends the Hydra search path so /ppo_trainer resolves:

Config forwarding mechanism

The Verl backend uses bidirectional sync (described above): for any shared key, the preferred path is rllm.*, while legacy Verl-native shared-key CLI overrides still work with deprecation warnings. The Tinker backend does its own one-way forwarding from native group-size settings into rllm.rollout.{n,n_val} (see “Tinker backend” above).

Example: set the preferred shared knob

Set adv_estimator on the rllm.* side:
A legacy Verl-native override still works for now, but logs a deprecation warning:
If both are set and conflict, the rllm.* value wins.

Example: KL-in-loss

Setting rllm.algorithm.kl_beta=0.01 is enough — actor.kl_loss_coef is mirrored and actor.use_kl_loss is auto-set to True:
The legacy Verl-native equivalent still works for now, but logs a deprecation warning:

Benefits

  • Backward compatibility. Existing scripts that override on the verl-native side continue to work while logging deprecation warnings; the rllm-side value is mirrored automatically.
  • Backend portability. New scripts can target the backend-agnostic rllm.* namespace and run on either Tinker or Verl with the same flags.
  • Single source of truth at runtime. No oc.select interpolation in the yaml; the merged config that goes to verl’s workers and rLLM’s trainer holds the same values on both sides.

Configuration best practices

  1. Use rLLM configs for new projects: If starting from scratch, use the rLLM backend-agnostic configs for better portability across backends.
  2. Use rLLM paths for shared knobs: Existing Verl-native shared-key overrides still work for compatibility, but new configs should use rllm.*.
  3. Check the unified config: The unified.yaml file shows how all configs are combined and is useful for debugging configuration issues.
  4. Understand defaults hierarchy: Backend-specific configs override rLLM defaults, which in turn override Hydra’s base defaults.