Skip to main content
A capability is a connection the environment exposes; a harness attaches its own tools to it. The same environment serves a one-shot Q&A or a full computer-use rollout, depending on which capabilities a harness opens.

The Capability dataclass

A capability is (name, protocol, url, params) - concrete wire data carrying the real address of something serving the protocol. Each protocol has a factory (Capability.ssh, .mcp, .cdp, .rfb, .robot) - a classmethod that builds a valid Capability for that protocol, so you don’t fill in the four fields by hand. It normalizes the URL (fills in the default scheme and port), sets the right protocol id, and packs the protocol-specific params. cap.to_manifest() / Capability.from_manifest(data) round-trip it on the wire.

Spinning up a capability

Every capability points at a daemon. A daemon that already exists (a managed service, a remote box) is described with its factory and you’re done. A daemon the environment runs itself follows the same four steps inside an @env.initialize hook:
  1. Launch it as a subprocess or background task, bound to 127.0.0.1.
  2. Block until it is listening before publishing. A subprocess returns before its port is bound, so poll the port (or asyncio.sleep for a daemon you know starts fast). The environment runs every @env.initialize hook to completion before accepting a client, so a capability published here is live the moment any agent connects.
  3. Publish its address with env.add_capability(...).
  4. Tear it down in @env.shutdown.
Bind every daemon to 127.0.0.1: the environment exposes a single control port, and the HUD client transparently forwards a 127.0.0.1 capability through that port to the daemon inside. A capability already on a public address is used as-is.

Factories

ssh - a sandboxed shell

The shell case is built in via Workspace, so you rarely call this factory directly. env.workspace(root) starts a workspace, publishes its ssh capability, and stops it with the env.

mcp - your own tools

env.py

cdp - a browser

Playwright ships the Chromium binary (playwright install chromium). Add --no-sandbox to the launch flags only when running as root in a container.
env.py

rfb - a virtual screen

On Linux, Xvfb paints the framebuffer and x11vnc serves it (apt install xvfb x11vnc).
env.py

robot - an observation/action loop

The robot control loop (beta) runs over the openpi/0 protocol. It is openpi-like: it reuses openpi’s msgpack-numpy wire format and flat observation/action naming, but the environment is the server (it owns the world and pushes observations) and the agent is the client (it acts, replying with actions). The environment drives its simulator through a RobotEndpoint, which builds the capability once started:
See Robots for the bridge, the endpoint, the harness, and the contract spec.

Workspace file tracking

Workspace file tracking records what changed in a Workspace over a run, so HUD can show file diffs in the trace. It runs with the workspace lifecycle and is not a tool the agent calls. env.workspace(...) enables it by default (the HUD_FILE_TRACKING_ENABLED setting); set HUD_FILE_TRACKING_ENABLED=false or pass track_files=False to opt out:
env.py

Harness clients

Spinning up a capability is the environment side. The harness side is the mirror: it opens a capability to get a live client it can drive. The capability clients live in hud.capabilities: The bundled provider agents open these automatically based on which capabilities the manifest advertises (see Agents). To write your own harness, attach to the capability you need and define your tool spec.

Workspace

A Workspace is not itself a capability - it’s the built-in workspace daemon. It serves ssh for agent access and, when enabled, file tracking for rollout telemetry. For mcp, cdp, and rfb you stand up the daemon yourself. Concretely it’s a directory plus a bwrap-isolated SSH server (bash + chroot’d SFTP). env.workspace(root, ...) wires its whole lifecycle; construction is pure data, with keys, sockets, and the root directory materializing only at serve time. To run one outside an env, drive its lifecycle directly and publish ws.capability():
Use a relative path ("workspace", created next to env.py). Sandbox isolation (bwrap) is Linux-only - unisolated elsewhere, isolated in a built image.
A Mount (hud.environment) configures a single bwrap mount, Mount(kind, src, dst, optional), where kind is one of ro, rw, tmpfs, symlink, proc, dev. For authoring a complete environment around a capability, see creating an environment; for the object and serving API, see environment.