rlmesh.Session
A model bound to one env: drive it by hand, or pump whole episodes.
Session()The neutral pair-driver returned by rlmesh.session(). reset / predict /
step drive one step at a time – predict applies the model’s adapter (resolved
from the env’s published contract) around the model’s own predict, replaying an action
chunk one action per step when execution_horizon > 1 and the model defines
predict_chunk. run pumps whole episodes and returns a typed RunResult.
The env connection is opened lazily on first reset (manual driving); run
drives whole episodes through the same primitives and leaves the session open, so
a caller-held session runs as often as you like. Close it yourself – close()
or the with block; after that, any further use raises. (The one-shot
rlmesh.run() / Model.run create their session
internally and close it when the run ends.)
Attributes
Methods
- reset()Begin a new episode: end the previous one, then reset the env and adapter.
- predict()Map one env observation to an env-ready action (the model's adapter applied).
- step()Apply one action to the env; record reward and termination.
- frame_sources()The env's image roles and
render()source, as the viewer sees them. - reader()Build a read-only, role-addressed view over this env's observations.
- read()One-shot read of a single role from one observation.
- observation_roles()The observation roles this session's env declares, grouped by kind.
- run()Drive whole episodes to completion and return a typed
RunResult. - close()Close this session: served route (and owned source), connection, env.
selected_workflow_edition
property[source]property selected_workflow_edition: strThe workflow edition this session runs at, in the spelling the peers agreed on.
On a served model it is the floor across the env, the model, and this
runtime, settled when the session was opened; on a local model the env
leg is the whole negotiation, so it is what that connection settled on.
Named apart from the workflow_edition declaration surfaces: this
is what was agreed, not what this side asked for.
done
property[source]property done: boolWhether the current episode has terminated or truncated.
reset
function[source]reset(*, seed: int | None = None, trial_index: int | None = None)Begin a new episode: end the previous one, then reset the env and adapter.
Ending the previous episode fires the model’s on_episode_end (the local
per-episode boundary), so a stateful model clears its state between episodes
on the hand-driven path too, not only via run().
trial_index is the 0-based ordinal of this episode in a benchmark’s
trial sweep, delivered as reset(options={"trial_index": ...}) – but
only to an env that declared the key in
EnvFactory.reset_options.
Passing one to an env that did not warns and resets without it.
predict
function[source]predict(observation: ObsT)Map one env observation to an env-ready action (the model’s adapter applied).
step
function[source]step(action: ActT)Apply one action to the env; record reward and termination.
contract
property[source]property contract: AnyThe connected env’s contract (connects on first use).
num_envs
property[source]property num_envs: intLanes the connected env runs (a session drives one).
frame_sources
function[source]frame_sources()The env’s image roles and render() source, as the viewer sees them.
reader
function[source]reader(*items: object)Build a read-only, role-addressed view over this env’s observations.
Each item is a role constant – kept in the env’s native encoding – or a
model-input leaf declaring the encoding you want
(Image(IMAGE_PRIMARY, layout="hwc"), State(EEF_POS)). The returned
Reader maps a raw observation to {role: value} through the same
adapter pipeline a model uses, so it is encoding-agnostic across envs and
runs identically in the native core. Resolved once here, reused each step::
read = sess.reader(Image(IMAGE_PRIMARY, layout=“hwc”), EEF_POS) obs, _ = sess.reset() while not sess.done: screen.show(read(obs)[IMAGE_PRIMARY]) obs, *_ = sess.step(sess.predict(obs))
A bare role is desugared to the env-native leaf for that role (by the env’s own tag); pass an explicit leaf to override the encoding.
read
function[source]read(observation: object, item: object)One-shot read of a single role from one observation.
The single-value convenience for reader() – item is a role
constant or a model-input leaf. The reader is resolved once and cached per
item, so calling this every step does not re-resolve::
ee = sess.read(obs, EEF_POS) img = sess.read(obs, Image(IMAGE_PRIMARY, layout=“hwc”))
The value is typed Any (like Reader’s): its concrete shape is
the leaf’s declared encoding, which the caller owns.
observation_roles
function[source]observation_roles()The observation roles this session’s env declares, grouped by kind.
Connects if needed, reads the env contract’s published tags, and returns
their observation_roles. An env that
publishes no tags yields empty groups – “none declared” is an answer,
not an error.
run
function[source]run(
*,
seeds: Sequence[int] | None = None,
episodes: int | None = None,
max_episode_steps: int | None = None,
max_episode_seconds: float | None = None,
hooks: RunHooks | None = None,
trial_index_base: int = 0,
)Drive whole episodes to completion and return a typed RunResult.
The single drive loop: pumps this session’s own reset / predict /
step primitives, so a served model’s run routes through here.
episodes is the exact number of episodes to run (see
resolve_episode_budget(): one by default, the length of seeds
when only seeds are given, and the two must agree when both are).
max_episode_steps / max_episode_seconds
cap each episode – hitting a cap marks it truncated, exactly like the
built-in step bound (the wall-clock cap is checked at the top of the step
loop). Episode i walks trial ordinal trial_index_base + i,
delivered as reset(options={"trial_index": ...}) to an env that
declared the key in :attr:EnvFactory.reset_options \<rlmesh.EnvFactory.reset_options> (an env that did not never sees it,
and its EpisodeResult.trial stays None); the base lets a local
eval walk the same states as a platform shard. hooks
(RunHooks) observes the loop; hook exceptions propagate and
abort the run, and RunHooks.on_run_end() always fires exactly once
with the completed episodes, even on an error or interrupt.
Does not close the session: a caller-held session (from
rlmesh.session() / Model.session()) stays connected – viewer
and hooks included – so run can be called again or mixed with manual
driving; close it via close() or the with block. (The one-shot
rlmesh.run() / Model.run() own their internal session and
close it for you.)
close
function[source]close()Close this session: served route (and owned source), connection, env.
For a served model, closes the model client and shuts down a managed source it
started (e.g. a SandboxModel container). For the env, shuts it down only on
the close_env opt-in, and always releases what this session made itself:
a connection it dialed or an env it built from a factory. A local model
instance is the caller’s and is never closed here (one the session built
from a class is closed exactly once).
Idempotent: later calls are no-ops, and any other use of a closed session
raises RuntimeError.