Module:
rllm.trainer.backend_protocolBackendProtocol is the abstract interface that decouples the
unified trainer from any specific training infrastructure.
By implementing this protocol, you can plug in any model-serving, optimization, and
checkpointing system while reusing the trainer’s episode generation, data
transformation, rejection sampling, and logging machinery.
Class signature
TDataset— the iterable type returned byget_dataloader(e.g.torch.utils.data.DataLoader)TBatch— the batch type consumed by your pipeline methods (e.g.list[tinker.Datum])
What a backend provides
A backend implementation is responsible for four categories of functionality:Setup methods
init_rollout_engine(**kwargs) -> RolloutEngine
Called once during trainer initialization. The backend must create and return a
RolloutEngine that the workflow engine will use for model inference. The trainer
passes the parsed config objects as keyword arguments:
validate_config() -> None
Called during trainer initialization to validate backend-specific configuration.
Raise or warn on invalid settings.
get_dataloader(dataset, trainer_state) -> TDataset
Called at the start of each epoch (training) and at each validation round. Use
trainer_state.is_training to distinguish between training and validation and
return the appropriate dataloader.
shutdown() -> None
Called when the trainer is torn down. Release GPU memory, close connections, etc.
Pipeline methods
These are called by the trainer in a fixed order during each training batch. TheTrainerState object is the shared mutable context throughout a batch.
Stage 1: generate_episodes
- Prepares the batch (e.g. repeat each task
group_sizetimes for GRPO) - Sets the current model on the rollout engine
- Delegates to
agent_workflow_engine.execute_tasks(...)
Stage 4: transform_to_backend_batch
TrajectoryGroup objects into your backend-native format.
This is a sync method since it is typically pure data transformation.
Some backends defer transformation to process_backend_batch and return a
placeholder here.
Stage 5: process_backend_batch
- Run a forward pass to compute training logprobs
- Run a backward pass to compute gradients
- Store results in
trainer_state.backend_batchandtrainer_state.extra_info
trainer_state in place (no return value).
Stage 6: compute_advantages
Step objects within each
trajectory. The base class provides a default implementation using rLLM-native
advantage estimators (GRPO, REINFORCE):
Step objects
(e.g. computed during episode generation via a workflow decorator), the default
implementation detects this and skips re-computation.
Stage 7: update_policy
process_backend_batch and make update_policy a no-op (see
flexible stage organization below).
Lifecycle hooks
All hooks areasync def methods with default no-op implementations. Override only
what you need.
Training hooks
Validation hooks
Common uses for hooks
on_batch_end runs after the pipeline but before logger.log(...). This makes it the right place to inject derived metrics (e.g. KL divergence, learning rate) into trainer_state.metrics.
Flexible stage organization
The protocol defines stages 4-7 as separate methods, but backends are free to redistribute work across them. The trainer always calls them in the same order — it is the backend’s responsibility to decide what each stage does internally.Example: TinkerBackend’s fused mode
TheTinkerBackend demonstrates this flexibility. When
fuse_forward_backward_and_optim_step is enabled:
Example: Pre-computed advantages
For workflows that compute per-token advantages during episode generation (stage 1) — for example, distillation flows that derive a reverse-KL signal from a teacher policy — everyStep already has its .advantage field set
by the time compute_advantages (stage 6) runs. The default implementation
in BackendProtocol detects this and skips re-computation, collecting only
metrics.
This means such workflows can use the standard TinkerBackend directly —
no custom backend subclass is needed.
Implementing a custom backend
1
Subclass BackendProtocol
2
Implement required methods
At minimum, implement these abstract methods:
3
Override lifecycle hooks as needed
4
Wire it up
Reference: TinkerBackend
TheTinkerBackend (rllm.trainer.tinker.tinker_backend) is the primary
production backend. It serves as a comprehensive reference implementation.
Setup
Pipeline
Lifecycle hooks
Key patterns
-
Deferred transformation.
transform_to_backend_batchreturns a placeholder; the real work happens inprocess_backend_batch. This is valid because the trainer only checkstrainer_state.has_backend_batchafterprocess_backend_batchruns. -
Checkpoint-driven sampling client. The
sampling_client(used by workflows for inference) is updated inon_batch_endafter each checkpoint save. This ensures workflows always sample from the latest policy. -
Metrics injection in
on_batch_end. Sinceon_batch_endruns after the pipeline but beforelogger.log(...), it is the natural place to compute derived metrics (KL divergence, entropy, learning rate) and add them totrainer_state.metrics.

