Email Agent

Purpose

The Email Agent autonomously generates personalized cold email sequences, sends them through Amazon SES, monitors replies, classifies intent, and routes hot leads to the BDR queue in HubSpot. It replaces third-party tools like Instantly or Smartlead with a fully custom system.

Email Generation with Claude API

Each email is generated dynamically using the Claude API. The agent receives seller context from HubSpot (business name, category, estimated revenue, marketplace, trigger events) and generates a personalized email using one of three sequence frameworks.

Prompt Structure for Email Generation

System: You are writing cold outreach emails for a daily payout service for Amazon/Walmart sellers.
The service lets sellers access their marketplace earnings every day instead of waiting 2-3 weeks.
Fee is 2-3% of sales volume. Not a loan — no interest, no credit check, no debt.
The company has 100+ active sellers using the service.

Rules:
- Under 120 words per email
- Never say "factoring" — say "daily payouts" or "get paid every day"
- Never open with "I hope this finds you well" or "My name is..."
- One idea per email
- Soft CTA only — "Would it be worth a 15-minute call?" not "Sign up now"
- Tone: peer-to-peer, like a fellow seller sharing a tool, not a salesperson pitching
- Personalize using the seller data provided

Seller context:
- Business name: {business_name}
- Marketplace: {marketplace}
- Primary category: {category}
- Estimated monthly revenue: {revenue}
- Trigger event: {trigger_event}
- Sequence: {sequence_type}
- Email number: {email_number} of 4

Generate only the email subject line and body. No preamble.

Three Sequence Frameworks

Sequence A: The Cash Flow Calculator — Default for medium-priority leads (score 40–69). . Day 1: Personalized observation + "Do you know how much cash is sitting in Amazon right now?" + calculator link . Day 3: Brief case study of similar seller. Three sentences max. . Day 7: Address #1 objection ("Is this a loan?"). Soft CTA. . Day 14: Breakup email + testimonial.

Sequence B: The Seasonal Trigger — Used when trigger_event = seasonal_prep or when approaching Q4/Prime Day. . Day 1: Lead with upcoming season. Frame the cash flow challenge. Introduce daily payouts. . Day 3: Stat about sellers missing revenue targets due to cash flow during peak seasons. . Day 7: Case study of seller who capitalized on seasonal opportunity. . Day 14: Breakup with urgency about timeline.

Sequence C: The Payment Hold Recovery — Used when trigger_event = payment_hold. . Day 1: Empathize with hold experience. Introduce daily payouts as insurance. . Day 3: How the service works during holds specifically. Tactical. . Day 7: Testimonial from seller who survived a hold. . Day 14: Breakup + helpful resource (payment hold guide).

Sequence Assignment Logic

  • trigger_event = payment_hold → Sequence C

  • trigger_event = seasonal_prep → Sequence B

  • trigger_event = scaling_ads, new_launch, expanding_marketplace → Sequence A

  • trigger_event = none → Sequence A (default)

Sending Infrastructure (Amazon SES)

Domain Setup

Register 5 sending domains (variations of your brand name). For each domain: * Configure SPF, DKIM, and DMARC records * Set up SES domain identity verification * Create 3 mailboxes per domain (15 total mailboxes) * Warm each mailbox over 3 weeks: start at 20/day, increase by 10/day each week, cap at 80/day

Runtime: AgentCore Runtime (marketplace-email-agent)

The Email Agent runs as an AgentCore Runtime deployment. It does not live in Lambda. Lambda functions are only used as tools called via AgentCore Gateway, and as thin webhook receivers that forward inbound events to the agent.

AgentCore services used by this agent: * AgentCore Runtime — hosts the agent; handles both scheduled send runs and inbound reply events as separate session invocations * AgentCore Memory (email-sequences store) — per-contact sequence position, send timestamps, reply history, A/B test variant assignments, per-mailbox daily send counts; eliminates manual DynamoDB state tracking * AgentCore Memory (cross-agent-leads shared store) — reads contact lifecycle stage and score; writes reply outcomes visible to Voice and LinkedIn agents * AgentCore Identity — manages Claude API key, SES SMTP credentials per mailbox, HubSpot token * AgentCore Gateway — exposes ses_send_email, ses_verify_email, hubspot_get_contact, hubspot_update_stage, hubspot_create_task, dynamo_check_suppression as MCP tools

Triggers: * Scheduled send run: EventBridge every 15 min → dispatch-email-sender Lambda → InvokeAgentRuntime * Inbound reply: SES receipt rules → SNS → webhook-ses-inbound Lambda → InvokeAgentRuntime with reply payload

Sending Logic

AgentCore Runtime Session: email-send-run
Trigger: EventBridge every 15 minutes, 8am–6pm ET Mon–Fri

Steps:
1. Read from AgentCore Memory (email-sequences): contacts in active sequences
   needing their next email based on sequence timing
2. Read per-mailbox daily send counts from AgentCore Memory — enforce limits
3. Check suppression via `dynamo_check_suppression` tool (bounces, complaints,
   unsubscribes, disqualified contacts)
4. For each eligible send:
   a. Select mailbox using round-robin from AgentCore Memory state
   b. Call Claude API (via AgentCore Identity credential) to generate personalized email
   c. Call `ses_send_email` tool with selected mailbox and generated content
   d. Update AgentCore Memory: increment mailbox send count, advance sequence position,
      log send timestamp
   e. Call `hubspot_update_stage` tool if lifecycle stage needs updating
5. Respect per-mailbox limits: max 50/day during first month, 80/day after
   (enforced from AgentCore Memory counters, not DynamoDB manual checks)

Total Daily Capacity

  • 15 mailboxes × 50–80 emails/day = 750–1,200 emails/day

  • Monthly: 15,000–25,000 emails (well above the 3,000–5,000 target, providing headroom)

Reply Handling

Inbound Processing

AgentCore Runtime Session: email-reply-session
Trigger: SES receipt rules → SNS → webhook-ses-inbound Lambda → InvokeAgentRuntime
         (Lambda is a thin forwarder only; all reply logic runs inside AgentCore)

Steps:
1. Parse incoming email payload (reply body, sender, in-reply-to header) from
   the invocation input
2. Match to original outbound email via AgentCore Memory (email-sequences store)
   — look up send record by in-reply-to message ID
3. Classify reply intent using Claude API (via AgentCore Identity credential):
   - "interested" → call `hubspot_create_task` tool (BDR alert), call
     `hubspot_update_stage` tool (→ engaged), write to cross-agent-leads memory
   - "not_interested" → call `hubspot_update_stage`, call `dynamo_check_suppression`
     tool to add to suppression list, generate polite close via Claude + `ses_send_email`
   - "question" → generate helpful response via Claude + `ses_send_email` tool,
     log in AgentCore Memory and HubSpot
   - "out_of_office" → update sequence timing in AgentCore Memory to reschedule next send
   - "unsubscribe" → `dynamo_check_suppression` tool to add to suppression, confirm
     removal via `ses_send_email`, update HubSpot
   - "wrong_person" → suppression + attempt to find correct contact via
     `hubspot_get_contact` tool
4. Write reply classification and content summary to AgentCore Memory (email-sequences)
   and update HubSpot via `hubspot_update_stage` tool

Reply Classification Prompt

Classify this email reply into exactly one category:
- interested: The person wants to learn more, is open to a call, or asks how the service works
- not_interested: The person explicitly declines or says they don't need the service
- question: The person asks a specific question but hasn't committed to a call
- out_of_office: Auto-reply indicating the person is away
- unsubscribe: The person asks to be removed from emails
- wrong_person: The person says this isn't relevant to them / they don't sell on Amazon/Walmart

Reply text: {reply_body}

Respond with only the category name.

Self-Optimization

The Email Agent continuously improves its own performance: * Subject line testing: For each sequence, generate 3 subject line variants. Track open rates by variant. After 100 sends per variant, promote the winner and generate a new challenger. * Send time optimization: Track reply rates by hour and day of week. After 30 days, shift send schedules toward highest-performing windows. * Sequence routing: Track demo booking rates by sequence type. Adjust default routing if one sequence consistently outperforms. * Optimization data stored in AgentCore Memory (email-sequences store). The agent reads this during each send session to self-tune. No separate Lambda function needed — the agent handles optimization as part of its own reasoning loop.

Compliance

  • Include unsubscribe link in every email (CAN-SPAM compliance)

  • Honor unsubscribes within 24 hours (actually immediate via suppression list)

  • Include physical mailing address in email footer

  • Maintain bounce rate under 3% — auto-pause mailboxes that exceed this

  • Maintain complaint rate under 0.1% — auto-pause if exceeded

  • Never email contacts in disqualified stage or on suppression list

Expected Metrics

Metric Target

Daily sends

200–400 (ramp to 800+ by Month 3)

Open rate

40–55%

Reply rate

3–6%

Positive reply rate

1–2%

AI-handled replies (questions, OOO, unsub)

70–80% of all replies

BDR-escalated replies (interested)

20–30% of all replies

Demos booked from email

20–50/month