Framework Backends

A backend decides what RLMesh decodes values into at the Python boundary.

A backend decides what RLMesh decodes values into at the Python boundary. The wire stays framework-neutral, so the backend is a client-side choice: it changes the type you receive from reset and step, not the protocol or the server. The same served environment can feed a NumPy client, a Torch client, and a JAX client at once.

Every backend exposes the same surface (RemoteEnv, RemoteVectorEnv, Model, RemoteModel, and the sandbox sessions) under its own import path. Pick the one whose import matches the values your code already speaks.

import rlmesh                       # plain Python and RLMesh-native values
from rlmesh.numpy import RemoteEnv  # NumPy arrays
from rlmesh.torch import RemoteEnv  # Torch tensors  (experimental)
from rlmesh.jax import RemoteEnv    # JAX arrays     (experimental)

Choosing a backend

Backend Import Install Tensor leaves decode to Status Reach for it when
Plain Python rlmesh bundled RLMesh-native values supported you want no array dependency, just primitives
NumPy rlmesh.numpy pip install "rlmesh[numpy]" NumPy arrays supported examples, notebooks, and most CPU evaluation
Torch rlmesh.torch pip install "rlmesh[torch]" Torch tensors experimental your model or environment already speaks Torch, GPU included
JAX rlmesh.jax pip install "rlmesh[jax]" JAX arrays (immutable) experimental your pipeline is JAX

In every backend, only tensor leaves change type. Python primitives and nested containers (dict, tuple, lists) are preserved as they are.

Install the extra for the backend you use, then import its client or model class:

pip install "rlmesh[numpy]"   # or rlmesh[torch], rlmesh[jax]
from rlmesh.numpy import RemoteEnv

with RemoteEnv("127.0.0.1:5555") as env:
    obs, info = env.reset(seed=0)

Space wrappers use the client’s backend too, so env.action_space.sample() produces a value that env.step() can accept. Torch and JAX conversion happens at the client boundary; the environment itself can remain a plain Gymnasium environment. JAX arrays are immutable. For conversion details and version requirements, see the Python API.

What “experimental” means here

Torch and JAX are device-bearing frameworks: their obs/action seam can carry tensors that live on a device, GPU included. NumPy and the plain backend have no device concept. That difference is the source of the limitations to know before you reach for them.

Behavior NumPy / plain Torch / JAX
Device none tensors can live on a device; an env-side action accepts device= (see Serve an Environment)
Serving a vector env num_envs > 1 fans out via Gymnasium not supported: Gymnasium vectorization concatenates observations with NumPy and discards framework tensors. Serve scalar (num_envs=1), or serve with NumPy
Mutability of decoded values NumPy arrays are writable JAX arrays are immutable

The wire is framework-neutral regardless of backend, so a client’s framework is independent of the server’s. A NumPy environment can serve a Torch model client; nothing in between needs to agree on a framework.

Models

Backends apply to models the same way. A Model from any backend hands predict values in that backend’s types:

from rlmesh.numpy import Model

model = Model(lambda obs: 0)
model.run("127.0.0.1:5555", episodes=1)