Computers

A Computer is the Linux environment an Agent’s Sessions run in. It has its own disk, processes and Secret bindings, and it outlives the Sessions that use it. Every Computer is created from a Template definition that you declare in source with template() and deploy with your Agents.

Defining a Computer

import { agent, template, image } from "@helmr/sdk"

// Create these Secret IDs in each target Environment.
const GITHUB_TOKEN = "GITHUB_TOKEN"
const REGISTRY_TOKEN_ID = "REGISTRY_TOKEN"

export const repo = template({
  id: "repo",
  image: image("repo")
    .from("node:24-bookworm-slim")
    .run(["sh", "-ceu", "apt-get update && apt-get install -y git ripgrep"])
    .workdir("/workspace"),
  resources: { cpu: 2, memory: "4GiB" },
  async prepare(build) {
    await build.exec(["git", "clone", "https://github.com/acme/app.git", "/workspace/app"])
    await build.exec("npm ci", { cwd: "/workspace/app" })
  },
  refresh: { every: "1d" },
  prepareSecrets: [{ secret: REGISTRY_TOKEN_ID, env: { name: "REGISTRY_TOKEN", mode: "raw" } }],
  secrets: [{ secret: GITHUB_TOKEN, env: { name: "GITHUB_TOKEN", mode: "raw" } }],
  deleteAfterUnused: "30d",
})

export const fixer = agent({
  id: "fixer",
  template: repo,
  async turn(turn) {
    return { received: turn.input.length }
  },
})

The full field list is in the Computer reference.

Durations are positive integer milliseconds or a string such as "30m", "12h" or "7d".

The disk is 32 GiB in this release. You can omit disk; a Computer whose definition sets any other size cannot be created.

The prepared image

A template’s image() is the recipe; an image is the disk Helmr builds from that recipe and, when you declare one, the result of running prepare. Every Computer starts from a prepared image. New Computers start from a copy of it, so work that every Computer needs (cloning a repository, installing dependencies, warming caches) runs once instead of at the start of every Session.

prepare(build) runs inside a Computer built from the image() recipe. build.exec runs one command and rejects if it exits with a nonzero status. Pass a string to run it through /bin/sh -c, or an argv array to run it directly, with optional cwd and env. build.signal aborts when preparation is cancelled. When prepare returns and its commands finish, Helmr saves the disk as the prepared image. If prepare throws or a command fails, no image is produced and Computers waiting for it report an unavailable residency with the error code computer_preparation_failed.

When you promote a Deployment, Helmr waits for a usable image for every Template with a prepare callback and every Template referenced by an Agent in that Deployment. A changed image specification needs a new image. Templates with the same image specification share one preparation. A Template with no callback and no Agent reference can prepare its image when the first Computer needs it. Concurrent requests share that preparation.

Refresh

A prepared image ages. refresh: { every } sets the interval between background re-preparations, and it also limits how old an image may be: a new Computer does not start from an image older than three every intervals. Helmr prepares a new image instead. Without refresh, images have no age limit and are not re-prepared in the background.

Refresh affects only Computers created afterward. A Computer keeps the image it started from for its whole life, and its disk then changes only through its own work.

The age limit is enforced when a Computer is created and when a Deployment is promoted. Promoting a Deployment activates its every policy for background preparation. The interval is best effort: a usable build already in progress satisfies the interval, missed intervals are coalesced, and capacity or an executor awaiting physical shutdown can delay work. It does not guarantee a successful image at each interval; the age limit allows two missed intervals before a new Computer waits for preparation.

Helmr keeps the newest usable prepared image for each immutable recipe and images still needed by existing Computers or waiting preparations. Superseded payloads are reclaimed after the producing executor has stopped; image identities and build history remain. A new preparation may produce different bytes if external inputs changed. Historical generated image versions are not selectable through the API.

Preparation and runtime Secrets

A Template definition has two separate sets of Secret bindings:

Binding Available to Effect of rotation
prepareSecrets prepare only. An image prepared with an older Secret version is not used for new Computers; Helmr prepares a new one. Existing Computers are unaffected.
secrets Processes in Computers created from the definition. Follows the Secret’s own delivery rules. See Secrets.

Anything prepare writes to disk becomes part of the prepared image and is copied into every new Computer. Do not write preparation Secret values to files.

Revoking a prepareSecrets Secret stops new preparations that need it and keeps images prepared with it from being used for new Computers. Existing Computers keep running; when the binding is raw, helmr computer list --secret NAME marks them as possibly holding the value through their image.

Bindings use stable Secret IDs, never values. Runtime bindings are fixed when a Computer is created: it takes the definition’s secrets, or the bindings passed explicitly to client.computers.create.

Template network policies apply to the actual Computer and have a separate resolved preparation phase. Changing a policy changes preparation identity and newly selected definitions; existing Computers keep their original pins. See Execution policies.

Lifecycle

Starting an Agent without an existing Computer creates a new one from the Agent’s Template definition. You can also create a Computer directly and place Sessions on it:

const computer = await client.computers.create({
  template: "repo",
  key: "repo:acme/app",
  idempotencyKey: "create:repo:acme/app",
})

await client.sessions.create({ agent: "fixer", input: [{ type: "text", text: "Fix the failing test" }],
  computer: { id: computer.id }, })

key is an optional immutable lookup value; it does not make creation get-or-create. Several Sessions can use one Computer and see each other’s committed files. Use separate Computers when work must not share files or Secret placements. Workloads in one Environment are mutually trusted.

A Computer’s status is its resource lifecycle: available, deleting or deleted. Its residency describes where it is running; the Console shows the residency as a Computer’s status, and the lifecycle only while it is deleting or deleted:

Residency Meaning
starting Its image is being prepared or a machine is being started for it.
running It is running on a worker.
cold It is not running and has no ready memory checkpoint.
parked Its durable memory checkpoint is ready; background progress is paused.
restoring It is resuming from hibernation.
parking Capture or physical release is in progress.
unavailable It cannot run; error carries a code such as computer_preparation_failed or computer_recovery_required.

Use await computer.hibernate() to request hibernation of the whole Computer, or await computer.wake() to resume background execution without sending a prompt. Both return an accepted-operation receipt; observe computer.get() and executionControl for completion or failure. An optional idempotencyKey makes retries return the same accepted operation. Hibernate rejects active foreground work; it does not cancel work or queue a deferred sleep instruction.

Console provides the same actions and shows how many open Sessions hibernation pauses before you confirm; GET /v1/computers/{computerID}/hibernate-preview returns that count as { "sessions": N }. Wake does not release Session holds, reopen closed Sessions or change Slack mute.

Helmr also hibernates a Computer on its own when its Sessions’ Agents set hibernateAfterIdle and every open Session has been idle that long, or when the Computer has had no open Session and no unsettled Command for 10 minutes. See Hibernation.

Starting a Session or a Command on a Computer starts or restores it as needed. This applies after explicit and automatic hibernation. Rejected wake admission preserves the sleeping checkpoint. Failures after an accepted wake require observing the operation state; they do not imply rollback. See Durability for what is saved and when.

A Computer is unused when all its Sessions are finished, its Commands have settled and its disk saves are complete. After its origin Template’s deleteAfterUnused, Helmr deletes it. New work resets that interval; internal saves do not. A Computer that should live longer is created from a Template with a longer period. Delete a Computer explicitly at any time. Deleting cancels its Sessions and the Sessions they started, and its unfinished Commands; computers.delete is enough.

Commands

A Command runs one argv command inside a Computer, independent of any Session. It has its own ID, outcome and output logs, and it can change the Computer’s files. Commands default to /workspace as their working directory. A Command owns a bounded process scope: when its main process exits, including a successful exit, Helmr terminates remaining descendants. Starting a background server with sh -c 'server &' therefore does not keep that server running after the Command finishes.

helmr computer exec --id "$COMPUTER_ID" -- git status --short

Inside Agent code, run local work as ordinary child processes. See Run commands.

A Computer can also report an execution_wait reason for accepted runnable work: scheduling while compatible placement is pending, environment_limit while the Environment’s execution limits prevent admission, or saving while a save or checkpoint transition blocks follow-up work. The SDK exposes this as executionWait. An idle Computer reports null; this field does not give an ETA or replace residency, errors, or Session holds.