AI Agent Onboarding Emails: The Complete Guide
2026-03-19
Most onboarding sequences are time-based. Sign up on Monday, get a welcome email. Tuesday, a feature highlight. Wednesday, a nudge. The schedule doesn't care whether the user actually did anything.
AI agents can do better. They can watch for product events - first API call made, team member invited, billing activated - and send the next email only when it's relevant. No more "Have you tried our API?" emails landing in the inbox of someone who's already sent 500 requests.
But event-driven onboarding with an autonomous agent introduces a new problem: without guardrails, the agent can over-send, re-contact too soon, or duplicate messages when events fire in quick succession. The sequence needs to be smart about when to send and when to hold.
This guide walks through building an onboarding email sequence on Molted - from creating the journey to triggering it from product events - with policy enforcement handling the guardrails so your agent doesn't have to.
What makes agent-driven onboarding different
Traditional onboarding tools (Intercom, Customer.io, HubSpot) run sequences on fixed timers. Drip campaigns. Day 1, Day 3, Day 7. The user's behavior might influence which branch they take, but the cadence is predetermined.
An agent-driven sequence flips this. The agent observes what the user has done and decides what to send next based on actual milestones. The emails are contextual and timely instead of calendar-driven.
Here's the difference in practice:
Time-based: "It's been 48 hours since signup. Send the feature tour email."
Event-driven: "The user just created their first mailbox but hasn't sent an email yet. Send the first-send tutorial."
The second approach converts better because it meets the user where they are. But it also creates more opportunities for the agent to make mistakes - sending two emails in quick succession when multiple events fire at once, or re-sending a tutorial after the user already completed the step.
That's why the policy layer matters. It's the difference between a helpful onboarding sequence and an annoying one.
Designing the sequence
Before writing code, map your onboarding milestones. These are the product events that indicate a user has progressed - or stalled.
A typical SaaS onboarding sequence might track:
| Milestone | Event | Email if completed | Email if stalled |
|-----------|-------|--------------------|------------------|
| Signup | user.signed_up | Welcome + quick start | - |
| First API call | api.first_call | "Nice - here's what to try next" | "Here's how to make your first call" (after 24h) |
| Team invite | team.member_invited | Skip to next milestone | "Your team can help" (after 48h) |
| First send | email.first_sent | "Your first email is out" | "Ready to send?" (after 72h) |
| Billing activated | billing.activated | "You're all set" | Trial expiry reminder (Day 10) |
The key design decision: every email should be triggered by an event (either a completion or a timeout), not by a calendar day. This means your agent needs two inputs - the event stream from your product, and a way to schedule delayed checks for stalls.
Setting up the journey
Molted's journey orchestration lets you define multi-step sequences triggered by product events. Each step can send an email, wait for a delay, or branch based on conditions.
Create the journey:
curl -X POST https://api.molted.email/v1/journeys \
-H 'Authorization: Bearer mm_live_...' \
-H 'Content-Type: application/json' \
-d '{
"tenantId": "your-tenant-id",
"name": "Onboarding Sequence",
"triggerEvent": "user.signed_up"
}'
Then add steps. The first step sends the welcome email immediately:
curl -X POST https://api.molted.email/v1/journeys/j_abc/steps \
-H 'Authorization: Bearer mm_live_...' \
-H 'Content-Type: application/json' \
-d '{
"tenantId": "your-tenant-id",
"stepOrder": 1,
"stepType": "send",
"config": {
"templateId": "onboarding-welcome",
"dedupeKeyPrefix": "onboarding",
"payload": { "trialDays": 14 }
}
}'
Add a delay before checking whether the user has progressed:
{
"stepOrder": 2,
"stepType": "delay",
"config": { "delayMinutes": 1440 }
}
Then a branch to check the user's lifecycle stage:
{
"stepOrder": 3,
"stepType": "branch",
"config": {
"conditions": [
{ "field": "lifecycleStage", "operator": "eq", "value": "active", "nextStepOrder": 6 },
{ "field": "lifecycleStage", "operator": "eq", "value": "trial", "nextStepOrder": 4 }
]
}
}
If the user is still in trial after 24 hours, step 4 sends the "make your first API call" tutorial. If they're already active, step 6 skips ahead to the team invite nudge.
The pattern repeats: send, delay, branch, send. Each branch checks whether the user has completed the milestone or stalled.
Triggering the sequence from your product
When a user signs up, your backend fires the trigger event:
curl -X POST https://api.molted.email/v1/agent/events/ingest \
-H 'Authorization: Bearer mm_live_...' \
-H 'Content-Type: application/json' \
-d '{
"tenantId": "your-tenant-id",
"eventName": "user.signed_up",
"contactEmail": "alice@example.com",
"payload": { "plan": "starter" }
}'
When eventName matches the journey's triggerEvent, a run is created for that contact and the first step executes. Duplicate runs for the same journey and contact are automatically prevented - so if your signup webhook fires twice, the user still gets one welcome email.
As the user hits milestones, fire more events:
curl -X POST https://api.molted.email/v1/agent/events/ingest \
-H 'Authorization: Bearer mm_live_...' \
-H 'Content-Type: application/json' \
-d '{
"tenantId": "your-tenant-id",
"eventName": "email.first_sent",
"contactEmail": "alice@example.com",
"payload": { "provider": "resend" }
}'
These events update the contact's context, which the branch steps evaluate when the journey reaches them. The agent doesn't need to decide what to send next - the journey structure handles routing. The agent just needs to report what happened.
How policy protects the sequence
Every send step in the journey passes through the full policy engine before the email leaves. This is where agent-driven onboarding becomes safer than the traditional approach.
Consider what happens when events fire in quick succession. A user signs up, immediately makes their first API call, and invites a team member - all within five minutes. Without policy enforcement, the journey might fire three emails almost simultaneously.
With Molted's policy engine, each send is checked against:
- Per-recipient cooldowns - the same person can't receive more than one email within a configured window, even if three journey steps try to fire at once
- Deduplication - each send has a
dedupeKey(constructed from thededupeKeyPrefixand the step), so the same onboarding step can never send twice to the same recipient - Suppression lists - if the user unsubscribed or previously bounced, the send is blocked regardless of what the journey says
- Rate limits - triple-window rate limiting (hourly, daily, monthly) prevents the onboarding sequence from consuming your entire send budget
When a send is blocked, the journey receives a structured response:
{
"requestId": "req_abc123",
"status": "blocked",
"reason": "cooldown",
"cooldownExpiresAt": "2026-03-19T14:45:00Z"
}
The journey can handle this gracefully - wait for the cooldown to expire, then retry. Or skip the step and move on. The point is that the policy layer caught the issue before a recipient got three emails in five minutes.
Stall detection: the emails that matter most
The highest-converting onboarding emails aren't the welcome messages. They're the stall recovery emails - the ones that reach users who started setup but got stuck.
Detecting stalls requires checking what hasn't happened. Your agent can do this by querying contact context:
curl -X POST https://api.molted.email/v1/agent/propose-email \
-H 'Authorization: Bearer mm_live_...' \
-H 'Content-Type: application/json' \
-d '{
"tenantId": "your-tenant-id",
"recipientEmail": "alice@example.com"
}'
The response includes the contact's lifecycle stage, recent send count, and active journeys:
{
"contactContext": {
"email": "alice@example.com",
"lifecycleStage": "trial",
"recentSends": 1,
"recentInbound": 0,
"activeJourneys": 1
}
}
If lifecycleStage is still trial and recentSends is 1 (just the welcome email) after 48 hours, the user stalled. Your agent can use next-best-action to get a recommendation:
curl -X POST https://api.molted.email/v1/agent/next-best-action \
-H 'Authorization: Bearer mm_live_...' \
-H 'Content-Type: application/json' \
-d '{
"tenantId": "your-tenant-id",
"contactEmail": "alice@example.com"
}'
The stall recovery email should be specific. Not "Checking in!" but "You created your account but haven't sent your first email yet. Here's a 2-minute walkthrough." Reference exactly where they stopped.
Attributing onboarding to outcomes
The point of onboarding emails isn't open rates. It's activation - getting users to the moment where they experience the product's value. Molted's outcome tracking lets you close the loop.
When a user activates (however you define it), record the outcome:
curl -X POST https://api.molted.email/v1/outcomes/ingest \
-H 'Authorization: Bearer mm_live_...' \
-H 'Content-Type: application/json' \
-d '{
"tenantId": "your-tenant-id",
"contactEmail": "alice@example.com",
"eventType": "activation",
"eventName": "First production email sent"
}'
Later, pull the journey impact report to see how your onboarding sequence contributes to activation:
curl https://api.molted.email/v1/outcomes/journey-impact?tenantId=your-tenant-id \
-H 'Authorization: Bearer mm_live_...'
[
{
"journeyName": "Onboarding Sequence",
"totalOutcomes": 120,
"attributedOutcomes": 85,
"attributedRevenue": 34000
}
]
This tells you that 85 out of 120 activations had the onboarding journey in their touchpoint history. Not vanity metrics - actual revenue attribution.
The implementation checklist
To build an event-driven onboarding sequence with Molted:
-
Map your milestones. Identify the 4-6 product events that mark onboarding progress. Define what "stalled" means for each one.
-
Create templates. One per milestone - both the "you did it" progression email and the "need help?" stall recovery email. Use the
_defaulttransactional template type for onboarding emails (they bypass marketing suppression rules). -
Build the journey. Create the journey with
triggerEvent: "user.signed_up", then add send, delay, and branch steps. Keep delays proportional to how long the step should reasonably take - 24 hours for a first API call, 48 hours for a team invite. -
Instrument your product. Fire events to
/v1/agent/events/ingestwhen users hit milestones. The more events you send, the more responsive the sequence becomes. -
Activate and monitor. Set the journey to
active. Watch the journey runs viaGET /v1/journeys/:id/runsto see where users are progressing and where they're stalling. -
Close the loop. Record outcomes via
/v1/outcomes/ingestwhen users activate or convert. Use the journey impact report to measure what's working.
The policy engine handles the rest - deduplication, cooldowns, suppression, rate limits. Your agent focuses on reporting events and the journey handles sequencing. No homegrown rate limiters, no deduplication logic in your application code, no 3 AM pages because a retry loop sent 500 welcome emails.
If you're building agent-driven onboarding, start with a free trial or read the journey orchestration docs.
Keep reading
- How to Send Your First Policy-Checked Email - a step-by-step tutorial from signup to first send
- What Happens When an AI Agent Over-Sends - the anatomy of a runaway agent and what your infrastructure should catch
- Why AI Agents Need Email Guardrails - the case for policy enforcement between agents and the inbox
- What Is Agent-Native Email? - the infrastructure layer that makes safe agent email possible