← Back to blog

Cap AI Agent API Costs: Spend Policies & Usage Monitoring

August 25, 2026 · Eric · 6 min read

Your AI agent now has an API key and a very long to-do list. The more autonomous it gets — scheduled jobs, background workers, and human-in-the-loop purchases — the more important explicit limits become. A runaway loop can consume tool allowances or credits much faster than intended.

Agent Media Tools gives every agent key a real spend policy: daily caps in dollars and credits, per-purchase limits, item allowlists, approval thresholds, and a hard kill switch. All of it is readable by the agent itself over REST, and all of it is verifiable in the Toolbox or with two curl commands. This post shows you exactly how to monitor usage, set guardrails, and rotate keys when things go sideways.

Why agent spend control is different from human spend control

Humans stop and think before clicking "buy". Agents don't. An agent reads an instruction, calls a tool, and moves on. If the tool is a paid one, the charge is instant. That's why the key you give a worker bot should never be an unlimited key, and why the platform lets you set limits at the key level instead of only at the account level. You can have one key for your interactive session (loose limits) and another for the overnight batch worker (tight limits, approval required over a few cents).

Step 1 — Get your key and check what it can spend

Create an agent key in the Toolbox (/app → Agent Keys), or with POST /api/agent/keys from a logged-in session. Keys look like mt_... and are sent as a Bearer token:

export AMT_KEY="mt_xxxxxxxxxxxxxxxx"

curl -s https://agentmediatools.com/api/agent/usage \
  -H "Authorization: Bearer $AMT_KEY" | python3 -m json.tool

GET /api/agent/usage is the first thing your agent should call on startup. It returns your plan, how many calls you've used today, the daily limit, what's remaining, a percentage, your credit summary, and even a suggested action (for example consider_upgrade when you're almost out of free calls). Counts reset at midnight UTC, so a scheduled job can check it before every run and back off instead of erroring out.

The same shape in Python:

import os
import requests

KEY = os.environ["AMT_KEY"]
r = requests.get(
    "https://agentmediatools.com/api/agent/usage",
    headers={"Authorization": f"Bearer {KEY}"},
)
print(r.json()["used_today"], "/", r.json()["daily_limit"], "calls used today")

Step 2 — Read your spend policy (the agent can do this itself)

Every key has a stored policy. GET /api/agent/policy returns the policy plus today's actual spend in both cents and credits:

curl -s https://agentmediatools.com/api/agent/policy \
  -H "Authorization: Bearer $AMT_KEY" | python3 -m json.tool

You'll get something like this (fields abbreviated):

{
  "success": true,
  "policy": {
    "purchase_consent": true,
    "max_purchase_cents": 5000,
    "allowed_items": [],
    "daily_spend_cents": 0,
    "daily_credit_spend_limit": 0,
    "require_approval_over_cents": 0,
    "kill_switch": false,
    "notify_channels": { "email": null, "discord_webhook": null, "telegram_bot_token": null, "telegram_chat_id": null }
  },
  "today": {
    "spent_cents": 0,
    "credits_spent": 0,
    "remaining_spend_cents": null,
    "remaining_credits_budget": null
  }
}

Every field means something concrete when a purchase is attempted:

FieldWhat it does
purchase_consentMaster switch. Off means the key can never buy anything (403 NO_CONSENT).
max_purchase_centsCeiling for a single purchase in US cents (default 5000 = $50).
allowed_itemsAllowlist of purchasable item IDs. Empty means any item within other limits.
daily_spend_centsTotal money cap per UTC day. 0 = no cap.
daily_credit_spend_limitCap on paid credits per day. 0 = no cap.
require_approval_over_centsPurchases above this amount pause and ask a human. 0 = never ask.
kill_switchHard stop on all purchases until a human turns it off.

Step 3 — Set the guardrails

Policies are written by the human who owns the key (session-authenticated, not agent-authenticated — deliberately). From a logged-in browser session, POST /api/agent/keys/:id/spend-policy accepts any subset of the fields:

# Lock the overnight worker to $1/day, 20 credits/day, and ask before anything over $0.50
curl -s -X POST https://agentmediatools.com/api/agent/keys/KEY_ID/spend-policy \
  -b cookies.txt -H "Content-Type: application/json" \
  -d '{"daily_spend_cents": 100,
       "daily_credit_spend_limit": 20,
       "require_approval_over_cents": 50}' | python3 -m json.tool

You can also restrict which items the key may buy at all:

curl -s -X POST https://agentmediatools.com/api/agent/keys/KEY_ID/spend-policy \
  -b cookies.txt -H "Content-Type: application/json" \
  -d '{"allowed_items": ["credits-100"]}' | python3 -m json.tool

Every policy change is recorded as a signed policy receipt on the key (kind policy, action policy.update), so there's an audit trail of who tightened what, and when. You can review receipts with GET /api/agent/receipts.

If you'd rather click than curl, all of this lives in the Toolbox UI under your agent key settings — same fields, same result.

Step 4 — Send approvals where you'll actually see them

When require_approval_over_cents trips, the platform creates an approval request and fans it out to the notify channels configured on the key. Set them with POST /api/agent/keys/:id/notify-channels (Discord webhook, Telegram bot + chat, or plain email):

curl -s -X POST https://agentmediatools.com/api/agent/keys/KEY_ID/notify-channels \
  -b cookies.txt -H "Content-Type: application/json" \
  -d '{"discord_webhook": "https://discord.com/api/webhooks/123/abc",
       "telegram_bot_token": "123456:ABC-DEF",
       "telegram_chat_id": "@ops-alerts"}' | python3 -m json.tool

Now a $4 purchase attempt from a worker bot lands as an approve/deny link in your ops channel instead of silently hitting your card. The full approval flow is covered in Human-in-the-Loop Approvals for AI Agents.

Step 5 — The kill switch, rotation, and revocation

When a key is compromised — or an experiment goes feral — you have three speeds of response:

  1. Kill switch: {"kill_switch": true} on the spend-policy endpoint. Instantly blocks all purchases while still letting the key use free tools. Good for "pause spending now, investigate later".
  2. Rotate: POST /api/agent/keys/:id/rotate revokes the old key and returns a fresh mt_... with the same name and plan. Use this when a key leaked in logs or a chat transcript.
  3. Revoke or delete: POST /api/agent/keys/:id/revoke deactivates the key; DELETE /api/agent/keys/:id removes it after the server safely reconciles linked records. Prefer revocation when retaining history matters.
# Rotate immediately after a suspected leak
curl -s -X POST https://agentmediatools.com/api/agent/keys/KEY_ID/rotate \
  -b cookies.txt | python3 -m json.tool

Bonus — heartbeat so your ops dashboard sees the agent

Part of cost control is knowing a worker is still alive versus silently stuck in a paid retry loop. POST /api/agent/heartbeat lets the agent report its status to the presence dashboard:

curl -s -X POST https://agentmediatools.com/api/agent/heartbeat \
  -H "Authorization: Bearer $AMT_KEY" -H "Content-Type: application/json" \
  -d '{"status": "working",
       "session_type": "worker",
       "activity_hint": "processing 40 invoices",
       "note": "nightly batch, policy-capped"}' | python3 -m json.tool

Statuses are online, working, queued, idle, offline, and stuck; session types are always_on, live_session, and worker. A stuck overnight job with a spend cap is a notification, not an invoice.

Doing this from MCP

If your agent talks MCP instead of raw HTTP, the same controls are exposed as tools on the hosted MCP server: get_spend_policy returns the policy and today's spend, agent_heartbeat updates presence, and request_approval/get_approval drive the human-in-the-loop flow. Setup is covered in Connect Claude to Agent Media Tools in 5 Minutes.

Wrap-up

A budget is not a limit until something enforces it. Agent Media Tools enforces spend policies at the key level, the agent can read its own limits before acting, and you can flip a kill switch from your phone the moment a number looks wrong. Five minutes of setup — a daily dollar cap, an approval threshold, a Discord webhook — is the difference between "the agent did something expensive" and "the agent asked first".

Create a key, read /api/agent/policy once, and tighten the caps before your next scheduled job starts.

Try it in the Toolbox

Create an agent key, set its spend policy, and run the same tools in the browser — or call them from your agent with an API key.

Open toolbox