Skip to content

Node-agent internal: claim this host's due agent-plane job runs. (Not operator-facing.)

GET
/v1/agent/jobs/pending
curl --request GET \
--url http://localhost:8080/v1/agent/jobs/pending \
--header 'Authorization: Bearer <token>'

THE CLAIM IS THE RESPONSE. Returning a run and marking it running is one statement (FOR UPDATE … SKIP LOCKED), so two polls arriving together take DISJOINT sets rather than both executing the same warm-up. Capped at 5 runs per poll: a host coming back after an outage with a dozen jobs due must not start all of them at once, and the rest are still pending because the work is a durable row. A claim that is then never reported is not lost work — the dispatcher’s reaper aborts it after deadline_secs and materializes a fresh pending row. An empty list is the steady state, and is also what this returns when the jobs master switch is off: the switch is re-read HERE as well as in the dispatcher, because the dispatcher is what stops rows being CREATED and this is what stops an already-materialized row being HANDED OUT.

OK.

Media typeapplication/json
object
runs
required

Capped at 5 per poll; [] is the steady state and also the answer when the jobs master switch is off.

Array<object>

One run claimed by the calling host. Returning it and marking it running is ONE statement, which is what makes concurrent polls take disjoint sets.

object
run_id
required
string format: uuid
job_id
required

The registry job id, e.g. “template.warmup”.

string
params
required

The opaque per-job JSON the control plane stored when it materialized the run (for an event trigger, whatever the event carried). The framework NEVER interprets it; the agent hands it to the runner. {} rather than null when there is none. Bounded at 4096 bytes by a CHECK.

object
key
additional properties
any
deadline_secs
required

After this long with no report the dispatcher ABORTS the run and re-materializes it. Sent so the agent can bound its own execution rather than discover the abort by racing it.

integer
Examplegenerated
{
"runs": [
{
"run_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"job_id": "example",
"params": {},
"deadline_secs": 1
}
]
}

Missing/invalid/expired/revoked token.

Media typeapplication/json
object
error
required
object
code
required

E.g. validation_failed, unauthorized, forbidden, not_found, conflict, session_quota_exceeded, home_in_use, home_not_provisioned, parent_app_disabled, profile_ineligible, profile_not_launchable_for_app, no_host_available, capacity_exhausted, restart_required, rate_limited, internal. Open string, not an enum: new codes are additive and an unknown one falls through to a client’s generic per-status branch.

string
message
required
string
live_sessions

Present on restart_required.

integer
session_id

Steam library discovery Phase 3, ADDITIVE: present on home_in_use when the guard could name the CONFLICTING live session - the one already holding the home. It is here so the client can offer “go to your running session” with a link instead of a dead-end toast. OMITTED rather than empty when the conflict is known but the session is not, so a client branches on presence and never renders a link to nowhere. Load-bearing once derived tiles exist: the lock is held by the PARENT’s home, so a user who clicks a game tile can be refused because a DIFFERENT app (the Steam launcher, or another game from the same install) is running, and without the session id the refusal reads as a bug. See control-api.md §Derived tiles.

string format: uuid
derived_tiles

Steam library discovery Phase 3, ADDITIVE: present on the 409 conflict from DELETE /v1/apps/{id} when the app has derived tiles and ?delete_derived=true was not sent. A LIST, not a count - the point of the confirmation is that the admin sees what they are about to destroy. Capped; an empty array means the tiles could not be listed, never that there are none.

Array<object>
object
id
required
string format: uuid
name
required
string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"live_sessions": 1,
"session_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"derived_tiles": [
{
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"name": "example"
}
]
}
}

Could not claim pending jobs.

Media typeapplication/json
object
error
required
object
code
required

E.g. validation_failed, unauthorized, forbidden, not_found, conflict, session_quota_exceeded, home_in_use, home_not_provisioned, parent_app_disabled, profile_ineligible, profile_not_launchable_for_app, no_host_available, capacity_exhausted, restart_required, rate_limited, internal. Open string, not an enum: new codes are additive and an unknown one falls through to a client’s generic per-status branch.

string
message
required
string
live_sessions

Present on restart_required.

integer
session_id

Steam library discovery Phase 3, ADDITIVE: present on home_in_use when the guard could name the CONFLICTING live session - the one already holding the home. It is here so the client can offer “go to your running session” with a link instead of a dead-end toast. OMITTED rather than empty when the conflict is known but the session is not, so a client branches on presence and never renders a link to nowhere. Load-bearing once derived tiles exist: the lock is held by the PARENT’s home, so a user who clicks a game tile can be refused because a DIFFERENT app (the Steam launcher, or another game from the same install) is running, and without the session id the refusal reads as a bug. See control-api.md §Derived tiles.

string format: uuid
derived_tiles

Steam library discovery Phase 3, ADDITIVE: present on the 409 conflict from DELETE /v1/apps/{id} when the app has derived tiles and ?delete_derived=true was not sent. A LIST, not a count - the point of the confirmation is that the admin sees what they are about to destroy. Capped; an empty array means the tiles could not be listed, never that there are none.

Array<object>
object
id
required
string format: uuid
name
required
string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"live_sessions": 1,
"session_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"derived_tiles": [
{
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"name": "example"
}
]
}
}