Guide
Build an Onboarding Email Agent
Only 12% of employees strongly agree their company onboards new hires well, according to a Gallup study that surveyed over 2.7 million workers. The gap isn't indifference — it's coordination. HR teams lose track of which new hire got which email, orientation events get booked at conflicting times, and silent non-responders slip through until their start date arrives without preparation. An agent account on a dedicated inbox closes the coordination gap: it sends a day-0 welcome, creates the orientation calendar event, watches the inbox for a confirmation reply, and automatically escalates to HR when a new hire hasn't responded in 24 hours. The agent runs the sequence; the model personalizes the copy and classifies replies.
Written by Aaron de Mello Senior Engineering Manager
What is an onboarding email agent?
An onboarding email agent is an autonomous program that drives a new-hire email sequence from a dedicated inbox. It sends the day-0 welcome message, creates an orientation event on the company calendar, watches the inbox for a confirmation reply, and escalates to HR if none arrives within 24 hours. Every step runs on a managed identity — the agent account — so the sequence is auditable, repeatable, and isolated from personal mailboxes.
According to a Gallup study of 2.7 million workers, only 12% of employees strongly agree their company onboards new hires well. Employee turnover in the first 18 months can reach 50%, and SHRM estimates replacing a single employee costs six to nine months of their salary. A well-run onboarding sequence is one of the highest-return investments an HR team can make — and an automated agent makes running it consistently possible.
Why run onboarding on an agent account?
An onboarding agent should own a dedicated inbox, not send from a personal HR address. On an agent account, the onboarding address — say, onboarding@yourapp.nylas.email — is the agent's own identity, and all sent messages, calendar events, and replies are scoped to that one grant. Retire the whole pipeline by suspending one account, with no impact on any human's mailbox. SHRM estimates first-year turnover can reach 50%, and most of that loss happens in the first 90 days — exactly the window a consistent onboarding sequence covers.
It also keeps the agent honest. New-hire reply messages are untrusted input — a crafted reply body is a realistic prompt-injection vector. Because the agent account's outbound rules live on the workspace, a malicious reply can't talk the agent into emailing arbitrary recipients. Containment lives outside the agent's decision loop, so a prompt injection can't prompt its way past a rule it doesn't control. This is the lethal trifecta (private data, untrusted content, external communication) applied to onboarding: the inbox contains private hire data, reply bodies are untrusted, and the send command is the exfil vector. An outbound block rule cuts the third leg.
How do I set up the onboarding inbox?
Create the agent account with one command. The nylas agent account create call returns a managed grant in under 2 seconds, with a live inbox and an attached calendar. Point your HRIS system's new-hire webhook or your welcome-email trigger at this address to start the sequence:
nylas agent account create onboarding@yourapp.nylas.email
export NYLAS_GRANT_ID="$(nylas agent account get onboarding@yourapp.nylas.email --quiet)"The grant ID is what every subsequent nylas command uses to authenticate against the agent's mailbox and calendar. Keep it in an environment variable or a secret manager — not in source control. The account is provider-isolated: the agent can't read or send from any other mailbox, so a bug in the onboarding script can't accidentally touch real HR inboxes.
How does the agent send the day-0 welcome email?
The day-0 welcome is the first message a new hire receives from the company's systems. The nylas email send command dispatches the message in under 200ms, with no SMTP configuration required. The model's only job in this step is personalizing the body — name, role, start date, team name — against a template the code controls. Keep the structure and the call-to-action in the template; let the model fill the personal details:
# Personalized welcome — model fills NAME, ROLE, TEAM from your HRIS payload
nylas email send \
--to "alex.chen@newemployer.com" \
--subject "Welcome to the team, Alex — your orientation details inside" \
--body "Hi Alex, welcome aboard as a Senior Engineer on the Platform team. Your orientation is this Thursday at 10am — details in the calendar invite on its way. Reply to this message to confirm you received it."The reply-to-confirm ask at the end is intentional. It gives the watch loop (covered below) a clear signal to listen for, and it gives new hires an immediate human-feeling action. A template that asks for nothing gets nothing back, which makes non-responder detection unreliable.
How does the agent book the orientation event?
After the welcome email, the agent creates the orientation calendar event so the new hire has something concrete to accept. The nylas calendar events create command adds the event to the agent account's calendar and sends an invitation to the new hire's email address. Creating the event takes under 1 second and returns a stable event ID the agent can reference later if it needs to update the time:
nylas calendar events create \
--title "Orientation: Alex Chen" \
--start "2026-06-12T10:00:00Z" \
--end "2026-06-12T11:30:00Z" \
--description "90-minute orientation covering systems access, team introductions, and first-week plan." \
--participants "alex.chen@newemployer.com"The model doesn't pick the time. Scheduling logic — available slots, timezone normalization, buffer rules — lives in code, not in the prompt. Using the model for time arithmetic is how agents double-book or schedule events in the past. Pull available slots from your HR scheduling system and pass the resolved ISO 8601 timestamp to the CLI command.
How does the agent watch for confirmation replies?
After sending the welcome and booking the event, the agent polls the inbox on a 1-minute cron for confirmation replies. The nylas email list --unread --json command returns new messages as structured JSON. The model's classification task here is narrow: read the reply snippet and return one of three labels — confirmed, question, or other. The code branches on the label; the model never decides what to do next:
nylas email list --unread --json \
| jq '.[] | {id, from: .from[0].email, snippet}'Keeping the model's contract to a three-label classifier makes the classification prompt small (under 100 tokens) and the branching logic auditable. A new hire replying with anything that reads as acknowledgment — "got it", "see you Thursday", "confirmed" — should map to confirmed. A question about directions or access maps to question and routes to a human HR rep via the human-in-the-loop pattern.
How does the agent escalate non-responders?
A non-responder is a new hire who hasn't confirmed within 24 hours of the welcome message. The agent tracks this by recording the send timestamp and checking it on every cron run. When the gap exceeds 86,400 seconds, it escalates to HR with a single nylas email send containing the hire's name and email — no model call needed, because the decision is deterministic. The model doesn't decide when to escalate; a timestamp comparison does:
#!/usr/bin/env bash
set -euo pipefail
# Timing constants
SENT_AT="${SENT_AT:-}" # ISO 8601 send timestamp, from your state store
HIRE_EMAIL="${HIRE_EMAIL:-}" # e.g. alex.chen@newemployer.com
HIRE_NAME="${HIRE_NAME:-}"
now=$(date -u +%s)
sent=$(date -u -d "$SENT_AT" +%s 2>/dev/null || date -u -j -f "%Y-%m-%dT%H:%M:%SZ" "$SENT_AT" +%s)
elapsed=$(( now - sent ))
if (( elapsed >= 86400 )); then
nylas email send \
--to "hr-team@yourcompany.com" \
--subject "Onboarding escalation: $HIRE_NAME has not confirmed" \
--body "$HIRE_NAME ($HIRE_EMAIL) was sent a welcome email $((elapsed / 3600)) hours ago and has not replied. Please follow up before the start date."
fiThe escalation message goes only to your HR team address, not to the new hire, so there's no risk of spamming someone who simply missed the email. The timestamp comparison is the only logic here; keeping it out of the model prevents the 24-hour window from drifting based on how the prompt is phrased.
What does the full onboarding loop look like?
The complete loop is a bash script a cron job runs every minute against the agent account's inbox. It checks for new unread messages, classifies each with a model call, branches on the label, and marks the message read so the next run doesn't reprocess it. A separate daily job checks the state store for new hires past the 24-hour window and fires the HR escalation. Both scripts run under set -euo pipefail so failures surface instead of silently swallowing a missed step:
#!/usr/bin/env bash
# onboarding-watch.sh — runs every minute via cron
set -euo pipefail
msg=$(nylas email list --unread --json | jq -r '.[0] // empty')
[ -z "$msg" ] && exit 0
id=$(echo "$msg" | jq -re '.id')
from=$(echo "$msg" | jq -re '.from[0].email')
snippet=$(echo "$msg" | jq -r '.snippet')
# classify_reply is your LLM call; returns "confirmed", "question", or "other"
label=$(classify_reply "$snippet")
case "$label" in
confirmed)
# Record confirmation in your state store, then mark handled
echo "confirmed:$from" >> /var/log/onboarding-confirmations.log
nylas email mark read "$id" ;;
question)
# Route to a human HR rep and mark handled
nylas email send \
--to "hr-team@yourcompany.com" \
--subject "Onboarding question from $from" \
--body "$snippet"
nylas email mark read "$id" ;;
other)
# Log for review; don't mark read so a human can inspect it
echo "unclassified reply from $from" >&2 ;;
*)
echo "unexpected label '$label' from $from" >&2 ;;
esacThe other arm intentionally doesn't mark the message read. This keeps it visible in the inbox for a human to review instead of silently discarding an unclassified reply. The unknown-label arm logs to stderr so model drift — a label the classifier returns that isn't in the expected set — surfaces in your monitoring. Use the audit guide to add structured logging for each branch.
How do I contain the onboarding agent?
An outbound rule is the last line of defense. It limits where the agent can send, so a crafted reply body or a loop bug can't cause the agent to email arbitrary addresses. The nylas agent rule create command attaches the rule to the agent account in under 1 second:
# Block any outbound message to domains outside your company
nylas agent rule create \
--name "Block outbound to external domains" \
--trigger outbound \
--condition recipient.domain,is,exfil.example \
--action blockBecause the rule lives on the workspace, it fires before the message reaches SMTP. The agent can't prompt its way past it — a malicious reply body that tries to redirect the escalation to an attacker's address hits the block rule and stops. Pair this with a send-rate cap so a runaway loop can't flood your HR team's inbox, and reconcile all recipient addresses against your own team directory in code before the send. The rules and policies guide documents every trigger, condition field, and allowed action, and Stop Your AI Agent From Going Rogue covers the full containment pattern for agents handling untrusted input.
How do I verify the agent is working?
Before running the sequence against real new-hire emails, test it end-to-end against a staging inbox. Send a test message to the agent account, confirm the welcome reply arrives within 60 seconds, check that the calendar event appears in the agent's calendar, and confirm the escalation fires after the test window. Nylas CLI 3.1.16 on a Nylas managed account is the verified configuration for every command in this guide:
# Confirm the agent account is live
nylas agent account get onboarding@yourapp.nylas.email --quiet
# Send a test welcome and verify delivery
nylas email send \
--to "your-test-address@example.com" \
--subject "Test: Onboarding welcome" \
--body "Verify this arrives within 60 seconds."
# Poll the inbox for any unread replies
nylas email list --unread --json | jq '.[].from[0].email'Tested on Nylas CLI 3.1.16 with a Nylas managed account. Provider-side behavior described in this guide — calendar invitations, reply handling — is documented provider behavior. Verify locally before deploying to production.
Next steps
- Getting Started with Agent Accounts — the architecture behind the onboarding inbox and its workspace
- Build a Lead-Capture & Qualification Agent — the same agent-account pattern applied to inbound sales leads
- Build a Human-in-the-Loop Email Agent — require HR to confirm escalations before the agent acts on them
- Agent Rules and Policies — outbound guardrails and send caps that contain the agent
- Stop Your AI Agent From Going Rogue — the full containment pattern for agents handling untrusted input
- Full command reference — every
nylas email,nylas calendar, andnylas agentflag - Nylas v3 API documentation — the API surface behind these commands