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

# Budgets & the Upto Scheme

> Cap what an agent can spend per call, per tool, and per session using upto ceilings and smart account contracts.

When a human clicks "pay," they set the ceiling implicitly. When an agent pays, the ceiling has to be explicit. This page covers three layers of that ceiling.

## Layer 1: per-call ceiling with `upto`

When a seller uses the [`upto` scheme](/payment-schemes/upto), the client signs an authorization for a **ceiling** and the seller settles for less. The client SDK exposes this as `maxAmount`:

```typescript theme={null}
await fetchWithPayment(url, {
  wallet,
  facilitator,
  maxAmount: "0.05", // will refuse to sign a ceiling above this
});
```

If the seller's declared ceiling is higher than `maxAmount`, the SDK throws before signing. Nothing is authorized.

## Layer 2: per-tool budget

For an agent calling many tools, per-call ceilings are not enough. You want "this scraping tool can never exceed \$2/day." Wire this in the agent runtime, not the SDK:

```typescript theme={null}
const budget = new PerToolBudget({
  "weather.forecast": { dailyLimit: "0.50" },
  "llm.summarize":   { dailyLimit: "2.00" },
});

async function payFor(url, tool) {
  await budget.assert(tool);
  const res = await fetchWithPayment(url, { wallet, facilitator });
  await budget.record(tool, res.headers.get("x-payment-amount"));
  return res;
}
```

## Layer 3: session cap enforced on-chain

For higher assurance (the agent runtime cannot be trusted to keep its own books), enforce spending on-chain with a Stellar smart account contract. The wallet delegates signing to a contract that:

* Rejects transfers above a per-tx cap.
* Rejects transfers that would exceed a rolling window budget.
* Optionally restricts destination to an allowlist of `payTo` addresses.

```typescript theme={null}
const smartAccount = await deployBudgetedAccount({
  owner: eoa,
  perTxCap: "0.10",
  dailyCap: "5.00",
  allowedPayTo: ["GCKF...", "GABC..."],
});

const wallet = StellarWallet.fromSmartAccount(smartAccount);
```

An attempt above cap fails at signing time; no funds move.

## Composing the layers

Use all three. Per-call ceiling stops the seller from over-charging. Per-tool budget stops the agent from over-spending on a single capability. Session cap stops the entire agent from spending more than you meant to, even if the earlier layers are compromised.

## Related

* [Upto Scheme](/payment-schemes/upto)
* [MCP Integration for Agents](/guides/buyers/mcp-integration)
