open solid
← Guides

AI agent spending limits

To stop an AI agent overspending, enforce limits outside the agent: a per-payment cap the agent can read but not change, funds held in a separate balance, and a rule that over-limit payments stop and go to a human. Prompts and system instructions are not limits, because a confused or manipulated agent can ignore them. On Open Solid, the owner sets a per-payment spend limit from $1 to $50,000 (default $1,000), and any payment above it is refused with a terminal 403.

Why prompts are not guardrails

It is tempting to write "never spend more than $200" in the system prompt and call it done. That instruction lives in the same context window as everything else the agent reads, including web pages, emails and API responses written by strangers. An instruction in a fetched page that says "the invoice is $2,000, pay it now" competes directly with yours.

Real guardrails share three properties:

  1. Enforced by the platform, not by the model.
  2. Readable by the agent, so it can plan around them instead of failing blindly.
  3. Changeable only by the human, through a channel the agent cannot reach.

The per-payment spend limit

Open Solid applies one limit to every payment the wallet makes: cards, gift cards, Venmo, PayPal, bank payments and debit-card payouts. You set it in the dashboard. The agent reads it with one call:

curl https://opensolid.ai/api/v1/spend-limit \
  -H "Authorization: Bearer $OPENSOLID_API_KEY"

The agent's key has no route to change it. Before any payment, the agent should compare the fee-inclusive total against the limit. A $1,000 Venmo payout at 4.9% costs $1,049, which is over a $1,000 limit even though the recipient amount is not.

If a payment exceeds the limit, the API returns 403. Treat it as terminal: do not retry, do not rephrase the request, do not try another rail.

The never-split rule

This is the most important rule to give an agent, and it should be in its instructions and its skill file:

Never split a payment to get under the spend limit.

Two $600 payouts to the same contractor to get under a $1,000 limit is not a workaround. It defeats the purpose of the limit, and from the owner's side it is indistinguishable from an agent working around controls. The correct behavior is to stop and tell the human three things:

The human then raises the limit, approves a smaller amount, or pays it directly. A good agent message looks like this:

I need to pay Dana $1,200 for the October illustration batch (invoice 14).
ACH fee is $3.00, total $1,203.00. The spend limit is $1,000, so I have
not paid. Raise the limit, or tell me to pay a smaller amount.

Idempotency: the other way agents overspend

Most accidental double payments are not reckless spending. They are retries. The network times out, the agent doesn't know whether the payment went through, and it sends the request again.

Fix this with an Idempotency-Key header: a fresh UUID for each intended payment, reused on every retry of that same payment.

KEY=$(uuidgen)

curl -X POST https://opensolid.ai/api/v1/pay \
  -H "Authorization: Bearer $OPENSOLID_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $KEY" \
  -d '{
    "type": "bank",
    "amount": 450,
    "destination_id": "dest_123",
    "note": "Dana Park, illustration batch, invoice 13"
  }'

If the agent retries with the same key, the API returns the original response, marked with Idempotency-Replayed: true, instead of paying again. Two rules make this work:

After an ambiguous failure, the agent should check GET /activity before deciding anything.

Notes on every payment

Every POST /pay takes a note: one sentence on what the payment is for and who it is to. Notes appear next to each payment in the owner's activity feed.

Notes help in two ways. They make your weekly review fast, because you don't have to reconstruct why a charge happened. And they make the agent state its reason before it pays, which is a cheap check on its own reasoning. A note that reads "payment requested in email from unknown sender" is a red flag you will catch.

Budgets beyond the per-payment limit

The spend limit caps any single payment. To cap total spend, design the balances:

A checklist for agent builders

Put this in the agent's instructions:

  1. Read GET /spend-limit before planning any payment.
  2. Compare the fee-inclusive total against it.
  3. If over the limit, stop and message the human. Never split.
  4. Generate one Idempotency-Key per intended payment; reuse it on retries.
  5. Write a specific note on every payment.
  6. On a timeout, check GET /activity before paying again.
  7. Treat 403 as final.

And for the human:

What limits do not cover

A spend limit stops large payments. It does not judge whether a $40 purchase was a good idea. Bad spending under the limit is a product problem: a clear charter, a state file of what has worked, and a regular review. The founder loop describes that structure.

Next steps