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

# Spend Controls: Per-Call and Session Budget Limits

> Agora402 enforces per-call and session spend caps before signing any Hedera payment. Configure maxPerCall and sessionBudget to protect your agent's wallet.

Before signing any Hedera payment, the `BuyerAgent` applies two independent spend controls that protect your account from runaway costs. These controls operate at the x402 client layer, which means they fire before a partially signed transaction is ever created — a payment that fails a limit is never submitted to Blocky402 or Hedera. Both limits are expressed as bigint atomic units (tinybars for HBAR, or the smallest denomination of your HTS token), so no floating-point conversion touches your budget math.

## Per-Call Cap: `maxPerCall`

The per-call cap is a hard upper bound on any single payment. If a seller's `402 Payment Required` response carries an `amount` greater than your `maxPerCall` value, the x402 spend control rejects it immediately — the request is aborted and your balance is untouched.

* **SDK**: pass `maxPerCall` (bigint) to the `BuyerAgent` constructor.
* **CLI**: pass `--max-call <HBAR>` to any command (default `0.05` HBAR).

This protects you from a misbehaving seller quoting an inflated price, or from accidentally targeting a much more expensive endpoint.

## Session Budget: `sessionBudget`

The session budget is the total your agent may spend across all calls during a single process lifetime. Before signing any payment, the agent checks whether `amount ≤ remaining`, where `remaining = sessionBudget − totalSpent`. If the payment would exceed the remaining budget, the agent rejects the `402` and never signs.

* **SDK**: pass `sessionBudget` (bigint) to the `BuyerAgent` constructor.
* **CLI**: pass `--budget <HBAR>` to any command (default `0.5` HBAR).

The session budget resets when you create a new `BuyerAgent` instance. For long-running agents you can create a new instance at the start of each job or conversation turn to get a fresh budget.

## What Happens When a Limit Is Hit

When every payment option in a `402` response exceeds your remaining session budget, the agent emits a `failed` event with the message:

```
every option exceeds remaining session budget <amount> HBAR
```

The request returns a `PaidResult` with `amount: null`, `settlement: null`, and `status` reflecting the seller's original `402` status code. **Your account is not charged.**

<Note>
  Failed seller responses (4xx or 5xx after the payment was sent) are also never charged. Blocky402 only co-signs and submits the Hedera transfer after the seller returns a 2xx. If the seller's handler throws an error, the partially signed transaction is discarded and no funds move.
</Note>

## Setting Budgets in Code

```typescript title="buyer-with-budgets.ts" theme={"system"}
import { BuyerAgent } from '@agora402/buyer';

const agent = new BuyerAgent({
  network: 'testnet',
  accountId: process.env.BUYER_ACCOUNT_ID!,
  privateKey: process.env.BUYER_PRIVATE_KEY!,
  maxPerCall: 5_000_000n,     // 0.05 HBAR — reject any single payment over this
  sessionBudget: 50_000_000n, // 0.5 HBAR — total session limit
});

// Check remaining budget at any time
console.log(`Spent:     ${agent.totalSpent} tinybars`);
console.log(`Remaining: ${agent.remaining} tinybars`);

// Attempt a call — if the quoted price exceeds maxPerCall or the remaining
// session budget, the call returns { amount: null } without charging you.
const result = await agent.infer('Summarize this document', { counterBps: 9500 });

if (result.amount === null) {
  console.warn('Call was not paid — budget limit hit or seller error.');
} else {
  console.log(`Paid ${result.amount} tinybars. Remaining: ${agent.remaining} tinybars`);
}
```

## Asset Filtering

By default, `BuyerAgent` only accepts payment requests denominated in HBAR (asset id `0.0.0`). Any `402` response that asks for a different asset is silently filtered out before spend controls even run.

To use the TOLL settlement token instead, pass its HTS token id when constructing the agent:

```typescript title="toll-asset.ts" theme={"system"}
const agent = new BuyerAgent({
  // ...
  asset: process.env.TOLL_TOKEN_ID!, // e.g. '0.0.4567892'
  maxPerCall: 500n,    // atomic units of the TOLL token
  sessionBudget: 5000n,
});
```

<Warning>
  Setting `asset` to a token id changes what both limits are measured in. Make sure `maxPerCall` and `sessionBudget` reflect the token's decimal precision, not HBAR tinybars.
</Warning>

<Tip>
  Pass `--json` to any CLI command and pipe the output to `jq '.amount'` to extract the exact amount paid in atomic units for each call. This makes it easy to build programmatic budget dashboards or alerting on top of the CLI.
</Tip>
