skills/pufferlib/references/policies.md
Research snapshot: 2026-07-23. Policy APIs changed substantially between published PufferLib 3.0.0 and current 4.0 source.
PufferLib 3.0 policies are ordinary torch.nn.Module objects. The environment
exposes single_observation_space and single_action_space; size heads from
those single-agent spaces, not from the batched spaces.
Build an nn.Module with an encoder sized from
env.single_observation_space.shape, an action head sized from
env.single_action_space, and a one-value critic head. The official stable
example defines a rollout method named forward_eval(observations, state=None)
and makes the normal forward method use the same contract. Here, forward_eval
is a PufferLib/PyTorch method name; it does not invoke Python's dangerous
eval() builtin.
For a discrete action space, the first output contains action logits and the second is the value estimate. Preserve the leading agent-batch dimension.
The stable pufferlib.models.LSTMWrapper expects a base policy with:
def encode_observations(self, observations, state=None):
...
def decode_actions(self, hidden):
...
The wrapper uses an LSTMCell during rollout inference and an LSTM over
time-batched data during training. Do not manually reshape recurrent state
without checking the source's batch/time convention. Reset hidden state on
actual terminations and truncations according to the trainer's mask behavior.
Stable emulation flattens Dict and Tuple spaces into a homogeneous array.
The byte layout is described by env.emulated. In policy setup:
native_dtype = pufferlib.pytorch.nativize_dtype(env.emulated)
In the forward pass:
structured = pufferlib.pytorch.nativize_tensor(observations, native_dtype)
Keep the original flattened dtype. Constructing a new float tensor before unflattening can destroy the packed representation. Validate every recovered leaf shape and dtype before training.
The 3.0 source handles:
Discrete: one categorical logits tensor.MultiDiscrete: one logits tensor per action branch.Box: a Normal distribution path for continuous actions.Do not infer support from the 2024 paper's limitations section; that paper
describes an earlier release. Test clipping/scaling against the environment's
actual Box.low, Box.high, shape, and dtype. A tanh output is not a general
substitute for affine mapping to arbitrary bounds.
Useful 3.0 symbols include:
pufferlib.pytorch.layer_initpufferlib.pytorch.nativize_dtypepufferlib.pytorch.nativize_tensorpufferlib.models.Defaultpufferlib.models.LSTMWrapperpufferlib.models.Convolutionalpufferlib.models.ProcgenResnetInspect the exact 3.0 source before copying signatures. Do not use top-level
from pufferlib import PuffeRL; the trainer is
pufferlib.pufferl.PuffeRL.
The current PyTorch fallback composes a policy from three modules:
policy = pufferlib.models.Policy(
encoder=encoder,
decoder=decoder,
network=network,
)
The source contract is:
Policy.initial_state(batch_size, device)Policy.forward_eval(x, state) for rollout inferencePolicy.forward(x) for time-batched trainingCurrent built-ins include DefaultEncoder, DefaultDecoder, MLP, MinGRU,
LSTM, GRU, NatureEncoder, and ImpalaEncoder. INI config selects the
Torch fallback components:
[torch]
network = MinGRU
encoder = DefaultEncoder
decoder = DefaultDecoder
[policy]
hidden_size = 128
num_layers = 4
The default 4.0 backend is the native implementation, not this Torch fallback.
The CLI flag --slowly selects the fallback.
Run these checks before a long job:
torch.no_grad().(agent_batch, action_space.n).MultiDiscrete, verify branch count and each branch width.torch.compile and reduced precision can alter performance and numerical
behavior. Record PyTorch, CUDA, compiler mode, precision, and deterministic
settings. Do not claim determinism solely because seeds are fixed.
torch.load on an untrusted file. PufferLib 3.0 and the 4.0 Torch
fallback use torch.load for model paths; provenance review is therefore a
precondition, not an optional cleanup.scripts/inspect_checkpoint.py; it never imports
Torch or deserializes.torch.load documentation
— deserialization warning; accessed 2026-07-23.