Cadence
Guides

Staff a stage with a pool

Create a worker version, pin a pool to it, and route a stage's work to the pool.

This guide staffs a stage so that a task entering it is worked automatically. You will create a worker version, pin a pool to it, and add an assignment rule that routes the stage to the pool. It assembles three pieces the reference pages document separately; if the vocabulary is new, read Pools and workers first.

Before you start

Every step here needs admin on the space. See Authentication. You also need, already in place:

  • A workflow with the stage you want to staff.
  • A worker registered in the space, and an image in the space's catalogue. See Workers and Images.
  • For an agent, a registered account with the LLM vendor you will choose in step 1, holding at least one token that is live, can be read, and is not held back by its limit or by the vendor. Register it in the space, or have an instance administrator register it for the whole instance. If the space has its own registration of that vendor, the token must be in that registration: Cadence uses the instance's registration only when the space has none of that vendor. Token values are entered in the browser only. See LLM providers. Without such a token, the pool's workers do not start and every task they lease is held for you.

The examples use MCP tools, which expose the full configuration; the Fleet reference lists every field.

1. Create and publish a worker version

A pool runs a specific worker version, so create one and publish it. Build a draft with worker_versions_create_draft. Its one required argument is worker_id — the id of the worker you registered in the space; omit it and the call is refused. For an agent, also give its image_id, system_prompt, llm_vendor, model, and initial_prompt, and optionally an effort. Then freeze it with worker_versions_publish.

To choose the vendor and model, call llm_models_list, optionally narrowed to one vendor:

// llm_models_list
{ "vendor": "anthropic" }

Each row names a model you can set. Pick one whose deprecated is false, and, if you want an effort other than the default, one of its efforts:

{ "vendor": "anthropic", "model": "claude-sonnet-5", "title": "Claude Sonnet 5", "efforts": ["low", "medium", "high", "xhigh", "max"], "default_effort": "high", "deprecated": false }

Then create the draft with that vendor and model:

// worker_versions_create_draft
{ "worker_id": 34, "image_id": 7, "system_prompt": "You are a careful code reviewer.", "llm_vendor": "anthropic", "model": "claude-sonnet-5", "initial_prompt": "Review the change on this task and record your verdict." }
// worker_versions_publish
{ "id": 91 }

Note the version's id; the pool pins it. Publishing freezes the version's fields — a later change means a new version.

The refusals you are most likely to meet here:

  • Llm vendor must be chosen (defined: anthropic, openai, google, eurouter, tensorx) — the draft has no llm_vendor. Add one.
  • Model "<model>" is not defined for <vendor> (defined: …) — that vendor has no such model. Pick one from the list the refusal gives, or from llm_models_list.
  • Effort "<effort>" is not an effort of "<model>" (allowed: …) — the model does not list that effort. Pick one from the list, or leave effort out for the model's default.
  • model "<model>" is deprecated for <vendor> (choose one of: …) — from worker_versions_publish. A deprecated model can be saved on a draft but not published; update the draft with another model and publish again.

Choosing a vendor, model and effort lists every refusal.

2. Pin a pool to it

Create a pool that pins the version, with pools_create. Give it a size of at least one so it can run work:

// pools_create
{ "space_key": "OPS", "worker_version_id": 91, "size": 1 }

If the worker_version_id does not exist, the call is refused with unknown worker_version_id — check the id from step 1. Note the new pool's id.

3. Route the stage to the pool

Add an assignment rule that points the stage at the pool, with assignment_rules_create. The rule binds a task type and a stage to the pool, so name the task_type (a task-type slug in your space) and the stage you want to staff:

// assignment_rules_create
{ "space_key": "OPS", "workflow": "delivery", "task_type": "chore", "stage": "In review", "pool_id": 12 }

What happens now

When a task enters that stage, the pool leases it to a worker running your published version, and the worker works it — no one dispatches it by hand. This holds as long as the pool has a non-zero size and is not paused, the task has no blocking hold, no uncleared dependency, and no unpassed required check at the stage, and — for an agent — the registration serving the space for the version's vendor has a token it can serve. That is the space's own registration of the vendor if it has one, and the instance's only if it has none: a healthy instance registration does not help when the space's own has no token to serve. If no token can be served, the worker does not start: Cadence holds the task with a spin-up failure and does not retry or get the task moving again on its own. A person must, unless a worker whose lease reaches the task replaces the hold with an advisory one and clears it. A worker that moves the task does not get it moving: a move keeps the blocking hold, so no pool starts on the task at its new stage until the hold is cleared (see Web interface § Making a task wait for a person). First add a token, free one, or repin the pool — see LLM providers § How a token reaches a worker for every cause and its fix. Then clear the hold on each held task, with tasks_clear_hold or the Clear hold button in the task drawer; each task the pool failed to start carries its own hold. Clearing dispatches the task again at its stage. That starts your pool only when this stage's assignment rule names it and applies to the task, the pool is not archived, the task has no unresolved dependency that blocks at its current stage and no unpassed required check, and no lease of the pool is active on the task the rule leases. A rule with target: parent leases the task's parent instead, and starts nothing if the task has no parent or the parent is not of the type the rule names. So fix the cause first, or the next lease fails and holds it again. See Hold a task and clear a hold § 3. For exactly what runs on its own and what still waits for you, read What moves a task without a person.

On this page