OpenEnv documentation

Core Concepts

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.8.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Core Concepts

OpenEnv follows a client-server model inspired by Gymnasium’s simple API. Agents send structured actions to isolated environments and receive observations, rewards, and episode status in return.

+-----------------+     HTTP/WebSocket     +-----------------+
|   Your Agent    | <--------------------> |   Environment   |
|   (Client)      |    step/reset/state    |    (Server)     |
+-----------------+                        +-----------------+

To build one step by step, follow Your First Environment.

Key Abstractions

Environment

An Environment is an isolated execution context where your agent can take actions and receive observations. It subclasses Environment and implements reset(), step() and the state property. It runs inside a server, which creates one instance per client session.

Action

An Action is a structured command that your agent sends to the environment. Each environment defines its own action schema as a subclass of Action.

from coding_env import CodeAction

action = CodeAction(code="print('Hello!')")

Observation

An Observation is the response from the environment after taking an action. It contains the current state visible to your agent. Every observation carries done and reward fields, so step() returns an observation, not a tuple.

result = client.step(action)
print(result.observation.stdout)  # "Hello!"

State

The State is the episode’s bookkeeping on the server side: at least episode_id and step_count. Clients read it with state().

StepResult

A StepResult bundles together everything the client gets back from a step:

  • observation: what the agent can see
  • reward: numeric reward signal for training
  • done: whether the episode has ended
  • metadata: additional metadata returned alongside the observation

Reward and Rubric

Rewards are computed inside the environment, not by external code. A Rubric is a composable unit of reward computation passed to the environment. Rubrics can be combined with WeightedSum, Gate, and Sequential, use LLM judges for subjective criteria, and handle delayed rewards with TrajectoryRubric. See Rewards and the Rubrics tutorial.

Client

A Client is how you connect to and interact with an environment. OpenEnv provides both async and sync clients.

from openenv import AutoEnv

# Async
async with AutoEnv.from_env("coding") as client:
    result = await client.reset()
    result = await client.step(action)

# Sync, with its own client (a client is locked to the mode it is first used in)
with AutoEnv.from_env("coding").sync() as client:
    result = client.reset()
    result = client.step(action)

The Step Loop

with env.sync() as client:
    result = client.reset()

    while not result.done:
        obs = result.observation
        action = decide_action(obs)
        result = client.step(action)
        learn(result.reward)

Connection Methods

MethodUse CaseExample
HTTP URLRemote servers, Hugging Face SpacesEnvClient(base_url="https://...")
DockerLocal developmentEnvClient.from_docker_image("env:latest")
Cloud / custom runtimeRun the server on a cloud sandboxEnvClient.from_docker_image("env:latest", provider=DaytonaProvider())
Auto-discoveryInstalled packages or known environmentsAutoEnv.from_env("echo")

See the Runtime Providers guide for the available providers and how to pick one.

Environment Anatomy

An environment is a Python package with a manifest (openenv.yaml), the models, the client, and a server/ folder with the environment, the FastAPI app built with create_app, and a Dockerfile. The client, action and observation classes are found by naming convention (MyEnv, MyAction, MyObservation), so the manifest doesn’t list them. openenv init my_env generates this layout. Your First Environment goes through each file.

Next Steps

Update on GitHub