# Budgets

Canonical: https://auggy.dev/docs/augment-budgets
Status: Preview
Package: auggy 0.5.0

Gate turns and record per-peer runtime usage with SQLite-backed caps.

## Outcome

**What it enables:** Admit or reject turns by trust level and track turn counts, priced spend, and anonymous request rates.

- **Status:** Preview
- **Availability:** Install with ``auggy augment add` budgets`; the generated database is `./data/budgets.db`.
- **Contributes:** `turn gate`, `context`, `admin`

Budgets runs before the model call, reserves an allowed turn in SQLite, then commits the provider cost after the response. Creator and internal turns bypass the store.

## Install and configure

1. Run ``auggy augment add` budgets` in the agent project and confirm the Preview prompt.
2. Review `augments/budgets/augment.yaml`; the database path is relative to the agent project.
3. Run ``auggy doctor``, then restart the agent after changing caps.

**augments/budgets/augment.yaml**

```yaml
type: budgets
config:
  dbPath: ./data/budgets.db
  caps:
    public:
      recognized:
        maxTurnsPerThread: 20
        maxTurnsPerDay: 50
        maxUsdPerDay: 1
      anonymous:
        maxTurnsPerThread: 5
  anonymousGlobalLimit: 30
  dailyBudgetUsd: 5
```

`caps.agent`, `caps.public.anonymous`, and `caps.public.recognized` accept `maxTurnsPerThread`, `maxTurnsPerDay`, and `maxUsdPerDay`. The creator tier is intentionally omitted because it bypasses budgets.

## Use it

Use a recognized-visitor cap for a support chat that should allow enough context to solve one issue but stop runaway conversations and spend.

**A bounded support-chat policy**

```yaml
type: budgets
config:
  dbPath: ./data/budgets.db
  caps:
    public:
      recognized:
        maxTurnsPerThread: 8
        maxTurnsPerDay: 24
        maxUsdPerDay: 0.50
  dailyBudgetUsd: 10
```

After restart, a recognized peer receives a budget preamble showing remaining turns and estimated spend. Once a cap is exceeded, the next turn is rejected before the engine call.

## Runtime surfaces

| Surface | Exact behavior |
| --- | --- |
| Turn gate | `prepare` evaluates thread, daily, anonymous-window, peer-dollar, and global-dollar caps; denial is `cap-denied` and makes no engine call. |
| Context | Capped peers receive a high-priority, turn-scoped BATS preamble with remaining turns, estimated spend, and bucketed guidance. |
| Cost commit | After a response, priced USD is written to ``peer_daily_costs`` and ``daily_global``; unpriced turns are counted separately. |
| Admin | Runtime admin info shows today's spend and peer breakdown; the daily cap can be adjusted or reset, with overrides persisted in `admin-overrides.json`. |
| SQLite | ``turn_reservations``, ``peer_daily_costs``, ``daily_global``, and ``anonymous_requests`` are created at `dbPath`. |

## Boundaries

| Area | Current boundary |
| --- | --- |
| Trust | Creator and null/internal turns bypass caps and do not write reservations. Agent and public peers are capped only when their trust-tier config exists; public splits into anonymous and recognized. |
| Persistence | SQLite is single-process and single-replica. No automatic purge runs unless `retentionDays` is set; pending reservations are swept after the cleanup window. |
| Deployment | Keep the database on durable storage and run one replica. Use provider-side quotas or hard spend caps for unattended deployment. |
| Limitations | Dollar caps are post-hoc soft caps and can overshoot by one turn. Unpriced provider responses do not add USD, though turn caps still apply. This is runtime guardrail accounting, not billing control. |

> **Warning: Plan for overshoot**
>
> A USD cap is checked against settled spend before admission and cost is known only after the model response. Keep provider-side hard limits in place when the dollar ceiling must be authoritative.

## Verify

1. Run ``auggy doctor`` and confirm `dbPath` and cap values parse.
2. Start the agent with a recognized peer and complete one turn; confirm the model context contains the BATS remaining-turn lines.
3. Set `maxTurnsPerThread: 2`, complete two turns in one thread, then send a third; confirm `status: rejected`, `errorClass: cap-denied`, and no model call for the third turn.
4. Inspect the SQLite file and confirm a reservation row plus the priced or unpriced cost record; do not expect creator turns to create rows.

## Related

- [Visitor Auth](https://auggy.dev/docs/augment-visitor-auth/markdown)
- [Turn Control](https://auggy.dev/docs/augment-turn-control/markdown)
- [Console](https://auggy.dev/docs/console/markdown)
- [Deploy and verify](https://auggy.dev/docs/deploy/markdown)
- [Security](https://auggy.dev/docs/security/markdown)