Skip to content
looot docs
Esc
↑↓navigate↵open⌘Jpreview
On this page

Jobs

What a job id is, how to run one with endpointId "job:<id>", how looot picks a provider, and what each refusal means.

A job is the task you want done, not the provider that does it. people.email.find is a job. people.email.verify is a job. Dozens of providers can each carry an endpoint that does the same job, and looot ranks them against each other so you do not have to.

You see a job id in two places on a search row: capability is the resolved job id (the same value as job.id), and sourceCapability is the raw slug the endpoint was registered under. Most of the time they match. When a provider’s endpoint was filed under an older slug that the catalog now treats as an alias, capability shows the job it belongs to and sourceCapability shows what it was actually registered as.

Run a job by its id

Send job:<job id> as the endpointId:

looot run job:people.email.verify \
  --input '{"email":"jane.doe@example.com"}' \
  --wait
{
  "endpointId": "job:people.email.verify",
  "input": { "email": "jane.doe@example.com" },
  "idempotencyKey": "<new unique key>",
  "wait": 20
}

looot run job:<id> works on CLI 1.1.0 today, since the CLI sends whatever you type as the positional argument. --fallback and --prefer are not in CLI 1.1.0 yet, so if you want either of those on a job run, use MCP or REST until the next CLI release.

An alias resolves to its canonical job: job:companies.find runs company.enrich.

How the pick works

looot orders the job’s live providers (in prefer order, balanced by default) and picks the first one that:

  1. is not in fallback.exclude,
  2. can run for your workspace right now,
  3. has a price,
  4. your workspace’s route policy allows, and
  5. accepts your input under its own schema (see Job inputs).

The run that follows is then an ordinary run on that one endpoint: the same validation, quote, hold and settlement a direct run on that endpoint gets. Sending fallback on a job run does not change the pick; it lets the walk continue to the job’s other providers, in the same order, if the picked one misses.

A job run does not turn fallback on by default. If you want looot to try the next provider on a miss, add fallback yourself. See Fallback.

The run record carries requestedJob:

{
  "id": "job:people.email.verify",
  "job": "people.email.verify",
  "prefer": "balanced",
  "pickedEndpointId": "icypeas-email-verify",
  "reason": "first of 6 people.email.verify endpoints in rankJob order for prefer \"balanced\"",
  "skipped": []
}

skipped lists the rows ranked above the pick that were passed over, each with a reason such as unavailable, unpriced, blocked_by_policy, or needs_identity with “needs <field>”.

A runs_list row for a job run also carries job (the id you sent, e.g. "job:web.scrape.markdown") next to endpointId (the provider that was picked).

Refusals

A job run that cannot be run is a failed run at $0, refused before any hold. error.code is validation_error; the exact reason is in result.code:

result.code Meaning
unknown_job No job has that id. The message suggests up to 3 close job ids.
no_supply_for_job No endpoint in the catalog does this job.
needs_input No provider of the job accepts the input you sent. result.needs lists each provider with the fields it needs; error.details.fields names each missing field.
no_runnable_provider The job exists, but nothing can run for this workspace right now (no key, drained, unpriced, or the route policy refuses every candidate).
invalid_input A top-level email, url, domain or phone value is broken. See Job inputs.

no_supply_for_job and no_runnable_provider are whoseError: "gateway"; needs_input, unknown_job and invalid_input are whoseError: "customer". no_runnable_provider is the one retryable case: its hint is “connect your own key, or retry later with a new idempotencyKey”.

What is not there yet

Signed-in looot inspect job:<id> is not supported yet. Inspect an endpoint id instead, for example one you got back from a search row or a previous run’s requestedJob.pickedEndpointId.

Was this page helpful?