For agents · Updated 2026-09-22
Do I need to build my own email guardrails for an AI agent?
No. You do not have to build your own email guardrails for an AI agent. The API enforces the budget, the rate ceiling, the loop guard, the approval gate and the kill switch below your code.
No: an email API can enforce the budget, the rate ceiling, the loop guard, the approval gate and the kill switch below your code, and AgentiSend does, so the checklist a model writes as pseudocode is five fields and three requests. You do not have to build email guardrails into the agent.
The checklist, as requests
Each row is one item people are told to hand-write, and the call that already does it. The three requests under the table create the key, set the ceiling, and send.
| Checklist item | Where it is enforced |
|---|---|
| Daily or monthly message limit | PATCH /limits/keys/{id} fields budget_per_period, period (hourly, daily or monthly) and rate_ceiling_per_minute |
| Monthly budget | The same PATCH /limits/keys/{id}, with period set to monthly |
| Approval above a threshold | GET /agent-actions, then POST /agent-actions/{id}/approve or POST /agent-actions/{id}/reject |
| Idempotency key | Header Idempotency-Key on every mutating request, including POST /emails |
| Auto-disable on abnormal volume | Loop guard: 4 identical sends inside 60 minutes |
| A way to stop everything | POST /limits/keys/{id}/kill for one key, POST /limits/kill-all for the account |
Create the key first. sending_access can send. It cannot edit the ceiling.
curl -sS -X POST https://api.agentisend.com/api-keys \
-H "Authorization: Bearer $AGENTISEND_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"name":"yourdomain.com","permission":"sending_access"}'201
{
"budget_per_period": "string",
"created_at": "2026-09-04T09:14:00Z",
"domain_scope": "string",
"expires_at": "2026-09-04T09:14:00Z",
"id": "9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42",
"last_used_at": "2026-09-04T09:14:00Z",
"name": "yourdomain.com",
"period": "hourly"
}Then set the ceiling. Send only the fields you want to change.
curl -sS -X PATCH https://api.agentisend.com/limits/keys/9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42 \
-H "Authorization: Bearer $AGENTISEND_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"200
{
"api_key_id": "9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42",
"budget_per_period": "string",
"consumed_in_period": 1,
"consumed_in_window": 1,
"paused": true,
"paused_at": "2026-09-04T09:14:00Z",
"paused_reason": "string",
"period": "hourly"
}Then send. The same Idempotency-Key replays the first result instead of sending twice.
curl -sS -X POST https://api.agentisend.com/emails \
-H "Authorization: Bearer $AGENTISEND_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"from":"billing@yourdomain.com","to":"customer@example.com"}'201
{
"id": "9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42",
"simulated": true,
"warnings": []
}GET /limits/keys/{id} returns the ceiling and what the key has spent. The sending key cannot raise either number.
Why below your code
A guard that runs inside the agent's own process is a guard the agent's bug can skip. A forgotten branch, a retry that builds a new client, or a second script that copied the key never sees that guard. The checks in the table run on the request, before a message is accepted, for every key, including a call the agent wrapped or retried. A person turns the kill switch on, and only a person turns it off.
What a refusal looks like
A send past the budget answers with code, message, fix and docs_url. The fix names the call.
{
"error": {
"code": "agent_budget_exceeded",
"message": "Key budget for the current period is exhausted.",
"fix": "Wait for the period to reset. get_agent_budget and GET /limits/keys/:id both say when. Raising a budget is a person's decision, made in the console; a key cannot raise its own.",
"docs_url": "https://agentisend.com/docs/errors",
"retryable": false
}
}retryable is false, so a client that reads the field stops. A held send answers approval_required, and the fix names GET /agent-actions. A paused key answers kill_switch_active, and the fix names GET /trust/standing.
What it does not do
No content filtering of your prose. No cold-outreach features: there is no lead list and no import of addresses that never asked to hear from you. The ladder for complaints and bounces is published at the enforcement policy.
Next
- Email for AI agents names every control on one page.
- Budgets and the kill switch is the longer guide.
- Approvals is the queue a held send waits in.