Livepeer Agent · Admin & ops

Onboard a capability — the six stages

One process for putting a new capability on the agent, whether it comes from a provider like fal or from a community orchestrator. The stages do not change with the source; only stage 1 does.

This page is the standard — what each stage means and why it exists. For the step-by-step sequence of verb calls, read Register a capability — the admin runbook.

Start here, every time:
cap_status({ capability: "<name>" })
It audits all six stages and prints the exact next action for each one you have not cleared, naming the file or the verb. Read-only and free, so run it as often as you like while working through the list.

Then work the gaps with the verb for each stage — cap_price (stage 2), cap_route (3), cap_docs (4 + 5), cap_probe (6), and cap_promote for the gate at the end. Everything except cap_probe is read-only and free; cap_probe renders and says so.

Why six stages

A capability that merely runs is not usable. Each stage exists because skipping it produced a specific, expensive failure:

StageWhat it meansWhat skipping it caused
1 · registeredSomething can dispatch to itNothing — this one is obvious
2 · pricedPrice = a verified upstream cost + 5%16 capabilities mispriced by up to 6×, in both directions, for months
3 · discoverableThe agent layer can route to itA name that resolved to a different model, so users were billed for one thing and served another
4 · skillA skill file teaching its real contractAgents guessing at parameters and getting extra_forbidden
5 · playbook + showcaseProof it works with other capabilitiesCapabilities nobody could find a use for
6 · measuredReal probes on the real dispatch pathTimeouts sized from guesses; renders cut off and billed anyway
The promotion rule. A capability ships reachable by explicit name after stages 1–2. It enters automatic routing — keyword intent, fallback chains, tier defaults — only on stage-6 evidence. So NAME_ONLY is a legitimate shipped state, not a half-finished one, and cap_status reports it as such.

The stages

Stage 1 · registered

The only stage that differs by source

Community orchestrator — one verb, and the registry write is the wiring:

orch_register({
  discovery_url: "https://their-node.example:8935/discovery",
  contact_email: "them@example.org"
})

It validates the URL (public host, SSRF-guarded), probes discovery, classifies which advertised capabilities are onboardable, and upserts the provider registry. Capabilities land at registered; orch_update promotes them to live once verified. orch_healthcheck reconciles later — a capability that stops being advertised is marked failing and drops out of routing on its own.

Provider model (fal and friends) — a config change on the provider node plus a code entry. Verify the model id on the provider's own page first: providers rename models, and a wrong id fails at dispatch, not at registration.

A private capability of your owncap_add. It computes a semantic key and refuses a synonym of an existing capability, so the catalogue does not grow two names for one thing.

Stage 2 · priced

A price is a claim about cost

Every price is verified upstream cost × 1.05. Record the cost basis — the number, the unit, the date you read it, and the URL you read it from — and let the generator produce the price. Never hand-edit a generated price row.

Three things that have each gone wrong here:

For a community or self-hosted capability the basis is declared rather than read off a price page — so it must carry an expiry date, and the audit fails when it goes stale. "Verified" keeps its meaning that way.

Stage 3 · discoverable

Five tables have to agree

Each one fails differently when it is missing: no output kind ⇒ the result is handled as the wrong media type; no latency prior ⇒ a fabricated ETA; no timeout entry ⇒ the render is cut at the default and billed; no usage contract ⇒ the agent guesses at parameters.

The one that bites hardest: name collisions. Resolution matches by prefix before keywords, keeping the first longest match. So adding foo-2.5 can quietly steal every request for foo-2. Any version or alias spelling needs an explicit guard placed ahead of prefix matching, and the resolution snapshot updated so the change is reviewable. cap_status checks this: if a name does not resolve to itself, stage 3 is a gap.
Stage 4 · skill

Write down what the docs got wrong

A skill file is where the capability's real contract lives — especially where it departs from the provider's documentation. The most valuable lines are always the surprising ones: an endpoint that rejects a prompt outright, an option that returns extra assets free, a marketing page that advertises a tier the API schema does not accept.

Read a real response before writing the skill. Every genuinely useful thing in ours was found that way, not from a docs page.

Stage 5 · playbook + showcase

Show it working with something else

A playbook is a paste-ready brief; a showcase is the rendered proof, with real media and real numbers. The requirement is that it demonstrates the capability in combination — one capability alone rarely answers a brief, and the combination is the thing users cannot work out from a model list.

State the limits next to the output, not below the fold. A showcase that hides what a capability cannot do costs more trust than it earns.

Stage 6 · measured

Probe it, then believe the numbers

node scripts/smoke-cap.mjs --capability <name> --n 5

Real, billable renders through the production path. It records success rate, p50/p95, the failure class of each miss, and — the reason it exists — quoted cost against actual cost. A gap over 5% there means the price is wrong, not the estimate.

Then paste the numbers into the latency prior, the timeout table and the measured-p95 record. cap_status and CI both stay red until you do.

Verbs, by stage

VerbStageServerWhat it does
cap_statusall sixagentAudit one capability; get the next action per open stage
cap_price2agentIs the price derived from a verified basis at the house margin, and how does it move (tiers, add-ons, minimums)? Quote a specific request
cap_route3agentWhat will actually run for a name or an intent phrase — plus collision and fallback-modality checks
cap_docs4, 5agentDraft the skill + playbook with the derivable facts filled in; returns content, writes nothing
cap_probe6agentBillable. Up to 5 real renders → success rate, p50/p95, failure classes. Needs confirm
cap_promotegateoperatorMove into automatic routing — only with all six stages clear and ≥4 successes at ≥80%
orch_register1adminOnboard a community orchestrator and its capabilities
orch_onboard1adminProbe + classify + register in one pipeline
orch_healthcheck1, ongoingadminReconcile registry against live discovery; self-heals routing
orch_update1adminPromote registeredlive
cap_add1agentRegister a capability, dedup-guarded
cap_test_report1, 6agentProvider-facing readiness + performance verdict
describe_capability3, 4agentWhat the agent will read: params, price, aliases
get_perf_report6adminMeasured latency and success across capabilities
cap_deprecate / cap_retireend of lifeagentSteer to a successor; tombstone a name forever

read-onlycap_status, cap_test_report, describe_capability and the reports change nothing and cost nothing. Only stage 6 spends money, and only through the smoke harness.

one endpointThe “admin” column above is about the role a verb requires, not a separate address. Admin verbs and agent verbs are served by the same MCP endpoint; the admin ones simply refuse a caller without the role. A verb is registered once — registering the same name on both surfaces makes the server throw on construction and every tool on the endpoint fails.

A worked example

Adding a rigged-3D capability, end to end, took five of the six stages in code and one on the provider node:

1  register    → provider node config + capability tables      (205 → 207 live)
2  price       → cost basis $1.20/call, +5% → $1.26 shipped
                 composable add-ons: rigging +$0.21, animation +$0.126
3  discoverable→ output kind, latency prior, 700s timeout,
                 usage contract, input requirement, 6 aliases
4  skill       → public/skills/meshy-v7.md
5  playbook    → sketch-to-rigged-character + a showcase with real media
6  measured    → 4/4 probes: 187s / 199s plain, 395s rigged, 213s multi-view

Two of the most useful facts in that skill are not in any provider document. One option returns walk and run animations free, so a separate paid option was unnecessary. And one endpoint's marketing page advertises a quality tier its API schema rejects — charging for it would have billed users for something that cannot happen. Both came from reading a captured response.

Watch the timeout ceilings. A long render can be cut at 300 seconds by three different layers — our HTTP client, the job timeout the client sends (which defaults to 300 and the orchestrator enforces), and the worker's own limit. The middle one is invisible unless you look: the render completes, the connection has closed, and the job is recorded failed and billed. Verbs and the CLI send the right value for you; a script calling the SDK directly must send it explicitly.

Definition of done

cap_status returns COMPLETE, CI is green, and the capability is deployed. Anything less is NAME_ONLY — shippable, honestly labelled, and not yet in automatic routing.