---
title: money skill
description: How the looot plugin's money skill quotes a run, explains holds and settlement, and reads receipts.
sidebar:
  label: Money
---

`money` loads automatically before a paid run or a batch of runs, when you ask what something
will cost, set a budget, run out of credit, or want receipts.

## What it does

- **Explains the balance.** The workspace has a prepaid USD balance. Runs spend it. Searching,
  [`inspect`](/mcp-tools/inspect), [`catalog_overview`](/mcp-tools/catalog-overview), [`balance`](/mcp-tools/balance) and run history are free. [`discover_smart`](/mcp-tools/discover-smart) is a paid
  search, well under a cent per call, so the skill asks first.
- **Quotes before running.** A search row carries `estimatedPrice`, `priceBasis` and
  `costPerSuccessUsd` (price divided by success rate, the better number for comparing
  providers). `inspect` gives the exact price formula in `endpoint.price` and
  `estimatedMaxCost`, the most one run can hold. For a batch, the skill multiplies
  `costPerSuccessUsd` by the row count, tells the user the total, and checks `balance` first.
- **Explains holds and settlement.** A run holds its estimated cost (shown in `balance` as
  `reserved`), the provider answers, the run settles at the actual charge (`actualCost`), and the
  rest of the hold goes back to `available`. A fallback run takes one hold for the whole route,
  covering up to `fallback.maxAttempts` providers and never more than `fallback.maxCostUsd`; only
  attempts that ran are charged, summed in `route.chargedUsd`.
- **Explains what's free.** Nothing is charged for an input that fails the basic check
  ([`invalid_input`](/errors/job-refusals#invalid_input)), [`needs_input`](/errors/job-refusals#needs_input), [`unknown_job`](/errors/job-refusals#unknown_job), [`no_supply_for_job`](/errors/job-refusals#no_supply_for_job), [`no_runnable_provider`](/errors/job-refusals#no_runnable_provider),
  any [`validation_error`](/errors/rest-errors#validation_error), or a route that called nobody ([`route_capped`](/errors/job-refusals#route_capped), [`route_no_fit`](/errors/job-refusals#route_no_fit)). A "not
  found" answer can still be charged, since some providers bill every call; free providers go
  first in a job run.
- **Explains the cost cap.** `fallback.maxCostUsd` caps the route's hold. A provider priced above
  what's left is skipped as `over_cost_cap`; if every provider is over it, the run fails as
  `route_capped` and charges nothing.
- **Handles being out of credit.** A run with too little balance comes back `status: "blocked"`,
  code [`insufficient_balance`](/errors/rest-errors#insufficient_balance), with a `topUp.checkoutUrl` to show the user. After payment, retry
  with a new [`idempotencyKey`](/concepts/idempotency).
- **Points to receipts.** `actualCost` and `route.summary` on the run, [`runs_evidence`](/mcp-tools/runs-evidence) for every
  attempt's status, latency, receipt id and cost, and [`runs_list`](/mcp-tools/runs-list) for history.

## Worked example

**User:** "Verify these 40 email addresses. What will it cost?"

```json
{"tool": "search", "input": {"filters": {"capability": "people.email.verify"}, "prefer": "cheapest"}}
```

The cheapest row has `costPerSuccessUsd: 0.006`.

**Agent's answer:** "At about $0.006 per address, 40 addresses comes to roughly $0.24. Your
balance is $X." (X is the `available` value `balance` returned.) "Want me to go ahead?"

After the user agrees, each run:

```json
{
  "tool": "run",
  "input": {
    "endpointId": "job:people.email.verify",
    "input": {"email": "jane.doe@example.com"},
    "idempotencyKey": "verify-jane-doe-example-01",
    "fallback": true
  }
}
```

**Agent's closing answer:** "Verified 40 addresses. Total charged: [sum of `actualCost`]. 3 came
back `catch_all`, flagged for you to check by hand."

See [find-and-run](/plugin/skills/find-and-run) for the search-and-run loop and
[troubleshooting](/plugin/skills/troubleshooting) for what each blocked or capped code means.

<Related />
