Email Deliverability

How to Stop an AI Agent From Sending Too Many Emails: Budgets, Rate Ceilings and a Kill Switch

Volume controls for AI agents that send email: how to size a per-key budget and rate ceiling, wire the 80% warning, and stop every key in one request, with the reputation math behind each.

By WarmySender Team November 12, 2026 9 min read

Direct answer. To stop an AI agent from sending too many emails, give it its own AgentiSend key with a budget_per_period and a rate_ceiling_per_minute, subscribe to the limit.warning webhook that fires at 80% of the budget, and keep POST /limits/kill-all ready: one request pauses every key, and no API key, including the agent's, can turn it back on. If you only need a coarse account-wide cap and the agent runs on a provider you already use, check that provider's own limits first; AgentMail, Plunk and MailerSend each have one, though none we read is set per key.

How we put this together

For this comparison we went through the pricing pages of AgentiSend, Resend, Amazon SES, MailerSend, Mailtrap, SMTP2GO, Plunk and AgentMail on 9 November 2026 and checked their documentation between 28 September and 10 November 2026. We did not run agents against these limits; the behaviour described is what each provider documents.

This guide is about volume: an agent that sends more than it should. An agent that sends the same message over and over is a different failure with a different control, covered in our piece on stopping an agent that sends the same email in a loop.

Why volume is a reputation problem before it is a billing problem

Most people meet this problem through the invoice. The more expensive damage is to the domain. An agent that over-sends usually does so to addresses it should not be mailing: an old export, a scraped list a user pasted in, guessed addresses. Those produce bounces and complaints, and mailbox providers count them against your domain whether or not a person was involved.

AgentiSend publishes the lines it enforces, which makes the risk concrete. It warns at 2% bounces and pauses at 4%, over a rolling 7 days. Suppose your app normally sends 3,000 messages a week with 30 bounces (1%). An agent that mails 1,000 stale addresses in an afternoon, a fifth of which bounce, adds 200 bounces: the week becomes 230 bounces on 4,000 sends, 5.75%, over the pause line. Every other sender on the account pauses with it. Volume controls exist to make that afternoon impossible.

The six controls, in the order they act

Control What it limits What the agent sees Who can undo it
Rate ceiling Messages per rolling minute, per key rate_ceiling_exceeded, retryable after the stated wait A person raises it; the key can lower it
Key budget Messages per period, per key agent_budget_exceeded A person raises it, or the period resets
Plan inclusion Messages per month, whole account plan_limit_reached (overage is off by default) The owner turns overage on, with a ceiling
Warning webhook Nothing; it tells you Nothing Not applicable
Single-key pause Everything from one key kill_switch_active A signed-in person
Kill switch Every key on the account kill_switch_active A signed-in person only

Both ceilings count messages, not money, and a recipient counts as one message, so one send to five people uses five. There is no daily cap on paid plans beyond what you set; delivery is paced per inbox provider.

Step 1: size the budget from the job, not from the plan

Every AgentiSend key is created with a budget, and the default is the plan's whole monthly inclusion. On Pro that is 50,000 or 100,000 messages, far more than a support agent needs. Size it from the work:

Agent Expected sends Budget per 30 days Rate ceiling per minute
Support-ticket replies 40 a day 1,500 (1,200 plus 25% headroom) 5
Weekly account digests 2,000 every Monday 9,000 60
Sales-meeting follow-ups to people who booked 15 a day 600 2

Now compare how far each agent gets if it goes wrong, sending as fast as it is allowed:

Agent Default budget (Pro 50,000) With the sized budget and ceiling
Support replies Up to 50,000 sends Stops at 1,500; at 5 a minute that takes 5 hours, with the 80% warning at 1,200
Weekly digests Up to 50,000 sends Stops at 9,000
Meeting follow-ups Up to 50,000 sends Stops at 600, at 2 a minute

The ceiling buys time; the budget sets the worst case. Together they turn "the agent emailed our whole user base" into "the agent sent a few hundred extra messages and someone got a warning."

Step 2: set both ceilings

import { AgentiSend } from 'agentisend';

const owner = new AgentiSend(); // your key, never the agent's

const agentKey = await owner.apiKeys.create({
  name: 'support-replies-agent',
  permission: 'sending_access',
});

await owner.limits.update(agentKey.id, {
  budget_per_period: 1500,
  rate_ceiling_per_minute: 5,
});

Or over REST with PATCH /limits/keys/{id}. Read the current state, including when the period resets, with GET /limits/keys/{id}; an agent connected over MCP calls get_agent_budget.

Two rules keep the agent inside these numbers. A key may lower its own budget or ceiling, which lets an agent cap itself before a big job, but raising either is refused with human_action_required and done by a person in the console. And a key made by another key starts no higher than its parent, so minting a fresh key does not reset a budget you lowered.

Step 3: hear about it at 80%

limit.warning fires once per period when a key reaches 80% of its budget, and again for the account at 80% of the plan inclusion. limit.exceeded fires the first time a send is refused. Both carry api_key_id (null for the plan inclusion), used, budget and period_started_at; the exceeded event adds resets_at.

A handler can do more than log. This one pauses a key the moment it crosses 80% outside working hours, so nobody wakes up to a spent budget:

import { AgentiSend } from 'agentisend';

const owner = new AgentiSend();

export async function onLimitEvent(event: {
  type: string;
  data: { api_key_id: string | null; used: number; budget: number };
}) {
  if (event.type !== 'limit.warning' || !event.data.api_key_id) return;
  const hour = new Date().getUTCHours();
  const outOfHours = hour < 7 || hour >= 19;
  if (outOfHours) {
    await owner.limits.kill(
      event.data.api_key_id,
      `paused at ${event.data.used}/${event.data.budget} outside hours`,
    );
  }
}

Verify the webhook signature on the raw body before trusting the event, using verifyWebhookSignature from agentisend/webhook-signing.

Step 4: keep the kill switch one command away

When something is clearly wrong, you do not want to work out which key it is. One request pauses all of them:

curl -X POST https://api.agentisend.com/limits/kill-all \
  -H "Authorization: Bearer $AGENTISEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason": "digest agent mailing an old export"}'

Every send then returns kill_switch_active. Mail already queued stays queued rather than being dropped, so nothing legitimate is lost. The pause and the reason go into the audit log.

Undoing it is a person's job. Someone signed in to the console presses Resume all, which calls POST /limits/resume-all with their session. The same call from any API key, even the one that triggered the pause, is refused, and AgentiSend's docs show the response (abridged):

{"error": {"code": "human_action_required",
  "message": "This is a person's decision, so an API key cannot make it."}}

A paused key also cannot create a key, rotate one or change a budget; each attempt returns kill_switch_active. It can still pause itself.

Step 5: let the plan be the last wall

AgentiSend's overage is off by default. When the account's monthly inclusion is used, sending pauses with plan_limit_reached until the owner turns overage on, up to a ceiling they choose. For an account with agents on it, leave it off until you have a month of normal numbers.

How other providers handle volume

Provider Volume control documented Set per key?
AgentiSend Budget and per-minute ceiling per key, plan inclusion, single-key pause, kill switch Yes
AgentMail Plan caps: 100 a day on Free; 1,000 a day and 100 every 5 minutes on Developer No
Plunk Monthly caps per project and category; crossing one returns 402 BILLING_LIMIT_EXCEEDED No
MailerSend A sending limit the account sets for itself (MS42204); a token can be paused No
SMTP2GO A rate limit per API key, unlimited by default Rate only, not a count
Mailtrap 150 requests per 10 seconds per token Request cap, not sends
Amazon SES SendingEnabled false disables the whole account No
Resend 10 requests a second per team; daily and monthly quota errors No

AgentiSend

Best for: any account where more than one service or agent sends, because each key gets its own budget and one pause stops them all. The budget controls are described on AgentiSend's agent email budgets page, and plans start free at agentisend.com.

AgentMail

Best for: agents with their own inboxes that need a hard plan-wide ceiling. Watch out for: one agent can use the whole plan's daily allowance.

Plunk

Best for: separating transactional, campaign, workflow and inbound spend. Watch out for: two agents in one project share every cap.

MailerSend

Best for: an account-level spending stop. Watch out for: its errors page says to raise the limit under Plan and billing, and nothing we read stops an agent's key from being the one that holds that access.

SMTP2GO and Mailtrap

Best for: slowing a sender down. Watch out for: a rate limit caps speed, not total volume; a slow agent left running overnight still sends thousands.

Amazon SES

Best for: a single account-wide off switch. Watch out for: it stops every sender at once with no per-credential option, and AWS's page says the call cannot re-enable sending if AWS paused the account.

Questions people ask

What is a sensible email budget for an AI agent? Its expected volume over the period plus about a quarter for headroom. Then set a per-minute ceiling near its real peak, so a runaway reaches the budget slowly enough for the 80% warning to matter.

Can an agent raise its own email limit? Not on AgentiSend. A key can lower its budget or ceiling, but raising one returns human_action_required, and only a person in the console can do it.

What happens to queued emails when the kill switch is on? They stay queued. Nothing is dropped, and they send after a person resumes.

Does a budget protect my sender reputation? It caps the damage. A budget does not judge whether the recipients wanted the mail, but it limits how many bounces and complaints a bad run can add before it stops.

Sources

Pricing pages read 9 November 2026: agentmail.to/pricing, resend.com/pricing. Documentation read 28 September to 10 November 2026: docs.useplunk.com/concepts/billing, developers.mailersend.com/api/v1/account/tokens, developers.mailersend.com/general, developers.smtp2go.com/docs/getting-started, docs.mailtrap.io (rate limits, billing plans), docs.aws.amazon.com/ses/latest/APIReference-V2/API_PutAccountSendingAttributes.html, resend.com/docs/api-reference/rate-limit.

Topics: ai agents email budget kill switch sender reputation