Why multi-agent collision arbitration matters
Autonomous AI agents (SDR follow-up bots, customer success bots, marketing agents, billing engines) operate concurrently across separate background worker threads and distinct API keys.
Without centralized server arbitration, multiple agents independently target the same customer within minutes. This causes severe recipient fatigue, aggressive spam complaints, domain reputation damage, and customer churn.
Furthermore, sending automated marketing or sales follow-ups to a customer who currently has an open, unresolved support ticket or billing complaint destroys customer trust. SadaSend solves this architecturally at the API gateway before an email ever enters the MTA queue.
Hierarchical priority tiers & preemption
Every outbound send is evaluated through hierarchical priority scheduling:
• P0: Auth & Security (`priority: "auth"`): One-time passcodes, password resets, magic links, and fraud alerts. Always dispatched immediately; never held by cooldowns.
• P1: Support (`priority: "support"`): Direct human customer service replies. Preempts lower-priority cooldowns.
• P2: Billing (`priority: "billing"`): Invoices, receipt notifications, failed payment alerts, and subscription renewals. Preempts marketing or follow-up holds.
• P3: Follow-Up (`priority: "follow_up"`): Automated sales cadences, onboarding check-ins, and proactive agent outreach. Subject to sliding contact cooldowns and support ticket holds.
• P4: Marketing (`priority: "marketing"`): Promotional newsletters and campaign announcements. Lowest priority; held automatically if an active cooldown or support ticket exists.
Support-ticket-aware delivery holds
When a customer opens a support ticket in Zendesk, Intercom, Plain, or your internal CRM, your system registers the active ticket with POST /arbiter/tickets.
While a support ticket is active, outbound agent emails with priority P3 (Follow-Up) or P4 (Marketing) are automatically paused and routed into the approval queue (pending_approval). Critical billing and security messages continue uninterrupted.
Once the support issue is resolved, your CRM webhook calls DELETE /arbiter/tickets/:recipient to resume normal agent communication.
# Register an active customer support ticket to pause automated outreach
curl -X POST https://api.sadasend.com/arbiter/tickets \
-H "Authorization: Bearer sada_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"recipient": "customer@enterprise.com",
"ticketId": "TKT-10492",
"subject": "Billing dispute regarding annual invoice",
"holdPriorityThreshold": 3
}'Querying recipient cooldown status in TypeScript
Autonomous agents can query recipient status before generating personalized email drafts, saving LLM token costs when a customer is already on active cooldown:
import { SadaSend } from 'sadasend';
const client = new SadaSend({ apiKey: process.env.SADASEND_API_KEY });
// Query recipient cooldown before agent drafting
const status = await client.arbiter.cooldowns.status('customer@enterprise.com');
if (status.ok && status.data.cooldownActive) {
console.log(`Agent on cooldown until ${status.data.expiresAt} (${status.data.remainingSeconds}s remaining)`);
} else {
// Safe to draft and dispatch email with server-enforced cooldown
const result = await client.emails.send({
from: 'alex@yourdomain.com',
to: 'customer@enterprise.com',
subject: 'Following up on our product demo',
text: 'Hi Sarah, wanted to follow up on our discussion yesterday.',
source: 'agent',
agentName: 'SDR Outreach Agent',
crossAgentCooldown: '48h',
priority: 'follow_up',
});
if (!result.ok) throw new Error(result.error.message);
console.log('Dispatched message ID:', result.id);
}Python SDK collision prevention recipe
In Python AI agent pipelines (CrewAI, LangGraph, AutoGen), wrap outreach steps with arbiter status checks:
import os
from sadasend import SadaSend
client = SadaSend(os.environ["SADASEND_API_KEY"])
recipient = "prospect@acme-corp.com"
# Check if any other agent has contacted this prospect recently
status = client.arbiter_recipients.status(recipient)
if not status.get("cooldownActive"):
# Dispatch outreach email with 24-hour server-enforced cooldown
response = client.emails.send(
from_="sales@yourdomain.com",
to=recipient,
subject="AI Infrastructure for Acme Corp",
text="Hi team, loved your latest release and wanted to share our benchmarks.",
source="agent",
agent_name="SalesBot-1",
cross_agent_cooldown="24h",
priority="follow_up",
)
print(f"Sent email ID: {response['id']}")
else:
print(f"Skipping {recipient}: Active cooldown ({status.get('remainingSeconds')}s remaining)")Arbiter REST API endpoint reference
| Method & Endpoint | Description | Required Scopes & Roles |
|---|---|---|
| GET /arbiter/recipients/:recipient/status | Query recipient cooldown status, active support ticket hold, and send velocity. | Scope: read |
| POST /arbiter/recipients/:recipient/cooldown | Set sliding contact cooldown (?duration=24h, priority, agentName) preventing multi-agent collisions. | Scope: write |
| DELETE /arbiter/recipients/:recipient/cooldown | Clear active contact cooldown for a recipient. | Scope: write |
| POST /arbiter/tickets | Register active customer support ticket hold (ticketId, recipient, subject, priorityThreshold) pausing automated agent sales/marketing outreach. | Scope: write |
| DELETE /arbiter/tickets/:recipient | Resolve customer support hold, re-enabling agent outreach. | Scope: write |
| GET /arbiter/stats | Account-level collision statistics, active cooldown count, and prevented email blasts. | Scope: read |