TorchRL specs are metadata containers that describe what a tensor should look like — its shape, dtype, device, and the mathematical domain it lives in. They are attached to every environment underDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/pytorch/rl/llms.txt
Use this file to discover all available pages before exploring further.
observation_spec, action_spec, reward_spec, and done_spec, and are propagated automatically through transforms and wrappers. Specs serve three main purposes: shape and dtype checking (catching bugs before a backward pass), automatic action sampling via spec.rand() (random agents, exploration layers, and testing), and transform validation (ensuring that a transform’s output remains in the expected domain).
The spec class names were shortened in recent TorchRL versions. The canonical names (
Bounded, Categorical, OneHot, Composite, Unbounded, etc.) are exported from torchrl.data. The legacy long names (BoundedTensorSpec, DiscreteTensorSpec, CompositeSpec, …) are no longer available and should not be used.Why Specs Matter
Base Class: TensorSpec
All spec classes inherit from TensorSpec. It is an abstract dataclass with four core fields: shape, space, dtype, and device.
Import path: torchrl.data.TensorSpec
Common Operations
Every concrete spec supports these operations regardless of domain:| Operation | Description |
|---|---|
spec.rand(shape=None) | Return a uniformly random tensor in the spec’s domain. For unbounded specs, samples from a standard normal. |
spec.zero(shape=None) | Return a zero-filled tensor. Does not validate that 0 belongs to the domain. |
spec.one(shape=None) | Return a ones-filled tensor. |
spec.encode(val) | Cast a numpy array, list, or tensor to the spec’s dtype/device. |
spec.is_in(val) | Return True if val satisfies all constraints (shape, dtype, bounds). |
spec.project(val) | Clamp or otherwise map val back into the valid domain. |
spec.assert_is_in(val) | Like is_in, but raises AssertionError on failure. |
spec.to(dest) | Cast to a different device or dtype. |
spec.expand(*shape) | Broadcast the spec to a larger batch shape. |
spec.squeeze(dim) / spec.unsqueeze(dim) | Add or remove singleton dimensions. |
spec.clone() | Deep-copy the spec. |
spec.sample(shape=None) | Alias for rand. |
Continuous Specs
Bounded / BoundedContinuous
A spec for tensors whose values lie in a closed box [low, high]. The constructor dispatches automatically to BoundedContinuous for floating-point dtypes and BoundedDiscrete for integer dtypes. Pass domain="continuous" or domain="discrete" to override this.
Import path: torchrl.data.Bounded (alias: torchrl.data.BoundedContinuous)
Lower bound. Must be broadcastable with
high and shape.Upper bound. Must be broadcastable with
low and shape.Shape of the tensors produced by this spec. Inferred from
low/high if not provided.Tensor dtype. Defaults to
torch.get_default_dtype() (usually float32). Determines whether BoundedContinuous or BoundedDiscrete is instantiated.Device for generated tensors.
Override automatic domain detection:
"continuous" or "discrete".Unbounded / UnboundedContinuous
A spec for tensors with no lower or upper bound. The internal box spans the full range of the dtype (torch.finfo.min to torch.finfo.max for floats). rand() draws from N(0, 1). Dispatches to UnboundedContinuous for float dtypes and UnboundedDiscrete for integer dtypes.
Import path: torchrl.data.Unbounded (aliases: torchrl.data.UnboundedContinuous, torchrl.data.UnboundedDiscrete)
Shape of tensors. Default is a single-element vector
(1,).Tensor dtype. Floating-point →
UnboundedContinuous; integer → UnboundedDiscrete.Device for generated tensors.
Discrete Specs
Categorical
A scalar-indexed categorical spec. Values are integers in {0, 1, ..., n-1}. More memory-efficient than OneHot for large categorical variables. Use n=-1 for an environment whose action space is dynamically sized; call spec.set_provisional_n(k) before sampling.
Import path: torchrl.data.Categorical
Number of possible outcomes. Use
-1 for a dynamically-sized space.Shape of the output tensor. Defaults to
torch.Size([]) (scalar).Tensor dtype.
Device for generated tensors.
Boolean mask of shape broadcastable to
(*shape, n). False prevents an outcome from being sampled.OneHot
One-hot encoding of a categorical variable. The last dimension of the tensor has size n and exactly one element is True (or 1). Enables differentiable indexing via tensor multiplication.
Import path: torchrl.data.OneHot
Number of categories. The last dimension of every sample is
n.Total shape including the one-hot dimension. If provided,
shape[-1] must equal n.Tensor dtype. Common choices:
torch.bool, torch.int64, torch.float32.Device for generated tensors.
Boolean mask to prevent specific outcomes from being sampled.
MultiOneHot
Concatenation of multiple one-hot vectors along the last dimension. Useful for multi-dimensional discrete action spaces (e.g., multiple discrete sub-actions at each step).
Import path: torchrl.data.MultiOneHot
Number of categories for each sub-dimension. The total length of the output tensor is
sum(nvec).Leading batch shape. The full spec shape is
(*shape, sum(nvec)).Tensor dtype.
Device for generated tensors.
Flat boolean mask of shape
(*shape, sum(nvec)).MultiCategorical
Integer-valued counterpart of MultiOneHot. Each element of the output vector is an independent category index. More memory-efficient than MultiOneHot for large action spaces.
Import path: torchrl.data.MultiCategorical
Number of categories for each independent sub-action.
Leading batch shape. The full spec shape is
(*shape, len(nvec)).Tensor dtype.
Device for generated tensors.
Mask of shape
(*shape, sum(nvec)) following one-hot flattening conventions.Binary
A spec for binary vectors where each element is independently 0 or 1. Unlike OneHot, multiple elements may be active simultaneously. Uses torch.int8 by default.
Import path: torchrl.data.Binary
Length of the binary vector. Either
n or shape must be provided. If both are given, shape[-1] must equal n.Total tensor shape.
shape[-1] determines the vector length.Tensor dtype. Also supports
torch.bool.Device for generated tensors.
Choice
A spec that draws samples from a fixed set of allowed values. Unlike Categorical, values can be arbitrary tensors rather than indices.
Import path: torchrl.data.Choice
The allowable tensor values, stacked along the first dimension.
Leading batch dimensions.
Tensor dtype. Inferred from
values if not provided.Device for generated tensors.
Composite Spec
Composite
A dictionary-like container for nested specs. Analogous to TensorDict but for spec metadata. Each leaf is a TensorSpec; leaves can be None to indicate unconstrained entries. The shape attribute acts like a TensorDict’s batch_size — it is the common leading shape for all leaf specs.
Import path: torchrl.data.Composite
Named specs as keyword arguments.
Batch shape shared by all leaves.
Shared device constraint.
None (default) allows leaves on different devices.The TensorDict subclass (
TensorDict, a tensorclass, etc.) that should be enforced in the environment.| Method | Description |
|---|---|
spec[key] / spec[key] = value | Get or set a leaf spec by key (string or tuple of strings). |
spec.keys(include_nested, leaves_only) | Iterate over keys. |
spec.values() / spec.items() | Iterate over values or key-value pairs. |
spec.rand() | Sample a TensorDict with one random tensor per leaf. |
spec.zero() | Return a zero-filled TensorDict. |
spec.is_in(td) | Check that every leaf of td satisfies its spec. |
spec.project(td) | Clamp all out-of-domain leaves back into their specs. |
spec.encode(td) | Encode all leaves. |
Non-Tensor Spec
NonTensor
A spec for non-tensor data (strings, Python objects, metadata). Used for NonTensorData leaves in TensorDicts, e.g., task descriptions or environment info dicts.
Import path: torchrl.data.NonTensor
Batch shape.
Device. Non-tensor data is typically device-agnostic.
Spec Operations Reference
Using Specs with Environments
Specs are automatically defined on everytorchrl.envs.EnvBase subclass and can be inspected or modified: