Multi-step outreach your agent runs end-to-end
Define a sequence once — email, LinkedIn connect, follow-up message, conditional branches. Enroll a lead with one API call. MyAgentMail handles the schedule, deliverability, and reply detection — your agent supplies the content per step (with full business context) and reads the outcome to decide what comes next.
Included with every Email and LinkedIn plan. No extra add-on.
The problem cadences solve
Most agent outreach falls apart on day two. The first message is easy — your agent drafts something thoughtful and ships it. Then what? You need follow-ups. You need them to fire only if the prospect didn't reply. You need them to switch channels (email → LinkedIn DM) when the first one goes quiet. You need them to stop the moment a reply comes back, so a human takes over.
Wiring that yourself means cron jobs, a state machine, retry logic, reply detection glued to your inbox webhook, and a way to pause everything when someone says "unsubscribe." It's the kind of plumbing that consumes 80% of a "build an AI SDR" project before the agent has done anything interesting.
Cadences are that plumbing, factored out into the API. You define the steps. We run them.
Three building blocks
Steps, conditions, enrollments. That's the whole model.
What runs
linkedin_connect— send a connection requestlinkedin_message— DM (often gated on accept)email— send a personalized emailwait— pause for N hours or days
Each step uses a static template with merge fields (set once at create time) or asks your app for content per-lead via cadence.step.draft.requested webhook — your agent brings the message, MyAgentMail brings the rails. Defined via PUT /v1/cadences/:id/steps.
When it runs
after_accept— only after a LinkedIn invite is acceptedno_reply_to_prev— skip if they replied to the previous stepnever_replied— skip if they replied at any prior step
Conditions gate a step against the lead's history. The runner evaluates them at each tick — no replied-but-still-followed-up mistakes.
Who's in it
active— runner advances through stepsreplied / accepted— auto-stops, surfaces to agentbounced / unenrolled / completed— terminal states
Enroll a lead with one POST. Each enrollment carries the prospect's email + LinkedIn URN + arbitrary metadata your agent can read on every reply event.
One worked example
Connect on LinkedIn → wait 2 days → DM if accepted → wait 5 days → email fallback if still silent. Total: ~30 lines.
import { MyAgentMail } from "myagentmail";
const mam = new MyAgentMail({ apiKey: process.env.MAM_KEY! });
// 1. Create the cadence shell
const cadence = await mam.cadences.create({
name: "Founder outreach — Series A AI",
inboxId: "ibx_...", // which inbox sends email steps
sessionId: "lks_...", // which LinkedIn session runs LI steps
});
// 2. Define the sequence — your app drafts each step at fire-time
// via cadence.step.draft.requested webhook. MAM never writes copy.
await mam.cadences.replaceSteps(cadence.id, [
{ kind: "linkedin_connect", drafting: "webhook",
promptHint: "Warm, 1-sentence note referencing their recent post." },
{ kind: "wait", waitHours: 48 },
{ kind: "linkedin_message", condition: "after_accept", drafting: "webhook",
promptHint: "Ask if they're open to a 15-min chat about {{topic}}." },
{ kind: "wait", waitHours: 120 },
{ kind: "email", condition: "never_replied", drafting: "webhook",
promptHint: "Short fallback. Reference the LI connect. Offer value, not a meeting." },
]);
// 3. Enroll a lead
await mam.cadences.enroll(cadence.id, {
email: "[email protected]",
linkedinUrn: "urn:li:person:abc123",
metadata: { topic: "agent-driven outreach", firstName: "Alice" },
});
// 4. Listen for events (webhook or polling)
// cadence.enrollment.replied → your agent jumps in, takes over the thread
// cadence.enrollment.accepted → connection landed, DM step queued
// cadence.enrollment.completed → ran all steps without a replyThe runner ticks every few minutes. Replies coming back to either channel (email or LinkedIn DM) auto-transition the enrollment to replied and stop further steps for that lead. You don't have to detect replies yourself.
What the runner handles for you
The stuff you'd otherwise have to build and maintain forever.
Per-prospect content from your agent
Each step fires a synchronous webhook to your app at send time with the enrollment's metadata + thread context. Your agent drafts the message with full business context — MyAgentMail never sees your prompts. Same cadence, uniquely written for every lead, no mail-merge fingerprint.
Conditional gating
after_accept, no_reply_to_prev, never_replied — evaluated against the lead's full history on every tick. No follow-ups to people who already replied.
Reply detection
Replies on either channel auto-pause the cadence for that lead. message.received and LinkedIn DM webhooks both feed into the enrollment state machine.
Smart scheduling
wait steps respect timezone, send-window preferences, weekends, and per-account warmup limits. The runner ticks every few minutes — no cron to operate.
Channel handoff
A cadence can move a prospect from LinkedIn → email mid-sequence. Same enrollment, same identity, threading preserved.
Safe stop
Unsubscribe footer in emails auto-unenrolls. Manual unenroll via API. Suspended tenants auto-pause every active enrollment instantly.
Reselling to your own customers? Cadences are workspace-scoped at create time — pinned to one inbox and one LinkedIn session that belong to the same workspace. Every tier gives you one isolated workspace per connected LinkedIn account (Solo 2, Team 15, Agency 60), so each of your customers gets their own isolated cadences, sessions, and signals. See LinkedIn pricing for tier details.
API surface
Nine endpoints. Same shape across SDK, REST, and MCP.
| Method · path | What it does |
|---|---|
| POST /v1/cadences | Create a cadence shell |
| GET /v1/cadences | List your cadences |
| GET /v1/cadences/:id | Fetch one with its steps |
| PATCH /v1/cadences/:id | Rename, pause, swap inbox/session |
| DELETE /v1/cadences/:id | Remove (also stops active enrollments) |
| PUT /v1/cadences/:id/steps | Replace the full step list atomically |
| POST /v1/cadences/:id/enrollments | Enroll a lead |
| GET /v1/cadences/:id/enrollments | List enrollments, filter by state |
| POST /v1/cadences/:id/run | Force a tick now (testing) |
Full schemas + try-it pane: /docs (Cadences group). Markdown for LLMs: /docs-md/cadence-create et al.
Agent-callable, too
The MCP server exposes cadence_create, cadence_replace_steps, cadence_enroll_lead, cadence_list_enrollments, cadence_run_now as native MCP tools. Drop into Claude Desktop, Cursor, Windsurf, Cline — your agent can define and run a cadence without writing any of the wiring.
npx -y myagentmail-mcp installRun your first cadence in 5 minutes.
Included with any Email or LinkedIn plan. 7-day free trial — card required, cancel anytime before day 7.