Skip to content

unienv_interface.remote

Transport-independent remote UniEnv execution and latest-value observation.

PROTOCOL_VERSION module-attribute

PROTOCOL_VERSION: int = 1

RemoteClient

RemoteClient(transport: MessageTransport, *, backend: ComputeBackend = NumpyComputeBackend, device: Optional[object] = None, timeout: Optional[float] = 30.0, max_message_size: int = DEFAULT_MAX_MESSAGE_SIZE)

A connection, descriptor cache, and shared control session.

Requests are serialized, including entire component operation contexts. A timeout closes the connection: late replies can never be confused with a later request. Mutations aren't retried and may have executed remotely.

timeout instance-attribute

timeout = timeout

codec instance-attribute

codec = Codec(max_message_size)

session_id instance-attribute

session_id: Optional[str] = hello['session_id']

closed instance-attribute

closed = False

descriptors instance-attribute

descriptors: Dict[str, Descriptor] = {}

connect classmethod

connect(uri: str, **options: object) -> RemoteClient

discover

discover() -> List[Descriptor]

describe

describe(resource_id: str) -> Descriptor

resource

resource(resource_id: str) -> Union[RemoteEnv, RemoteWorld, RemoteWorldNode]

env

env(resource_id: str) -> RemoteEnv

world

world(resource_id: str) -> RemoteWorld

node

node(resource_id: str) -> RemoteWorldNode

acquire

acquire(resource_id: str, mode: Optional[ExecutionMode] = None) -> None

release

release(resource_id: str, *, close_subscriptions: bool = False) -> None

Release shared world control, retaining subscriptions by default.

Set close_subscriptions=True to also close this client's domain streams.

operation

operation(resource_id: str, kind: OperationKind = 'step') -> Iterator[str]

Mark one client-coordinated reset/reload/step, without rollback.

Use a world or node ID. Every mutating component call must belong to an operation. The context publishes snapshots only after successful exit.

call

call(resource_id: str, method: str, *args: Any, **kwargs: Any) -> Any

subscribe

subscribe(resource_id: str, fields: Optional[Iterable[str]] = None) -> Subscription

close

close() -> None

Subscription

Subscription(client: RemoteClient, resource_id: str, subscription_id: str)

Closeable latest-snapshot iterator. next(timeout=...) is also supported.

next

next(timeout: Optional[float] = None) -> WireMessage

close

close() -> None

RemoteServer

RemoteServer(*, max_message_size: int = DEFAULT_MAX_MESSAGE_SIZE, idle_timeout: Optional[float] = 60.0)

Host objects or lazy root factories. Register resources before connecting.

Registration doesn't call lifecycle methods. All discovery, lifecycle, snapshots, and cleanup execute on the resource's dedicated world worker. Only factory registrations are evicted after idle_timeout seconds.

codec instance-attribute

codec = Codec(max_message_size)

idle_timeout instance-attribute

idle_timeout = idle_timeout

register

register(resource_id: str, obj_or_factory: Union[HostedResource, ResourceFactory]) -> str

Register an Env, World, WorldNode, or zero-arg root factory.

WorldEnv exports its world and complete node tree automatically. Re-registering the same object returns its existing ID, without aliases. World/node relationships and child names must stay fixed after registration. Factories run on the world worker on first access (including discovery). Their topology must remain identical across idle eviction and revival. A root WorldNode with world=None owns a separate domain, including its detached children. Each node must declare a backend; device defaults to None for RPC coercion. Devices secretly shared by detached nodes have no ownership protection, so their construction must be trusted.

attach

attach(transport: MessageTransport) -> _Session

Accept a connected MessageTransport, starting a session in background.

connect

connect(**client_options: object) -> RemoteClient

Create an in-memory RemoteClient using the full wire protocol.

listen

listen(host: str = '127.0.0.1', port: int = 0) -> str

Start the optional WebSocket listener; return its ws:// endpoint.

close

close() -> None

RemoteEnv

RemoteEnv(client: RemoteClient, resource_id: str)

Bases: _Proxy, Env

metadata class-attribute instance-attribute

metadata: dict[str, Any] = {'render_modes': []}

render_mode class-attribute instance-attribute

render_mode: Optional[str] = None

render_fps class-attribute instance-attribute

render_fps: Optional[int] = None

backend instance-attribute

backend: ComputeBackend[BArrayType, BDeviceType, BDtypeType, BRNGType]

device instance-attribute

device: Optional[BDeviceType]

batch_size class-attribute instance-attribute

batch_size: Optional[int] = None

action_space instance-attribute

action_space: Space[ActType, BDeviceType, BDtypeType, BRNGType]

observation_space instance-attribute

observation_space: Space[ObsType, BDeviceType, BDtypeType, BRNGType]

context_space class-attribute instance-attribute

context_space: Optional[Space[ContextType, BDeviceType, BDtypeType, BRNGType]] = None

unwrapped property

unwrapped: Env

prev_wrapper_layer property

prev_wrapper_layer: Optional[Env]

rng instance-attribute

rng = self.backend.random.random_number_generator(device=self.device)

close

close() -> None

Close this proxy and release shared control, retaining subscriptions.

sample_space

sample_space(space: Space) -> Any

Sample from space using and updating self.rng.

sample_action

sample_action() -> ActType

Sample one action from action_space.

sample_observation

sample_observation() -> ObsType

Sample one observation from observation_space.

sample_context

sample_context() -> Optional[ContextType]

Sample one context value if context_space is defined.

update_observation_post_reset

update_observation_post_reset(old_obs: ObsType, newobs_masked: ObsType, mask: BArrayType) -> ObsType

Merge masked reset observations back into a full batched observation.

update_context_post_reset

update_context_post_reset(old_context: ContextType, new_context: ContextType, mask: BArrayType) -> ContextType

Merge masked reset contexts back into a full batched context.

has_wrapper_attr

has_wrapper_attr(name: str) -> bool

Checks if the attribute name exists in the environment.

get_wrapper_attr

get_wrapper_attr(name: str) -> Any

Gets the attribute name from the environment.

set_wrapper_attr

set_wrapper_attr(name: str, value: Any)

Sets the attribute name on the environment with value.

reset

reset(*, mask: Optional[ArrayAPIArray] = None, seed: Optional[int] = None, **kwargs: Any) -> ResetResult

reload

reload(*, mask: Optional[ArrayAPIArray] = None, seed: Optional[int] = None, **kwargs: Any) -> ResetResult

step

step(action: Any) -> StepResult

render

render() -> Any

get_node

get_node(nested_keys: Union[str, Sequence[str]]) -> Optional[RemoteWorldNode]

RemoteWorld

RemoteWorld(client: RemoteClient, resource_id: str)

Bases: _Proxy, World

backend instance-attribute

backend: ComputeBackend[BArrayType, BDeviceType, BDtypeType, BRNGType]

device instance-attribute

device: Optional[BDeviceType]

The world timestep in seconds, if None, the world is asynchronous (real-time)

world_timestep instance-attribute

world_timestep: Optional[float]

The world's physical timestep in seconds, there might be multiple world sub-steps inside a world step. If none this means it is not known

world_subtimestep class-attribute instance-attribute

world_subtimestep: Optional[float] = None

The number of parallel environments in this world

batch_size class-attribute instance-attribute

batch_size: Optional[int] = None

close

close() -> None

Close this proxy and release shared control, retaining subscriptions.

is_control_timestep_compatible

is_control_timestep_compatible(control_timestep: Optional[float]) -> bool

Check whether a node control period aligns with world_timestep.

step

step() -> Union[float, ArrayAPIArray]

reset

reset(*, seed: Optional[int] = None, mask: Optional[ArrayAPIArray] = None, **kwargs: Any) -> None

reload

reload(*, seed: Optional[int] = None, mask: Optional[ArrayAPIArray] = None, **kwargs: Any) -> None

after_reset

after_reset(*, seed: Optional[int] = None, mask: Optional[ArrayAPIArray] = None, **kwargs: Any) -> None

after_reload

after_reload(*, seed: Optional[int] = None, mask: Optional[ArrayAPIArray] = None, **kwargs: Any) -> None

RemoteWorldNode

RemoteWorldNode(client: RemoteClient, resource_id: str)

Bases: _Proxy, WorldNode

name instance-attribute

name: str

control_timestep class-attribute instance-attribute

control_timestep: Optional[float] = None

update_timestep class-attribute instance-attribute

update_timestep: Optional[float] = None

context_space class-attribute instance-attribute

context_space: Optional[Space[ContextType, BDeviceType, BDtypeType, BRNGType]] = None

observation_space class-attribute instance-attribute

observation_space: Optional[Space[ObsType, BDeviceType, BDtypeType, BRNGType]] = None

action_space class-attribute instance-attribute

action_space: Optional[Space[ActType, BDeviceType, BDtypeType, BRNGType]] = None

has_reward class-attribute instance-attribute

has_reward: bool = False

has_termination_signal class-attribute instance-attribute

has_termination_signal: bool = False

has_truncation_signal class-attribute instance-attribute

has_truncation_signal: bool = False

supported_render_modes class-attribute instance-attribute

supported_render_modes: Sequence[str] = ()

render_mode class-attribute instance-attribute

render_mode: Optional[str] = None

reset_priorities class-attribute instance-attribute

reset_priorities: Set[int] = set()

reload_priorities class-attribute instance-attribute

reload_priorities: Set[int] = set()

after_reset_priorities class-attribute instance-attribute

after_reset_priorities: Set[int] = set()

after_reload_priorities class-attribute instance-attribute

after_reload_priorities: Set[int] = set()

pre_environment_step_priorities class-attribute instance-attribute

pre_environment_step_priorities: Set[int] = set()

post_environment_step_priorities class-attribute instance-attribute

post_environment_step_priorities: Set[int] = set()

can_render property

can_render: bool

Whether the node currently exposes a render mode.

effective_update_timestep property

effective_update_timestep: Optional[float]

Resolved update period, defaulting to control_timestep when unset.

unwrapped property

unwrapped: WorldNode

prev_wrapper_layer property

prev_wrapper_layer: Optional[WorldNode]

world instance-attribute

world = None if world_id is None else client.world(world_id)

backend property

backend: ComputeBackend

device property

device: Optional[object]

get_nodes_by_type

get_nodes_by_type(node_type: Type[WorldNode]) -> list[WorldNode]

Return nodes in this subtree that are instances of node_type.

close

close() -> None

Close this proxy and release shared control, retaining subscriptions.

has_wrapper_attr

has_wrapper_attr(name: str) -> bool

Checks if the attribute name exists in the environment.

get_wrapper_attr

get_wrapper_attr(name: str) -> Any

Gets the attribute name from the environment.

set_wrapper_attr

set_wrapper_attr(name: str, value: Any)

Sets the attribute name on the environment with value.

pre_environment_step

pre_environment_step(dt: Union[float, ArrayAPIArray], *, priority: int = 0) -> None

post_environment_step

post_environment_step(dt: Union[float, ArrayAPIArray], *, priority: int = 0) -> None

set_next_action

set_next_action(action: Any) -> None

get_context

get_context() -> Any

get_observation

get_observation() -> Any

get_reward

get_reward() -> Union[float, ArrayAPIArray]

get_termination

get_termination() -> Signal

get_truncation

get_truncation() -> Signal

get_info

get_info() -> Optional[Dict[str, Any]]

render

render() -> Any

reset

reset(*, priority: int = 0, seed: Optional[int] = None, mask: Optional[ArrayAPIArray] = None, **kwargs: Any) -> None

reload

reload(*, priority: int = 0, seed: Optional[int] = None, mask: Optional[ArrayAPIArray] = None, **kwargs: Any) -> None

after_reset

after_reset(*, priority: int = 0, mask: Optional[ArrayAPIArray] = None) -> None

after_reload

after_reload(*, priority: int = 0, mask: Optional[ArrayAPIArray] = None) -> None

get_node

get_node(nested_keys: Union[str, Sequence[str]]) -> Optional[RemoteWorldNode]

get_nodes_by_fn

get_nodes_by_fn(fn: Callable[[WorldNode], bool]) -> List[WorldNode]

RemoteWorldEnv

RemoteWorldEnv(world: RemoteWorld, node_or_nodes: Union[RemoteWorldNode, Iterable[RemoteWorldNode]], *, render_mode: Optional[str] = 'auto')

Bases: WorldEnv

Local lifecycle composition with explicit remote operation boundaries.

Pass a RemoteWorld and RemoteWorldNode(s) from the same client and world. Underlying nodes always run on the world server. Client-local combinations are supported; combining different simulator worlds isn't a WorldEnv model.

metadata class-attribute instance-attribute

metadata: dict[str, Any] = {'render_modes': []}

render_mode property

render_mode: Optional[str]

render_fps property

render_fps: Optional[int]

backend property

backend

device property

device

batch_size property

batch_size

action_space property

action_space

observation_space property

observation_space

context_space property

context_space

rng instance-attribute

rng = self.backend.random.random_number_generator(device=self.device)

unwrapped property

unwrapped: Env

prev_wrapper_layer property

prev_wrapper_layer: Optional[Env]

node instance-attribute

node = node_or_nodes

world instance-attribute

world = world

control_timestep property

control_timestep: Optional[float]

Simulation time represented by one environment control step.

This is the resolved control timestep: the explicit node control_timestep when configured, otherwise the effective update timestep, otherwise the world timestep. It is None when none of these are defined (e.g. an asynchronous real-time world).

client instance-attribute

client = world.client

render

render() -> RenderFrame | Sequence[RenderFrame] | None

Render via the root node when rendering is enabled.

sample_space

sample_space(space: Space) -> Any

Sample from space using and updating self.rng.

sample_action

sample_action() -> ActType

Sample one action from action_space.

sample_observation

sample_observation() -> ObsType

Sample one observation from observation_space.

sample_context

sample_context() -> Optional[ContextType]

Sample one context value if context_space is defined.

update_observation_post_reset

update_observation_post_reset(old_obs: ObsType, newobs_masked: ObsType, mask: BArrayType) -> ObsType

Merge masked reset observations back into a full batched observation.

update_context_post_reset

update_context_post_reset(old_context: ContextType, new_context: ContextType, mask: BArrayType) -> ContextType

Merge masked reset contexts back into a full batched context.

has_wrapper_attr

has_wrapper_attr(name: str) -> bool

Checks if the attribute name exists in the environment.

get_wrapper_attr

get_wrapper_attr(name: str) -> Any

Gets the attribute name from the environment.

set_wrapper_attr

set_wrapper_attr(name: str, value: Any)

Sets the attribute name on the environment with value.

get_node

get_node(nested_keys: Union[str, Sequence[str]]) -> Optional[WorldNode[Any, Any, Any, BArrayType, BDeviceType, BDtypeType, BRNGType]]

Look up a node by name or nested path.

get_nodes_by_fn

get_nodes_by_fn(fn: Callable[[WorldNode[Any, Any, Any, BArrayType, BDeviceType, BDtypeType, BRNGType]], bool]) -> list[WorldNode[Any, Any, Any, BArrayType, BDeviceType, BDtypeType, BRNGType]]

Collect nodes in the tree that satisfy fn.

get_nodes_by_type

get_nodes_by_type(node_type: Type[WorldNode[Any, Any, Any, BArrayType, BDeviceType, BDtypeType, BRNGType]]) -> list[WorldNode[Any, Any, Any, BArrayType, BDeviceType, BDtypeType, BRNGType]]

Collect nodes in the tree that are instances of node_type.

reset

reset(*, mask: Optional[ArrayAPIArray] = None, seed: Optional[int] = None, reload: bool = False, **kwargs: Any) -> ResetResult

reload

reload(*, mask: Optional[ArrayAPIArray] = None, seed: Optional[int] = None, **kwargs: Any) -> ResetResult

step

step(action: Any) -> StepResult

close

close() -> None

Close this composer and release shared control, retaining subscriptions.

MessageTransport

Bases: Protocol

One reader and one writer may run concurrently; close unblocks both.

Implementations preserve complete message boundaries and order. They must bound buffering and raise ConnectionError/OSError on transport failure.

send

send(payload: bytes) -> None

recv

recv() -> bytes

close

close() -> None

MemoryTransport

MemoryTransport(incoming: _Channel, outgoing: _Channel)

Bounded, byte-copying transport for tests and embedded deployments.

pair classmethod

pair(capacity: int = 16) -> Tuple[MemoryTransport, MemoryTransport]

send

send(payload: bytes) -> None

recv

recv() -> bytes

close

close() -> None

WebSocketTransport

WebSocketTransport(connection: Connection)

connection instance-attribute

connection = connection

connect classmethod

connect(uri: str, *, max_message_size: int = DEFAULT_MAX_MESSAGE_SIZE, **kwargs: object) -> WebSocketTransport

send

send(payload: bytes) -> None

recv

recv() -> bytes

close

close() -> None

TransportClosed

Bases: ConnectionError

Codec

Codec(max_message_size: int = DEFAULT_MAX_MESSAGE_SIZE)

Encode a tagged value tree and contiguous binary attachments.

Limits apply to the whole envelope, on both send and receive. Arrays decode to independently owned NumPy memory; clients may subsequently map backends.

max_message_size instance-attribute

max_message_size = max_message_size

encode

encode(value: Any) -> bytes

decode

decode(payload: bytes) -> Any

CodecError

Bases: ValueError

A value or envelope cannot be represented by the v1 codec.

RemoteError

RemoteError(code: str, message: str, *, uncertain: bool = False)

Bases: RuntimeError

code instance-attribute

code = code

uncertain instance-attribute

uncertain = uncertain

UncertainOutcomeError

UncertainOutcomeError(message: str = 'Connection lost or timed out; the remote mutation may have executed')

Bases: RemoteError

code instance-attribute

code = code

uncertain instance-attribute

uncertain = uncertain