Skip to main content
Version: v5.7.0

Runner

Included from Basic tier

The runner as the fleet/admin API serves it: one enrolled runner identity with its advertised capability, group placement, liveness, drain state and current jobs.

The v2 OpenAPI document declares this resource's schema; the resource-field coverage gate holds this page to it.

Two endpoints serve it (both admin-token gated):

  • GET /api/runners — the list view: {"runners": [...], "server_version": ..., "server_commit": ...}, one row per enrolled, unrevoked runner, with the server's own build identity alongside (empty on an unstamped build).
  • GET /api/runners/{id} — the detail view: the list row plus registration identity, the self-reported host inventory and the server-observed peer address. Revoked ids answer 404 exactly like unknown ones — the revocation tombstone is never exposed.

The registry behind both is durable (DBRegistry) or in-memory (MemRegistry) depending on composition; the payload shape is the same. Narrative on enrolment, liveness and drain lives at opschain docs runner-registry.

List row fields​

FieldTypeMeaning
idstringThe registration id (an ocr_… credential minted at enrolment). The Ed25519 keypair, not the name, is the identity: re-enrolling the same key supersedes the previous registration under a new id.
namestringDisplay label from registration. Not unique.
groupstringThe runner group the registration token placed it in.
labelsstring arrayCapability labels advertised at registration. Absent when empty.
osstringSelf-reported OS, from registration. Absent when empty.
archstringSelf-reported architecture, from registration. Absent when empty.
runner_versionstringThe runner binary's version, read from the host inventory (host.runner_version); absent when no inventory was reported.
runner_commitstringThe runner binary's commit, read from the host inventory (host.runner_commit); absent when no inventory was reported.
version_skewstringThe runner's build identity against the server's own: none (they match), skewed (they differ — commits compare for identity, never for order), or unknown (the runner reported no identity — a pre- binary — or the server has none). A skewed or unknown runner also records one warn:runner:version_skew event per (runner, version-pair) at registration and session establishment.
executorsstring arrayExecutor kinds the runner advertises (e.g. hostexec, containerexec). Absent when empty.
max_parallel_stepsintThe runner's declared step capacity (--max-parallel-steps on the process): clamps a pinned run-scoped run's runner.max_parallel_steps to min(offered, declared). 0 = undeclared (follows the server's cap). The GUI's Runners page shows it as the Capacity column.
secrets_providersstring arrayThe secrets provider codes the runner declared it resolves at Prepare from its own secrets_providers configuration — the capability runner-resolved placement matches; refreshed from every poll that re-advertises a different set. Absent when none.
ephemeralboolThe registration token's ephemeral flag. Absent when false.
onlineboolComputed at read time: stopped_at is null AND last_seen_at is present AND younger than the 3-minute liveness window (fleetOfflineAfter).
last_seen_attimestampThe runner's last poll, recorded by TouchRunner. Absent until the runner has polled.
stopped_attimestampSet by the runner's graceful goodbye; cleared by its next poll. Absent while running.
drainingboolEffective drain: an operator drain of the runner or of its group is in force.
drain_requested_attimestampWhen the runner's own drain was requested (POST /api/runners/{id}/drain). Absent when no per-runner drain is in force; a group drain does not set it.
group_drainingboolA drain of the whole group is in force (POST /api/runner_groups/{name}/drain). Absent when false.
current_jobsarrayThe runner's in-flight job bindings (below). Absent when idle.
group_attributesstring mapThe stored group's placement attributes, echoed for selector debugging. Absent when the group row has none (or no group row exists).
group_exclusiveboolThe stored group's exclusive flag — the runner only receives work targeted at its group. Absent when false.

current_jobs entries​

FieldTypeMeaning
run_idstringThe owning run (change or workflow run).
step_idstringThe dispatched step.
attemptintThe attempt number of the lease.
ackedboolWhether the runner has acknowledged delivery of the job.
actionstringThe owning run's action — enrichment from the run record; absent when the run cannot be read (the ids still render).
target_pathstringThe owning run's target node path — same enrichment and absence rule.

Detail-only fields (GET /api/runners/{id})​

FieldTypeMeaning
registered_attimestampWhen the identity enrolled. Always present.
observed_remotestringThe server-observed peer address of the runner's connection, refreshed on poll. Absent when never observed.
hostobjectThe runner's self-reported host inventory, captured at (re-)registration and refreshed on the session-open/poll rail: hostname, addresses ([{ip, mac}]), cpu_count, go_version, runner_version, runner_commit, pid, started_at, state_dir — every member omitted when empty. Absent when nothing was reported. Admin-surface data only; never logged.
group_bindingsstring arrayThe stored group's node-path bindings. Absent when the group row has none or does not exist.
public_key_fingerprintstringSHA256: + base64 (raw, std) of the SHA-256 of the runner's Ed25519 public key. The key itself is never rendered. Absent when no key is stored.

State vocabulary​

There is no single state field; a runner's condition is read from the booleans above. The placement verdict in the fleet queue names the offline condition verbatim as "offline (stopped, or silent past the liveness window)" — i.e. stopped_at set, or last_seen_at null or older than 3 minutes. Offline and draining are separate truths: both can be true at once.

What changes it​

  • Enrolment (registration token redemption) creates or supersedes the row and sets identity, capability and registered_at.
  • Polling refreshes last_seen_at and observed_remote, and clears stopped_at.
  • Goodbye sets stopped_at.
  • POST /api/runners/{id}/drain / /resume set and clear the per-runner drain (events info:runner:drain_changed).
  • POST /api/runners/{id}/forget deletes a stale registration outright (not revocation — the identity may re-register). Refused with 409 while the runner is online or holds a live job binding.
  • Revocation (runner delete) tombstones the id and key; the runner then vanishes from both views (detail answers 404).
  • opschain docs runner-registry — enrolment, identity and liveness narrative.
  • opschain docs fleet-queue — how the fields above feed placement verdicts.
  • opschain docs platform-halt — the emergency posture that stops dispatch fleet-wide.