Workers and Health API
The workers and health endpoints expose the runtime state of the worker pool and the scheduler. Both are public (no authentication required) and are suitable for use in load balancer health checks and operational dashboards.
How sessions yield control and park while waiting for events.
Monitor the worker pool in the console.
Endpoints
| Method | Path | Auth | Summary |
|---|---|---|---|
| GET | /v1/workers |
none | List registered workers |
| POST | /v1/workers/{worker_id}/drain |
required | Mark a worker as draining |
| GET | /v1/health |
none | Liveness probe with scheduler and worker metrics |
GET /v1/workers
Returns the list of workers registered in the pool with their current status, capacity, and heartbeat.
{
"items": [
{
"id": "wrk-d5ba94ecac66",
"host": "build-host",
"pid": 3371965,
"capacity": 8,
"started_at": "2026-06-07T19:00:55.238423Z",
"last_heartbeat": "2026-06-07T19:00:55.238423Z",
"status": "active"
}
]
}
| Field | Type | Description |
|---|---|---|
id |
string | Worker identifier (prefix wrk-) |
host |
string | Hostname of the process |
pid |
integer | Operating system process id |
capacity |
integer | Maximum concurrent sessions this worker accepts |
started_at |
datetime | When the worker process registered |
last_heartbeat |
datetime | Timestamp of the most recent heartbeat |
status |
string | One of active, draining, dead |
curl https://your-host/v1/workersimport httpx
r = httpx.get("https://your-host/v1/workers")
workers = r.json()["items"]const r = await fetch("/v1/workers")
const {items} = await r.json()Note: No Authorization header is needed. This endpoint is public.
POST /v1/workers/{worker_id}/drain
Marks the specified worker as draining. The worker stops accepting new session claims but continues serving any sessions already in flight. Returns 204 No Content.
The worker's status field on GET /v1/workers flips to draining immediately; the row remains visible throughout the drain window. The actual process shutdown happens externally (for example, via a SIGTERM to the worker process). Poll GET /v1/workers to observe the status transition.
curl -X POST https://your-host/v1/workers/wrk-d5ba94ecac66/drain \
-H "Authorization: Bearer $TOKEN"import httpx, time
token = "..."
r = httpx.post(
"https://your-host/v1/workers/wrk-d5ba94ecac66/drain",
headers={"Authorization": f"Bearer {token}"},
)
assert r.status_code == 204
# Poll the drain status
for _ in range(30):
workers = httpx.get("https://your-host/v1/workers").json()["items"]
row = next((w for w in workers if w["id"] == "wrk-d5ba94ecac66"), None)
if row and row["status"] == "draining":
break
time.sleep(0.5)const r = await fetch("/v1/workers/wrk-d5ba94ecac66/drain", {
method: "POST",
headers: {"Authorization": `Bearer ${token}`}
})
// r.status === 204Guarantee: Every GET /v1/workers and GET /v1/health call during the drain window returns a clean 2xx response with no 500 or /errors/internal envelopes. The drained worker row stays present and identifiable throughout.
Errors: 500 on internal failure.
GET /v1/health
Liveness probe that returns 200 OK whenever the API process is responsive. Includes scheduler liveness and worker pool capacity metrics.
{
"status": "ok",
"version": "0.3.0",
"scheduler": {
"alive": true,
"metrics": {
"primer_sessions_active": {},
"primer_sessions_runnable_queue_depth": 0,
"primer_lease_expirations_total": 0,
"primer_scheduler_notify_received_total": 0
}
},
"worker_pool": {
"in_flight": 0,
"capacity": 8,
"metrics": {
"primer_worker_id": "wrk-d5ba94ecac66",
"primer_worker_in_flight": 0,
"primer_worker_capacity": 8,
"primer_worker_claims_total": 1,
"primer_worker_claims_empty_total": 7,
"primer_session_turns_total": {},
"primer_session_turn_duration_seconds": {"count": 0, "sum": 0.0}
}
}
}
| Field | Type | Description |
|---|---|---|
status |
string | Always "ok" when the process is responsive |
version |
string | API surface version (semver) |
scheduler.alive |
boolean | True when the in-process scheduler is running |
scheduler.metrics |
object | Snapshot of scheduler counters and gauges |
worker_pool.in_flight |
integer or null | Sessions currently executing; null in API-only mode |
worker_pool.capacity |
integer or null | Configured per-worker concurrency; null in API-only mode |
worker_pool.metrics |
object | Snapshot of worker-pool counters and histograms |
curl https://your-host/v1/healthimport httpx
r = httpx.get("https://your-host/v1/health")
health = r.json()
assert health["status"] == "ok"
capacity = health["worker_pool"]["capacity"]
in_flight = health["worker_pool"]["in_flight"]const r = await fetch("/v1/health")
const health = await r.json()
const {capacity, in_flight} = health.worker_poolNote: No Authorization header is needed. This endpoint is public and suitable for use as a load balancer health check target.
Errors note
All error responses use the RFC 7807 ProblemDetails envelope with type, title, status, detail, instance, and extensions (which includes request_id). See the REST API overview for details.