Skip to content

simulo.Runtime

A Simulo-curated runtime a job executes in. Torch-free metadata recorder.

You normally never construct one: every simulo.App defaults to DEFAULT_RUNTIME. Pick a Simulo runtime by name and layer your own environment variables and public-PyPI packages on top:

runtime = (
simulo.Runtime.from_registry("simulo/gpu-rl:2026.06")
.pip_install("wandb==0.17.0")
.env({"WANDB_PROJECT": "cartpole"})
)
app = simulo.App("cartpole", runtime=runtime)

Nothing is installed on your machine — the runtime is Simulo-built and lives in the cloud; submit only records which runtime the app picked plus the declared env/dependency layers, and the cloud materialises them at execution time.

Real usage, from the shipped cartpole training app — the imports() boundary, the half of the contract the class docstring’s own example above doesn’t show: the one heavy import deferred so discovery never resolves it:

with app.runtime.imports():
import torch # resolved only in execution mode, on the worker

The shipped pip-install-shapely app layers a public PyPI package onto a picked runtime the same way:

runtime = simulo.Runtime.from_registry("simulo/gpu-rl:2026.06").pip_install("shapely")
app = simulo.App("pip-install-shapely", runtime=runtime)
simulo.Runtime(runtime_id: str)
Runtime.from_registry(image: str) -> Runtime

classmethod

Pick a Simulo runtime by name (e.g. "simulo/gpu-rl:2026.06").

Runtime.pip_install(*packages: str, pre: bool = False) -> Runtime

Declare public-PyPI packages to add on top of the Simulo runtime.

Each package is a plain PyPI requirement — name, optionally with extras and a version specifier ("wandb==0.17.0", "transformers[torch]>=4.40"). URLs, VCS refs (git+...), local paths, and PEP 508 direct references (name @ url) are rejected: the Simulo image builder installs from public PyPI only. pre=True allows pre-release versions for this layer.

Each call appends an ordered layer; the builder installs the layers in order on top of the base runtime. Submit only records the layers — nothing is installed locally. A package the base runtime already provides (torch, numpy, the CUDA wheels, the simulo distributions — simulo.interfaces.platform.PLATFORM_PINNED_PACKAGES) cannot be re-declared here; submit fails fast if one is.

Called with no packages (pip_install()), this is a no-op — no layer is recorded — rather than appending a vacuous empty layer for every downstream consumer (the manifest, the worker) to special-case.

Returns self for chaining.

Runtime.env(variables: Mapping[str, str]) -> Runtime

Merge environment variables into the job’s execution environment.

Later calls win on key conflicts. Returns self for chaining. Guarded: runner/worker-owned keys (simulo.interfaces.platform.RESERVED_RUNTIME_ENV_KEYS / RESERVED_RUNTIME_ENV_PREFIXES) are never honoured at execution — enforcement lives at the runner/worker, which also sanitises the pip environment so no variable declared here can redirect the image builder’s package installs.

Runtime.imports() -> AbstractContextManager[None]

Remote-only-import boundary.

In execution mode this is a plain nullcontext (the imports really happen). In discovery mode it installs a stub import finder that records the deferred top-level imports without resolving them — how heavy libraries (torch and friends) stay off your machine at submit.

Runtime.torch_jit(fn: F) -> F

Record the function’s qualname; JIT-compile only on the worker.

In discovery (submit) this is a no-op marker — it records the qualname and returns fn unchanged, so no torch import happens locally. In execution mode (the backend runner, which has the heavy runtime) it replaces @torch.jit.script: torch is imported lazily inside the method so module load stays lean.

Runtime.runtime_id: str

property

The Simulo runtime name passed to from_registry().