Skip to content

Limits: how much agents may send, and no double sends

Last updated November 3, 2026

On this page

Agents that write to people outside the company (emails, WhatsApp and SMS messages, calls) do it many times a day, often without anyone pressing Send. Two things keep that safe:

  • Limits say how many messages and calls each agent may send a day, and how many marketing messages one address may get a week.
  • No double sends: a retry, a restart, a second click on Approve or a run that is carried on again never sends the same message twice.

Limits are a company setting. Your company decides them and is responsible for them; the suggested numbers are a starting point.

This guide describes limits as they work today on the master branch.

Where the limits are#

Admins open Limits in the sidebar (/settings/limits).

Part What it sets
Each agent, per day How many emails, WhatsApp messages, SMS messages, calls, AI calls, record writes and tasks one agent may do in a day. An empty box is no limit.
Each address, per week How many marketing messages one email address or phone number may get in a week, across every channel. 0 is no limit.
Exceptions Limits for one agent (they replace the ones above), for a team (its agents together) or for the whole company (every agent together).
Sent today What each agent has sent so far today.

The suggested limits, which a company starts with:

Each agent, per day
Emails 50
WhatsApp messages 25
SMS messages 25
Calls 40
AI calls 40
Record writes, tasks no limit

and 3 marketing messages per address per week. Use the suggested limits puts the agent limits back to these.

Days start at midnight in the company's time zone and weeks on Monday; the page names the zone it counts in. A company in India counts its day from midnight in Kolkata, not in London.

How a limit stops a send#

A limit is checked before anyone is asked to approve a message, and again just before an approved message leaves. When an agent has reached a limit, the send is refused with a sentence saying which:

  • "Sales Assistant reached today's limit of 25 WhatsApp messages"
  • "Sales reached today's limit of 60 emails" (a team's exception)
  • "The company reached today's limit of 200 calls"
  • "ravi@acme.example already got 3 marketing messages this week"

In a loop run the agent reads the refusal and can do something else; a single-mode run stops with the sentence.

What counts:

  • Each recipient. A message to ten people counts ten against each daily limit, and is refused when it would take the count past one.
  • Only messages that left, or may have. As an approved message leaves, its count is checked and added in one step, so messages sent at the same moment never all pass a limit one of them reaches. The count is given back when the message is refused or fails, and kept when it went or may have gone ("Did this send?" below). Nothing is counted while a message is asked for, waiting for approval or rejected.
  • People are never stopped. A person's own message through OrchKernel is never refused by a limit. It does count toward the address's week, so an agent backs off a contact that people already reached.
  • The inbox assistant's replies keep their own daily limits (see Your inbox assistant) and are not counted here.
  • Counts survive a restart. They are kept in the database, not in memory, and so is a connector's hourly limit (see Connectors).
  • Counts hold numbers only: never a message, and never an address (an address is counted by its hash, keyed with a secret of your install). A number written in different ways ("+91 98200 12345", "09820012345") is one address, and so is an email written as "Ravi ravi@acme.example".
  • Zero and empty. In the daily boxes, 0 stops agents sending that kind at all and an empty box is no limit; in the weekly box, 0 is no limit. In an agent's exception an empty box keeps the limit above, and No limit lifts it for that agent.
  • When the counts cannot be read, the message is refused: "The send counts could not be read, so nothing was sent; try again".

No double sends#

Every message an agent sends carries a key made from the run, the step and what it sends. Before a message leaves, OrchKernel claims its key; a second attempt with the same key gets the first result back and sends nothing. This covers:

  • the same approval approved twice, or by two people at the same moment;
  • a run carried on after a restart, which repeats the step it was on;
  • the same message asked for again by a replayed run.

A connector tool that sends gets the key as the X-OK-Idempotency-Key header, and an integration that supports it passes it to the vendor, so the vendor can drop a duplicate too.

"Did this send?"#

Sometimes nobody knows whether a message went: the connection dropped or timed out while it was sending, the server exited or never answered, the answer was cut off, or OrchKernel stopped in the middle. Such a message is never sent again on its own. The person it was sent for (or the agent's manager when it acted for nobody) gets an inbox card Did this send? with two buttons:

  • Mark as sent: it went. It will never be sent again.
  • Send again: it did not go. It is sent once more, with the same key.

Check with the person, or in the tool it went through, before you choose. Only that person or an admin can answer; the answer is recorded as an event.

A tool whose vendor drops duplicates by key may be marked as safe to retry (idempotent): its message is tried once more, with the same key, without asking.

The record of sends keeps the key, the tool, the run, who owns it, what happened and when, for 30 days. It never keeps the message.

For developers#

Route What
GET /api/settings/limits The limits, the suggested ones, the agents and teams an exception may name, and each agent's sends today (admins)
PUT /api/settings/limits Save the limits: { "per_agent_day": { "email": 50, ... }, "per_recipient_week_marketing": 3, "overrides": { "<agent or team id>" or "company": { "whatsapp": 10 } } }
POST /api/sends/:key/resolve Answer "Did this send?": { "send_again": true } or false for Mark as sent

Refusal codes: 403 cap_day, 403 cap_recipient_week (with the sentence as message), 409 send_in_flight ("This message is already being sent"), 409 send_unknown (the send may already have gone and its owner was asked), 409 not_unknown (already answered), 404 not_found (not your send). Each change to the limits is a cap_settings_changed event; a send of unknown outcome is send_unknown, its answer send_resolved.

A tool sends when it declares sends: { channel, purpose, recipient } (see Writing packs and skills); idempotent: true says its vendor drops duplicates by key.