Environment object is the wire-protocol control handle for one: it holds the capabilities and
tasks registered against it and answers an agent harness over the protocol.
Authoring an env.py lives in creating an environment; this
page is the object and its serving API.
The Environment object
hud.environment.Environment is the lightweight control object the whole file hangs off. When
served, it acts as the server an agent harness connects to: it answers hello with its
capabilities and runs its tasks on request.
| Parameter | Type | Default | Description |
|---|---|---|---|
name | str | "environment" | Environment identity (used as the env-ref name). |
version | str | "0.0.1" | Version string surfaced in the manifest. |
capabilities | list[Capability] | None | None | Wire data for services that already exist; see Capabilities. |
Methods
You register capabilities, lifecycle hooks, and tasks against the object with these methods. Each becomes part of what the environment advertises when it serves.| Method | Description |
|---|---|
env.template(*, id=None, description="", input=None, returns=None) | Register a task template (an async generator that yields a prompt, then a reward). Returns a factory that mints a Task when called. |
env.initialize / env.shutdown | Decorators registering hooks run once before serving / on teardown (shutdown runs in reverse order). |
env.add_capability(cap) | Publish concrete wire data, replacing any same-named entry. Call it from an @env.initialize hook once a daemon the env runs is up. |
env.capability(name) | Look up a published capability by name. |
env.workspace(root, *, name="shell", track_files=None, **kwargs) | Attach a Workspace serving name over ssh/2, wiring its start, publish, and stop lifecycle. File tracking runs by default (track_files defaults to HUD_FILE_TRACKING_ENABLED). |
env.start() / env.stop() | Run the @env.initialize / @env.shutdown hooks directly (start is idempotent until stop). |
env.tasks / env.templates | The registered template factories by id (templates is an alias of tasks). |
@env.template() decorator takes optional arguments:
| Parameter | Type | Description |
|---|---|---|
id | str | None | Task id (defaults to the function name). |
description | str | Human-readable description, surfaced in the manifest. |
input | Any | Optional type for the agent’s input (JSON schema in the manifest). |
returns | Any | Optional type the agent must produce; the answer arrives as an Answer[T]. See Types. |
Serving
You rarely serve by hand -hud eval, task.run(), and Taskset.run() bring
the environment up for you, and the runtime you pass decides where. Serving
itself belongs to hud.environment.server, the entry point every substrate runs: a
LocalRuntime child process, a container CMD, or hud serve.
| Function | Description |
|---|---|
await serve(env, host="127.0.0.1", port=0) | Start daemons and serve the control channel until cancelled (blocks). |
await bind(env, host="127.0.0.1", port=0) | Bind the control-channel socket and return an asyncio.Server without serving. |
load_environment(path, *, name=None) | Return the one Environment defined at path (a .py file or directory); name selects among several. |
A dependency that must own the process main thread (e.g. Isaac Sim / Omniverse) can’t run under
hud serve, which runs the asyncio loop on main. Run serve(env, host, port) on a worker thread
instead and keep the main thread for the dependency - see Robots.