LLM providers
Register a vendor account, hold its tokens, set usage limits, read usage, and have an agent worker version's workers draw on it.
An LLM-provider registration is a vendor account Cadence can draw on to run your
agents. A registration names one vendor and holds one or more tokens — the
credentials that vendor's tool authenticates with. Each token carries a label,
an optional usage limit, and the usage Cadence reads against that limit. An
agent worker version names
a vendor, and a worker running that version is served one of that vendor's tokens
when its pool leases a task.
A registration exists at one of two scopes: a single space, or the whole instance. A space's own registration serves that space's pools; an instance-wide registration is the fallback for any space that has no registration of that vendor. The vendor comes from the lease's worker version; the pool supplies the space. A worker draws on the pool's space's registration for that vendor if there is one, otherwise the instance-wide registration.
Registrations and tokens are retired, never deleted. Retiring one stamps it retired and keeps the row, so its value stays available to log redaction. A retired registration is no longer resolved for a worker, and a retired token is no longer served or selected.
Every operation on this page needs admin. The space-level surface needs admin
on the space; the instance-level surface needs an instance administrator, and a
space admin is not an instance administrator. See
Authentication. Replace https://cadence.example.com
with your instance's address.
A token value is entered in the browser only. There is no HTTP API or MCP path that accepts a token value — a value never crosses either boundary. MCP reads a registration and sets a token's limit; the browser is where you register a vendor, enter and rotate token values, and refresh usage.
Read and set limits over MCP
Four tools work a space's registrations over MCP. All four are admin-only, all four read cached readings only — they never probe the vendor — and no token value ever crosses the boundary.
llm_providers_listlists the registrations serving a space: the space's own and the instance-wide fallbacks, each marked with itslevel(spaceorinstance), with itsvendor, its live token count, and whether it is retired. Live and retired registrations are both listed. It takesspace_key.llm_providers_getreads one registration byprovider_id(as returned byllm_providers_list), with a row per live token:label,limit,usage,headroom, reset time, whether the reading is measured and accepted, the age of the reading, and the held-back reason. Every row is drawn from the cached reading only; a token with no cached reading reads as not read yet. It takesspace_keyandprovider_id.llm_provider_tokens_updatesets or clears one token's usage limit, addressed byspace_key,provider_id, and the token'slabel. Passlimit_valueas an integer to set the limit, ornullto clear it —limit_valueis required (limit_value is required (an integer to set, null to clear)if omitted). The limit is the only field this touches; a request carrying any other field is refused. The limit is validated by the vendor adapter (see Accepted vendors and their limits).llm_provider_tokens_removeretires one token bylabel, addressed byspace_keyandprovider_id. The token's value is kept for log redaction.
The two write tools are space-scoped. They act on the space's own registrations
only. Addressing one at an instance-wide registration is refused with instance-wide registration is read-only through a Space-scoped tool; change it in instance settings — an instance-wide registration is changed in instance settings by an
instance administrator. An unknown registration is refused with unknown provider_id, and a label with no live token is refused with no live token labelled "<label>".
Register, enter tokens, and refresh in the browser
Registering a vendor, entering and rotating token values, and refreshing usage are done in the browser.
- Space scope: the LLM Providers section of the space's settings. Register a vendor, retire a registration, and add, relabel, re-limit or retire its tokens.
- Instance scope: the LLM Providers screen at
/settings/llm_providers, reachable only by an instance administrator. The same register, retire, and per-token forms, for registrations that serve the whole instance.
On both, the Vendor select lists the vendors by title: Anthropic, OpenAI, Google, Eurouter, TensorX.
Each token is its own form, so relabelling or re-limiting one token submits that token alone — no other token's value is read or rewritten. A token value is never rendered back into a form, even when the form is redisplayed after an error, so a value you type is never shown again. A token's value cannot be changed once it is entered: editing a token changes its label and limit only. To replace a value, add a new token with the new value and retire the old one. Two live tokens in one registration cannot share a label, so give the new token a different label, or retire the old one first.
A registration refuses a second live registration of a vendor already registered at the same scope, and an unknown vendor name. A token refuses a blank label or value, and a second live token with a label already live in that registration.
Refresh
Refresh is a per-registration action, and it is the one screen action that causes traffic to the vendor: it re-reads the registration's tokens through the vendor and writes the fresh readings to the cache the token summary draws from. Every other view — listing, opening a registration, the MCP reads — reads the cache and never probes the vendor. After a reset or a fresh deploy the cache is empty, and a token reads as not read yet until the next refresh or the next time a lease reads it.
Accepted vendors and their limits
A registration's vendor is one of five names:
| Vendor | Limit | Range | How usage is read |
|---|---|---|---|
anthropic | Percentage of the rolling seven-day utilisation | 0–100 | Anthropic's own published seven-day utilisation percentage |
openai | Whole number of tokens over the rolling seven days | 0 or more | Cadence's own count of the fleet's token counters over the rolling seven days |
google | Whole number of tokens over the rolling seven days | 0 or more | Cadence's own count of the fleet's token counters over the rolling seven days |
eurouter | Whole number of euros of seven-day spend | 0 or more | Eurouter's own seven-day spend figure for the token |
tensorx | Whole number of tokens over the rolling seven days | 0 or more | Cadence's own count of the fleet's token counters over the rolling seven days |
A token with no limit set is never held back. When a limit is set, the token is held back once its usage reaches the limit, and is not served to a worker until its usage falls back under it.
A limit outside the vendor's unit and range is refused, with a message that names the
unit and range. Over MCP, anthropic refuses with limit must be a percentage between 0 and 100 (7-day utilisation); openai, google and tensorx refuse with
limit must be a whole number of tokens (0 or more) over the rolling seven days; and
eurouter refuses with limit must be a whole number of euros (0 or more) of seven-day spend. In the browser, the limit field refuses with must be a percentage between 0 and 100 or must be a whole number of percent for anthropic; must be zero or more tokens or must be a whole number of tokens for openai, google and
tensorx; and must be zero or more euros or must be a whole number of euros for
eurouter, whose limit field is labelled Seven-day spend limit (EUR).
Held back by the vendor, whatever the limit
Two vendors can hold a token back even when it has no limit set, or is under it, because the vendor itself will not serve it:
eurouter—held back: Eurouter account credits are exhaustedwhen the account's credits are spent (a remaining balance under 0.10 euros counts as spent), andheld back: Eurouter's own credit cap on this key is spentwhen the per-key cap set in Eurouter is used up. A token held back by its own limit readsheld back by its <limit> EUR limit (7-day spend <spend> EUR).tensorx—held back: TensorX credits are exhaustedwhen TensorX answers that the account's credits are exhausted.
A Eurouter key that Eurouter rejects, or one disabled in Eurouter, is a rejected credential: it cannot be read, and it is not served. A Eurouter answer that the account has no credits left is the credits-exhausted case above. Any other failure to read a Eurouter key leaves the token Could not be measured — still selectable (see The token summary).
For every vendor, a key the vendor refuses outright is a rejected credential that
cannot be read and is not served. For anthropic, a token whose usage cannot be
fetched at all — a network error or a timeout — cannot be read either, and is not
served. For openai, google and tensorx, a failure to reach the vendor leaves
the token Could not be measured, and still selectable.
For openai, google and tensorx, the usage figure is Cadence's own count of the token
counters your workers report, not a figure the vendor confirms — the token summary
labels it as such so you do not read it as the vendor's own account.
The token summary
For each live token, Cadence reads a summary against its limit — the same figures on
the browser section and through llm_providers_get:
- Usage — how much of the token's allowance has been spent, in the vendor's unit
(a percentage for
anthropic, a token count foropenai,googleandtensorx, euros foreurouter). - Limit — the operator-set limit, or none.
- Headroom — limit minus usage, floored at zero. Meaningful only for a measured reading against a set limit; otherwise none.
- Reset time — when the counted usage falls back out of the rolling window.
- Reading age — how old the reading is, in seconds since it was read.
A reading is in one of these states, and the two held-back states mean opposite things:
- Not read yet — no cached reading. The normal state after a reset or a deploy, until the next refresh or lease reads it.
- At its limit — a reading was taken and the usage met the limit. The reservation is working; the token is held back until its usage falls back under the limit.
- Could not be measured — a reading was taken but the usage could not be established. The token is not treated as at its limit — it stays selectable — so a measurement fault does not read as a spent account. This is a measurement to investigate, not a token that is out of allowance.
How a token reaches a worker
A worker on an agent pool is served two environment
variables in its lease, for the vendor named by the llm_vendor of the agent
version the lease runs:
LLM_TOKEN— the selected token's value.LLM_PROVIDER— that token's vendor name:anthropic,openai,google,eurouter, ortensorx.
The vendor is the lease's own version's, recorded when the lease is created — not the pool's. Repinning the pool to a version with another vendor changes the registration its later leases draw on. A runner or classifier lease is served neither variable, and no token is read for it. Neither is a lease whose version names no vendor: a version published now must name one, so only a version made before vendors were required can.
Cadence selects the token once per lease and records it on the lease. The first time the lease dispatches, Cadence reads the registration serving the pool — the pool's space's registration for the vendor, or the instance-wide fallback — reads its live tokens, passes over any it cannot read, excludes any held back by their limit or by the vendor, and serves the one with the most headroom. It reads only that one registration: if the space has a registration of the vendor, the instance-wide one is not consulted, even when none of the space's tokens can be served. That token is recorded on the lease, so a later dispatch of the same lease serves the same token rather than choosing again.
A worker version's own env declaration wins. If a worker version declares env for
LLM_TOKEN or LLM_PROVIDER, its declared value is served and Cadence's served
value is not.
If the lease's version names a vendor but no live token can be served — neither
the space nor the instance has a registration of that vendor, or every live token in
the registration serving the space is held back or could not be read — the worker
does not start. Cadence
records worker_spin_up_failed on the task, ends the lease as failed, and puts a
blocking hold on the task, naming the vendor, the pool, and which tokens were held
back and which could not be read. Cadence does not retry around this. To get work
moving again, a person has to do one of these:
- if neither the space nor the instance has a registration of the vendor, register it in the space, or have an instance administrator register it instance-wide. If the space already has one, an instance-wide registration does not help: fix the space's;
- add a token to the registration serving the space;
- free a token held back by its limit, by raising or clearing the limit;
- for a token held back by the vendor, top up the account, or raise the key's own cap, with the vendor;
- for a rejected credential, add a new token with a working key and retire the rejected one — a token's value cannot be edited;
- repin the pool to a version that names a vendor with a token to serve.
Then clear the hold on each held task, with tasks_clear_hold or the Clear
hold button in the task drawer in the board view. Each task whose lease failed
this way carries its own hold. Cadence never clears the hold, and the clear tools
refuse a worker. But a worker whose lease reaches the task can replace the hold
with an advisory one and then clear it, with no person involved. A worker can also
move the task, but 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.
Clearing dispatches the task again at its stage. That starts a pool only when an
assignment rule at the stage names the pool 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 that pool is active on the task the rule leases. A rule with target: parent leases the
task's parent, not the task, and starts nothing if the task has no parent or the
parent is not of the type the rule names. A pool you assigned the task to, a scheduled rule's pool
or an inbound rule's pool is not started again by a clear. So fix the cause first:
clear the hold while no token can be served, and the next lease fails and holds
the task again. See Hold a task and clear a
hold § 3. Set a limit or
leave a registration short of a selectable token, and every pool whose version
names that vendor, in each space that registration serves, fails to start its
workers and holds their tasks. Cadence does
not start them again on its own.
Audit events
LLM-provider actions are recorded in the audit feed under
these kind values, readable by filtering on kind:
kind | Recorded when |
|---|---|
llm_provider.registered | A vendor is registered |
llm_provider.retired | A registration is retired |
llm_provider.resolved | A lease selects a token to serve a worker |
llm_provider.resolution_failed | A lease could not select a token to serve a worker |
llm_provider_token.added | A token is added to a registration |
llm_provider_token.updated | A token's label or limit is changed |
llm_provider_token.retired | A token is retired |
No audit event carries a token value.