Guardrails for an AI agent that calls paid media APIs
Five guardrails for an agent that spends money: required cap, read before paying, idempotency keys, no secrets in logs, and a cancel path. Drawn from Sume docs.

An AI agent that calls paid media APIs needs five guardrails: a hard spend cap on every run, a read of catalog and usage before any paid action, an idempotency key on every write, no keys or signed URLs in logs, and a cancel path you have tested. Sume's docs ask for each of these.
Agents are attractive precisely because they decide what to call. That is also why the limits must be outside the agent's reach, in the request and in your code.
Think of the five as layers. Any one can fail, and the aim is that a failure in one layer costs cents, not hundreds of dollars.
Rule 1: a cap the agent cannot raise
On Agent Completions, generation_spend_cap_usd is required with no default. On Format runs it is above zero and at most 500, and scheduled runs default to $1.00 with a per-run value that can only lower it. Set the cap in code you control, not in text the agent can edit. See Agent Completions.
A cap also doubles as documentation. When a reviewer sees a cap of 2.00 on a ten second clip, they know what you expected the work to cost, and a cap of 400 on the same call is a question worth asking.
Rule 2: read before you pay
The Safe automation page says to read the catalog, jobs, and usage before paid actions. Practically, check the model or Format exists, check there is not already a job for the same input, and look at remaining budget. A free read can prevent a paid duplicate.
Rules 3 to 5
Send an Idempotency-Key on writes. Derive it from stable ids such as an order and a version, not from a random value, so a retry replays rather than spends again. A same-key, different-body call returns 409 idempotency_conflict, which is useful: it catches a change you did not intend.
Never log API keys or signed URLs. And keep the cancel path alive: each receipt has a cancel_url, cancel is idempotent, and you pay for what was generated before it. Test it with a tiny run before you need it.
Review logs for leaks on a schedule. A search for the strings Bearer and X-Amz-Signature in your log store takes a minute and finds the most common mistakes.
| Guardrail | Where it lives | Failure it prevents |
|---|---|---|
| Spend cap | Request field | Runaway cost |
| Read first | Your code, before the paid call | Paying for a duplicate |
| Idempotency-Key | Request header, up to 255 chars | Double charge on retry |
| No secrets in logs | Your logging config | Leaked key or signed URL |
| Tested cancel | cancel_url | Long unattended runs |
What Sume does not give you
Do not assume a global kill switch or a per-agent budget object; the cap is per request. Scheduled runs are unattended by design, and a run that would need a person ends as unattended_blocked rather than waiting. Hosted MCP paid tools require the right scope or a key and take an idempotency_key, and the docs do not treat hosted MCP as the primary path today.
Put your own daily ceiling in front of everything: a counter of cents spent per day that refuses new runs past a limit. It is twenty lines and it is the guardrail that survives a bug in the others.
Sources
Related posts
More in Agents
- Planlock in front of Sume MCP: approve the plan, then the calls
Planlock is an MCP proxy that enforces a human-approved plan. Where it fits in front of Sume's hosted MCP, and which Sume gates still do work behind it.
- Porting chat-completions code to Sume Agent Completions
Agent Completions takes system and user messages, rejects assistant turns, returns a 202 receipt, and does not stream. Here is what to change when porting.
- Scheduled run cost cap: a per-run cap can only lower it
A scheduled Sume run defaults to a $1.00 cap. A per-run cap can only lower the schedule cap, never raise it. Here is how that differs from a direct Format call.
- Send product photos to the Sume agent API, get edited images back
Agent Completions takes up to 30 image attachments and a required spend cap, then returns generated images in output.images. When to use it over /v1/images.
Written by Sume