> ## Documentation Index
> Fetch the complete documentation index at: https://piloop.autoresearch.inc/llms.txt
> Use this file to discover all available pages before exploring further.

# Cost and spend limits

> What the agents use in tokens, and a hard limit on what the campaign spends outside piloop.

A campaign costs money in two ways: the tokens that the agents use, and what the project pays outside piloop, such as
GPU time or paid APIs. piloop measures the first and enforces a limit on both.

## Tokens

When an agent ends, piloop reads the tokens that it used from the harness's own session file. This works for Claude
Code, Codex and pi, and does not need Entire. piloop writes the totals to `workers.usage`:

```json theme={null}
{"input": 120345, "output": 18230, "cache_read": 950112, "cache_write": 40211, "total": 1128898, "turns": 41, "source": "…"}
```

* `piloop status` and `piloop watch` show the tokens of each project.
* The kept lineage shows the tokens that each candidate cost.
* `[stop] max_tokens` ends the campaign when the agents of the project have used that many tokens in total.

```toml theme={null}
[stop]
max_tokens = 50_000_000
```

The token counts of different harnesses are not directly comparable. For Codex, `input` includes `cache_read`.

## Stop conditions

The `[stop]` table ends the campaign when one of its conditions holds:

| Key | The campaign ends when |
| - | - |
| `target` | the primary metric of the head reaches this value. |
| `max_runs` | this many worker runs are queued, running, or have a candidate that is measured or waits for its measurement. |
| `max_hours` | this many hours have passed since the first run started. |
| `max_tokens` | the agents of the project have used this many tokens. |
| `plateau` | this many finished runs in a row produced no new keep. |

`max_runs` skips a run that ended without a scored candidate: a run with no commit, or with only `Piloop-Eval: skip`
commits. Such a run still costs tokens, and `max_tokens` bounds that. `plateau` counts it: it made no progress. Both
skip a run that a daemon stop or a campaign stop ended.

When a condition holds, the project becomes `stopped`. The daemon tells the running workers to commit and stop, and
ends them 10 minutes later. It scores what they committed. It drops the queued runs and the requested agents, and
asks for one last watchdog review that writes the closing report. The triggers request nothing more, but an agent that
you request with `piloop launch` still starts. Without a `[stop]` table, the campaign has no end. `piloop stop` stops
the daemon, not the campaign.

To resume a stopped project, change its `[stop]` table and run `piloop init`.

## Spend outside piloop

`[spend]` is a hard limit in US dollars on what the campaign costs outside piloop. piloop knows no vendor, so you give
it a command that prints the spend so far:

```toml theme={null}
[spend]
command = ["uv", "run", "scripts/spend.py"]   # prints one number: the spend so far in USD
limit = 1000                                  # nothing new starts at this spend
notices = [300, 600]                          # each one posts a note to the inbox when crossed
interval = 300                                # seconds between two runs of the command
```

The daemon runs the command every `interval` seconds, at the root of the repo, with its own environment. The command
must print one number and exit 0 within a minute. Give it its keys through the daemon's environment; see
[Secrets](/guides/secrets).

* When the spend crosses a value in `notices`, the daemon posts one note at priority 1.
* When the spend reaches `limit`, the daemon starts no agent and no evaluation for the project, and posts one
  escalation at priority 0. Agents and evaluations that already run finish, and their commits are scored.
* When the command fails, the daemon holds the project in the same way, with one escalation for each series of
  failures. An unknown spend is never read as zero.

This is a hold, not a stop: nothing is dropped. To resume, raise `limit` in `piloop.toml` and run `piloop init`.

`piloop status` shows the spend as `$412.30/$1,000.00 spend`. Tokens are not part of the spend, because piloop has no
price table. Use `[stop] max_tokens` for them.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.