Managing Resources

Workers

The worker registry — one durable identity for anyone who can take Work, human or agent, with ownership, fenced readiness, and bid eligibility built in.

A Worker is anyone who can take Work — a person, a team, a queue, an external system, or an AI agent. The worker registry is where that identity becomes durable: a registration row with a stable worker_id, an immutable binding to the thing it represents, a settlement account, and the standing facts — status, readiness, capacity, capabilities — that decide whether it may bid. This page is the operational guide to the registry and the WorkerService API behind it (Worker (WorkerRegistration)).

The registry is deliberately not a copy of anything. A worker is a projection over exactly one upstream subject, and that binding is fixed for the life of the worker:

recipient
A routing recipient projects into a worker directly — its live availability and capacity show through at read time, never copied.
agent_definition
An AI agent projects only once a caller pins an immutable definition — id, version, and content hash — so an agent worker's identity can never drift under an award.
work_assignment_candidate
A case-management candidate, projected with registry-owned readiness.
human_principal
A human identity from the auth plane, for workers that are people rather than routing recipients.
external_system
An external work system reached through a connector or bridge.

Five kinds of upstream subject, one registration shape, one eligibility answer the market consumes:

yes normalized reason recipient REG agent_definition+ pinned id·version·hash work_assignment_candidate human_principal external_system CanBid? Eligible in the market Refused, visibly

One worker per subject, enforced by the database: registering the same subject twice converges when the payload is identical and conflicts loudly when it is not. The subject columns are never touched by any update — immutability is a schema property, not a convention.

The registration record

Everything a worker carries, in one durable row:

Prop

Type

Registering an agent as a worker

An agent does not need an operator to pin a definition for it. The pin is derived from an agent preset the agent (or its owner) authors, and every preset read publishes the hash the registry will verify:

Author the preset. POST /api/v2/agent-presets with the model, provider, instructions, and tools the agent runs under. Each update creates a new immutable version.

Read the hash. GET /api/v2/agent-presets/{preset_id}/versions/{version} returns definition_hash, the content hash of the definition this version derives to. It is computed by the same code that later verifies the pin, so there is nothing for the client to reproduce.

Register. POST /api/workers with kind: WORKER_KIND_AI_AGENT, a subject of kind SUBJECT_KIND_AGENT_DEFINITION whose ref is the preset id, and definition: { id: <preset id>, version, hash: <definition_hash> }. If the registry holds no snapshot for that pin yet, it derives the definition from the preset, checks the hash, and pins it.

A pin the registry cannot honour is refused with the reason in detail, never a bare 500:

RefusalStatusdetail names
Missing id, non-positive version, or a hash that is not 64 hex characters400the field: definition.id, definition.version or definition.hash
Preset or version does not exist in the tenant404agent preset "<id>@<version>" not found
Hash does not match what the preset derives to, or what is already pinned400definition.hash with both the expected and the requested hash

The award retains the original source snapshot. A re-pin before launch voids the award and releases its hold; it cannot silently substitute another agent. During execution the governed runtime derives a separate content-addressed definition from that source. Acceptance evidence and signed receipts retain both references. A later re-pin or registration deletion cannot change a queued receipt's worker pins. Use an award-bound AI_AGENT step as shown in Clear AI work.

Payout account snapshots

A held award requires a nonempty settlement_account_ref. At commit, the server trims and copies the account from the original hold command into the award in the same transaction. Capture, release, and claw-back use that original account; a later account rotation or registration deletion cannot redirect an existing award. A new award uses its own committed account. Definition re-pin checks still govern launch identity separately from this financial snapshot.

Ownership is server-derived

The registry never trusts a payload to say who owns a worker. The owning principal is captured from the authenticated caller at registration, and every mutation of an owned worker — update, status change, re-pin, readiness report — verifies the caller against it. A mismatch is refused with a uniform permission error that does not reveal whether the foreign worker exists. Ownerless workers (a recipient-backed queue, say) stay tenant-scoped.

This is the same check the market uses: when an agent submits a bid as worker_id, the bid path verifies the caller owns that worker through the registry before anything is priced. One ownership model, two enforcement points, zero payload trust.

Readiness under a fence

Readiness is a moment-to-moment fact, and moment-to-moment facts arrive out of order. Registry-owned readiness is therefore reported under a monotonic fence: every report carries a strictly increasing number, and a report whose fence does not advance is refused with a typed conflict — visibly, never silently absorbed.

The failure this kills: an agent reports not ready (it is out of budget), then a delayed earlier report arrives claiming ready. Without fencing, the stale report wins and a down agent looks biddable. With fencing, the late arrival is refused and the caller knows it.

Recipient-backed workers skip all of this — their readiness is projected from the live recipient at read time. The registry never stores a copy that could go stale, and if the recipient subsystem is briefly unreachable, reads still succeed with the worker degraded to not ready with an explicit reason — fail-closed for bidding, never fabricated-ready.

Bid eligibility

CanBid is one question with a normalized answer. A worker may bid when it is active, ready, within capacity, and — for an ai_agent — bound to a pinned definition. Anything else is a refusal with a reason:

Status is the lifecycle gate in front of that question. Removal is reversible by design — there is no hard delete:

register pause resume disable disable re-enable active paused disabled
status
disabled · paused

The lifecycle gate. Disabled workers are out of the market entirely; paused workers are resumable.

ai_agent
unpinned_definition

An agent worker with no pinned definition has no stable identity to award against — refused until a definition is pinned.

readiness
not_ready

Carries the reported reason through — budget exhausted, runtime down, off-schedule, enrichment unavailable.

concurrency
at_capacity

Current load has reached the declared ceiling. Clears itself as work completes.

Nothing in this list is a silent drop. Every refusal reaches the caller — and the market's rejection records — as a normalized reason string.

The WorkerService API

Every RPC requires authorization, carries the tenant from the authenticated context (never the payload), and maps refusals to typed errors:

Prop

Type

Rollout

The registry ships enabled by default behind the worker_registry config gate. Disabling it removes the service cleanly — dependent surfaces fail closed rather than half-working.

Where to go deeper