Skip to main content
Version: 0.1 (next)

Runner pools

A runner pool is room on one person's machine for an org's agent steps. With the org's steps placed on the pools, the operator offers each agentRole step's attempt as an AgentVM instead of starting a runner Job; a pool's node agent leases it, runs it as a VM, and reports the runner's result, which the operator records exactly as it records a Job's. The step's verdict, evidence, usage and pull request are the same either way.

Today a runner pool runs on a Mac with Apple's container runtime (container 1.5.0 or later), for the Infrared that ir local runs on the same Mac.

A pool is an option an org turns on, not the default: an org's agent steps run as runner Jobs in the cluster (placement jobs) unless its placement says pools. A pool changes where a step runs, not what it costs: its VMs run the same runner with the org's model key, an Anthropic API key, as a Job does.

How a step runs on a pool​

  • Exactly one pool runs an attempt. The API grants each AgentVM's Lease to the one pool whose request wins it.
  • A machine that sleeps or crashes loses the lease. Five minutes without a heartbeat and the AgentVM is Lost: the operator runs the step again. A node agent that is stopped gives its leases back at once, so its steps run again right away. Lost attempts count apart from the agent's own failures, at most three, so a closed laptop does not use up a step's attempts.
  • Nothing waits forever by default. When no pool that takes a step has been seen for two minutes, the step runs as a runner Job (fallback: jobs). With fallback: wait, it waits for a pool.
  • Some steps always run in the cluster: a step that publishes images, delivers to Slack or uses an MCP server.

Turn it on​

  1. Place the org's agent steps on the pools (an org admin; ir agent-steps get shows the placement):

    ir agent-steps set --placement pools # a step waits two minutes for a pool, then runs as a Job
    ir agent-steps set --placement pools --fallback wait # a step waits for a pool

    On a Mac, ir local up <stack> --pool brings a stack up with its pool connected and the org's steps placed on it, and ir local pool connect <stack> --model-key-file <your key file> --place does the same for a stack that is up.

  2. Connect the Mac's pool. It writes the RunnerTemplates and the RunnerPool, mints a pool token that can lease and report the pool's AgentVMs and nothing else, keeps your Anthropic API key under ~/.localred/<stack>/pool (mode 600), and pulls the runner image:

    ir local pool connect <stack> --model-key-file <your key file>
  3. Run the node agent in a terminal:

    ir local pool run <stack>

    ir local pool install <stack> runs it under launchd, at login and again whenever it exits, but macOS's Local Network privacy keeps a program launchd starts this way off the stack's network today, so run it in a terminal.

ir local pool status <stack> shows the node agent, the pool as Infrared records it and its AgentVMs. ir local pool stop <stack> kills the pool's VMs and gives their leases back. To turn pools off, ir agent-steps set --placement jobs.

What a VM can reach​

The runnerThe agent
Your Anthropic API key, the step's forge tokenIn its environmentNo: started with an empty environment, as another user
Your SSH agentNo: a RunnerTemplate cannot forward itNo
Your Mac's filesThe step's spec and the stack's certificate authority's certificate (never its key), both read-onlyNone
Where it writesIts own working directories in the VMIts own working directories in the VM

Each step's VM is deleted when it ends. The step's forge token is minted for the attempt and revoked with it, as for a Job. The mounts are read-only because a file a VM writes to a mounted folder lands on your Mac as you, whichever user in the VM wrote it.

Templates​

TemplateCPUsMemoryRuns
reviewer21 GiBreview, issue and report steps
builder-step46 GiBbuild and resolve steps
agent22 GiBan interactive Claude Code a person starts by hand

--room on ir local pool connect sets how many VMs the pool runs at once (default 2); --takes the step modes it takes. Run connect again to change them: it replaces the pool token, and a running node agent takes up the new one.

An agent of your own​

ir local vm run <stack> --mount <folder> starts the agent template's Claude Code in a VM of its own, in your terminal, with only the folders you name, each under your home folder. Each is writable from the VM, as you, unless you add :ro (--mount ~/src/docs:/docs:ro). You sign it in with your own subscription. ir local vm ls <stack> lists every AgentVM with its pool, phase, CPU time and peak memory; ir local vm logs and ir local vm kill read and end one.

Watch it​

  • kubectl --context <stack> -n ir-org-<org> get agentvms,runnerpools,leases
  • The metrics infrared_agentvm_phase{pool,template,phase}, infrared_lease_lost_total{pool}, infrared_agentvm_peak_memory_bytes{template} and infrared_agentvm_cpu_seconds{template}, on the operator's metrics port. See Observability.