hud.environment.Environment is the control channel that exposes capabilities and tasks. Import it from the top level or the subpackage:
Constructor
| 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 | Capabilities to publish — concrete wire data for services that already exist (Capability.cdp(url=...)). Daemons the env runs itself publish theirs at serve time: env.workspace(root) for the shell case, env.add_capability(...) from an @env.initialize hook in general. |
Passing v5-only keywords emits a
DeprecationWarning and ignores them. See Migrate to v6.Registering tasks
yields a prompt and a reward. Calling the decorated object mints a public Task.
| 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. |
Capabilities
Capability is always concrete wire data — the URL of something serving the protocol. Pass capabilities for services that already exist to the constructor; for a daemon the env runs itself, start it in an @env.initialize hook and publish its address with env.add_capability(...). env.workspace(root) wires the common shell case: nothing touches the filesystem until the env serves. See Capabilities.
Lifecycle hooks
env.add_capability(...). By the time a client says hello, every published capability is concrete.
Serving
Serving belongs tohud.environment.server — the same entry point a container
CMD runs (python -m hud.environment.server <source>):
| Function | Description |
|---|---|
await serve(env, host="127.0.0.1", port=0) | Start daemons and accept control-channel connections (blocks). |
await bind(env, host="127.0.0.1", port=0) | Bind the socket and return an asyncio.Server without serving. |
await env.start() / await env.stop() | Run @env.initialize / @env.shutdown hooks directly. |
hud serve and run through hud eval, task.run(),
or Taskset.run() — placement (runtime=LocalRuntime(...)) brings substrates up for you.
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 Robotics.The wire protocol
An environment answers a small JSON-RPC control channel over tcp:| Method | Returns |
|---|---|
hello | session id, env identity, capability bindings |
tasks.list | task id/description metadata |
tasks.start | the task’s prompt (holds the session across disconnect) |
tasks.grade | the evaluation (score + metadata) |
tasks.cancel | cancels the held task |
bye | ends the session and tears the held task down |
tasks.start, disconnect, then reconnect to tasks.grade — which is how hud task start / hud task grade work against a packaged image.