February 20, 2026 · 17 min read

AI Agent for Gmail & Email: Automate Inbox Management, Drafts & Follow-ups

The average professional spends 2.5 hours per day on email. An AI agent handles 80% of it — triaging, drafting, following up — while you focus on work that matters. Here's exactly how to build one.

The Email Problem (and Why Filters Aren't Enough)

Gmail filters can sort emails into folders. Rules can auto-archive newsletters. Labels can color-code senders. But none of that helps with the actual work:

That's the work an AI email agent automates. Not replacing your judgment — but handling the processing overhead so you only deal with emails that genuinely need your attention.

Before vs After

A day with an email agent

Before: Wake up to 47 emails. Spend 45 minutes triaging. Draft 12 replies. Forget to follow up on 3 important threads. Miss an action item buried in paragraph 4 of a long email.

After: Wake up to a summary: "3 urgent, 8 need reply, 12 FYI, 24 auto-handled." Review the 3 urgent ones. Approve/edit the 8 draft replies the agent prepared. Follow-ups are scheduled automatically. Action items are already in your task list.

5 Email Agent Capabilities

Capability 1

Intelligent Triage

Classifies every incoming email: Urgent (needs reply today), Important (needs reply this week), FYI (read when you want), Noise (auto-archive). Uses sender history, content analysis, and your past behavior to learn your priorities.

Capability 2

Context-Aware Drafts

Drafts replies using the full email thread, your past conversations with this person, your calendar (for scheduling), and your writing style. You review and hit send — or edit first. The agent learns from your edits.

Capability 3

Follow-up Tracking

Monitors sent emails. If no reply in X days, creates a follow-up draft. Tracks which emails need responses and from whom. Sends you a daily digest: "3 emails awaiting reply for 3+ days."

Capability 4

Action Item Extraction

Scans every email for commitments, deadlines, and tasks. "Can you send the report by Friday?" becomes a task in your project management tool, due Friday, linked back to the email.

Capability 5

Thread Summarization

Long email threads with 15+ messages? The agent gives you a 3-sentence summary: key decisions, open questions, and what's needed from you. Perfect for catching up before meetings.

Architecture: The Email Agent Stack

┌─────────────────────────────────────────────┐
│              Gmail / Email Provider          │
│    Push notifications via Pub/Sub or IMAP    │
└────────────────┬────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────┐
│            Email Processing Pipeline         │
│  ┌─────────┐  ┌──────────┐  ┌───────────┐  │
│  │ Fetch & │→ │ Classify │→ │ Route to  │  │
│  │ Parse   │  │ & Triage │  │ Handler   │  │
│  └─────────┘  └──────────┘  └───────────┘  │
├─────────────────────────────────────────────┤
│              Action Handlers                 │
│  ┌─────────┐ ┌──────────┐ ┌────────────┐   │
│  │ Draft   │ │ Extract  │ │ Follow-up  │   │
│  │ Reply   │ │ Actions  │ │ Scheduler  │   │
│  └─────────┘ └──────────┘ └────────────┘   │
├─────────────────────────────────────────────┤
│            Context Layer                     │
│  Contact history │ Calendar │ Writing style  │
│  Past threads    │ CRM data │ Preferences   │
└─────────────────────────────────────────────┘

Build: Inbox Triage Agent

import Anthropic from "@anthropic-ai/sdk";
import { google } from "googleapis";

const anthropic = new Anthropic();
const gmail = google.gmail({ version: "v1", auth: oAuth2Client });

async function triageInbox() {
  // Fetch unread emails
  const { data } = await gmail.users.messages.list({
    userId: "me",
    q: "is:unread",
    maxResults: 50,
  });

  if (!data.messages) return [];

  const results = [];

  for (const msg of data.messages) {
    const email = await gmail.users.messages.get({
      userId: "me",
      id: msg.id,
      format: "full",
    });

    const headers = email.data.payload.headers;
    const from = headers.find(h => h.name === "From")?.value;
    const subject = headers.find(h => h.name === "Subject")?.value;
    const date = headers.find(h => h.name === "Date")?.value;
    const body = extractBody(email.data.payload);

    // Get sender history
    const senderHistory = await getSenderHistory(from);

    // Classify with Claude
    const response = await anthropic.messages.create({
      model: "claude-sonnet-4-20250514",
      max_tokens: 300,
      messages: [{
        role: "user",
        content: `Triage this email. Return JSON:
{
  "priority": "urgent|important|fyi|noise",
  "category": "client|team|vendor|newsletter|notification|spam",
  "needs_reply": true/false,
  "reply_deadline": "today|this_week|no_rush|none",
  "summary": "1-sentence summary",
  "action_items": ["list of actions needed"],
  "suggested_labels": ["gmail labels to apply"]
}

Sender: ${from}
Subject: ${subject}
Sender history: ${senderHistory.replyRate}% reply rate, ${senderHistory.avgResponseTime}h avg response
Body: ${body.substring(0, 2000)}`
      }],
    });

    const triage = JSON.parse(response.content[0].text);

    // Apply labels in Gmail
    await applyLabels(msg.id, triage);

    // If noise, auto-archive
    if (triage.priority === "noise") {
      await gmail.users.messages.modify({
        userId: "me",
        id: msg.id,
        requestBody: { removeLabelIds: ["INBOX"] },
      });
    }

    results.push({ from, subject, ...triage });
  }

  return results;
}

async function applyLabels(messageId, triage) {
  const labelMap = {
    urgent: "IMPORTANT",
    important: "CATEGORY_PERSONAL",
  };

  const labelId = labelMap[triage.priority];
  if (labelId) {
    await gmail.users.messages.modify({
      userId: "me",
      id: messageId,
      requestBody: { addLabelIds: [labelId] },
    });
  }
}

// Generate morning digest
async function generateDigest(triageResults) {
  const urgent = triageResults.filter(r => r.priority === "urgent");
  const important = triageResults.filter(r => r.priority === "important");
  const fyi = triageResults.filter(r => r.priority === "fyi");
  const noise = triageResults.filter(r => r.priority === "noise");

  return `📬 Morning Email Digest

🔴 Urgent (${urgent.length}):
${urgent.map(e => `  • ${e.from}: ${e.summary}`).join("\n")}

🟡 Important (${important.length}):
${important.map(e => `  • ${e.from}: ${e.summary}`).join("\n")}

🔵 FYI (${fyi.length}):
${fyi.map(e => `  • ${e.subject}`).join("\n")}

⚪ Auto-archived (${noise.length}): newsletters, notifications
`;
}

Build: Smart Draft Agent

async function draftReply(messageId) {
  // Get the full thread
  const message = await gmail.users.messages.get({
    userId: "me", id: messageId, format: "full",
  });

  const threadId = message.data.threadId;
  const thread = await gmail.users.threads.get({
    userId: "me", id: threadId, format: "full",
  });

  // Build conversation history
  const conversation = thread.data.messages.map(msg => {
    const headers = msg.payload.headers;
    return {
      from: headers.find(h => h.name === "From")?.value,
      date: headers.find(h => h.name === "Date")?.value,
      body: extractBody(msg.payload),
    };
  });

  // Get sender relationship context
  const senderEmail = extractEmail(conversation[0].from);
  const pastEmails = await searchPastEmails(senderEmail, 10);
  const contactInfo = await getCRMInfo(senderEmail);

  // Check calendar for scheduling context
  const calendar = await getUpcomingEvents(7);

  // Load user's writing style
  const writingStyle = await getWritingStyle();

  const response = await anthropic.messages.create({
    model: "claude-sonnet-4-20250514",
    max_tokens: 1000,
    system: `You draft email replies matching this person's style:
${writingStyle}

Rules:
- Match their typical tone (formal/casual based on relationship)
- Keep replies concise unless the topic needs detail
- Include specific references to the email content
- Never make commitments about dates/times without calendar check
- If scheduling, suggest times from the available slots below
- Sign off the way they typically do`,
    messages: [{
      role: "user",
      content: `Draft a reply to this email thread.

Thread:
${conversation.map(c =>
  `From: ${c.from}\nDate: ${c.date}\n${c.body}`
).join("\n---\n")}

Relationship context:
${contactInfo ? `Company: ${contactInfo.company}, Role: ${contactInfo.role}` : "No CRM data"}

Past email tone: ${pastEmails.length > 0
  ? analyzeTone(pastEmails)
  : "No history — use professional-friendly tone"}

Available calendar slots (next 7 days):
${calendar.availableSlots.map(s =>
  `${s.day}: ${s.times.join(", ")}`
).join("\n")}

Draft the reply. Just the body text, no subject line.`
    }],
  });

  // Create draft in Gmail
  const draft = await gmail.users.drafts.create({
    userId: "me",
    requestBody: {
      message: {
        threadId,
        raw: createRawEmail({
          to: extractEmail(conversation.at(-1).from),
          subject: `Re: ${getSubject(message)}`,
          body: response.content[0].text,
          inReplyTo: message.data.id,
        }),
      },
    },
  });

  return {
    draftId: draft.data.id,
    preview: response.content[0].text,
  };
}
⚠️ NEVER auto-send

Always create drafts, not sent emails. The human reviews and sends. This is non-negotiable. One bad auto-sent email to a client can damage a relationship that took years to build. Draft → Review → Send. Always.

Build: Follow-up Tracker

async function checkFollowUps() {
  // Find sent emails with no reply
  const sentMessages = await gmail.users.messages.list({
    userId: "me",
    q: "in:sent after:" + daysAgo(14),
    maxResults: 100,
  });

  const needsFollowUp = [];

  for (const msg of sentMessages.data.messages || []) {
    const message = await gmail.users.messages.get({
      userId: "me", id: msg.id, format: "metadata",
      metadataHeaders: ["To", "Subject", "Date", "Message-ID"],
    });

    const headers = message.data.payload.headers;
    const to = headers.find(h => h.name === "To")?.value;
    const subject = headers.find(h => h.name === "Subject")?.value;
    const sentDate = new Date(headers.find(h => h.name === "Date")?.value);
    const daysSinceSent = (Date.now() - sentDate) / (1000 * 60 * 60 * 24);

    // Check if there's a reply in the thread
    const thread = await gmail.users.threads.get({
      userId: "me", id: message.data.threadId, format: "metadata",
    });

    const hasReply = thread.data.messages.some(m => {
      const from = m.payload.headers.find(h => h.name === "From")?.value;
      const msgDate = new Date(parseInt(m.internalDate));
      return from?.includes(extractEmail(to)) && msgDate > sentDate;
    });

    if (!hasReply && daysSinceSent >= 3) {
      needsFollowUp.push({
        to,
        subject,
        daysSinceSent: Math.round(daysSinceSent),
        threadId: message.data.threadId,
        messageId: msg.id,
      });
    }
  }

  // Generate follow-up drafts for emails > 5 days old
  for (const email of needsFollowUp.filter(e => e.daysSinceSent >= 5)) {
    await draftFollowUp(email);
  }

  return needsFollowUp;
}

async function draftFollowUp(email) {
  const response = await anthropic.messages.create({
    model: "claude-sonnet-4-20250514",
    max_tokens: 300,
    messages: [{
      role: "user",
      content: `Write a brief, friendly follow-up email.

Original subject: ${email.subject}
Sent to: ${email.to}
Days since sent: ${email.daysSinceSent}

Rules:
- Keep it short (2-3 sentences)
- Don't be passive-aggressive
- Reference the original topic naturally
- Suggest a specific next step
- Tone: friendly, professional, not pushy`
    }],
  });

  await gmail.users.drafts.create({
    userId: "me",
    requestBody: {
      message: {
        threadId: email.threadId,
        raw: createRawEmail({
          to: email.to,
          subject: `Re: ${email.subject}`,
          body: response.content[0].text,
        }),
      },
    },
  });
}

Build: Action Item Extractor

async function extractActionItems(messageId) {
  const message = await gmail.users.messages.get({
    userId: "me", id: messageId, format: "full",
  });

  const body = extractBody(message.data.payload);
  const from = message.data.payload.headers
    .find(h => h.name === "From")?.value;

  const response = await anthropic.messages.create({
    model: "claude-sonnet-4-20250514",
    max_tokens: 500,
    messages: [{
      role: "user",
      content: `Extract action items from this email. Return JSON:
{
  "action_items": [
    {
      "task": "description of what needs to be done",
      "assignee": "me|them|unclear",
      "deadline": "ISO date or null",
      "priority": "high|medium|low",
      "context": "relevant quote from email"
    }
  ],
  "decisions_made": ["list of decisions mentioned"],
  "questions_asked": ["list of questions needing answers"]
}

Only extract REAL action items — things someone committed to or
was asked to do. Don't invent tasks.

From: ${from}
Email: ${body}`
    }],
  });

  const extracted = JSON.parse(response.content[0].text);

  // Create tasks in your project management tool
  for (const item of extracted.action_items) {
    if (item.assignee === "me") {
      await createTask({
        title: item.task,
        deadline: item.deadline,
        priority: item.priority,
        source: `Email from ${from}`,
        link: getEmailLink(messageId),
      });
    }
  }

  return extracted;
}

Production System Prompt

const EMAIL_AGENT_PROMPT = `You are an email management agent
for a busy professional.

## Core Philosophy
You REDUCE email burden, not create more of it. Every action
should save the user time. If in doubt, flag for review rather
than act.

## Triage Rules
URGENT: From direct reports, manager, key clients. Contains
  words like "asap", "today", "critical", deadlines within 24h.
IMPORTANT: Requires a thoughtful reply. From known contacts.
  Has action items or decisions needed this week.
FYI: Updates, reports, newsletters the user has read before.
  CC'd emails where action isn't needed.
NOISE: Marketing, automated notifications, social media
  digests, promotional emails. Auto-archive these.

## Draft Rules
1. Match the user's writing style EXACTLY
2. Mirror the formality level of the incoming email
3. Keep replies 50% shorter than the original email
4. Never commit to dates/times without calendar verification
5. Never agree to anything financial without user approval
6. Include one clear next step or CTA
7. When declining, be gracious but clear

## Safety Rules (NON-NEGOTIABLE)
- NEVER send an email automatically. Always create DRAFTS
- NEVER share confidential information across contexts
- NEVER reply to emails that look like phishing
- Flag suspicious emails for manual review
- If an email involves legal, financial, or HR matters,
  flag for the user without drafting a reply
- Never forward emails to anyone without explicit instruction

## Learning
Track which drafts get edited vs sent as-is.
Note: heavily edited = style mismatch, adjust.
Note: sent as-is = good match, reinforce pattern.
`;

Want the complete email agent template?

The AI Employee Playbook includes ready-to-deploy email agents with Gmail API setup, triage rules, and draft generation — plus 12 other agent templates.

Get the Playbook — €29

Tool Comparison: 8 Email AI Tools

Tool Best For Price Custom Logic
Gemini in Gmail Quick summaries, basic drafts $20/mo (Workspace) ❌ None
Superhuman AI Speed + AI drafts for power users $30/mo ❌ Limited
Shortwave AI-first email client, auto-triage Free / $14/mo ⚠️ Some
Sanebox Smart inbox filtering $7/mo ❌ None
Spark AI email writing + team inbox Free / $8/mo ❌ Limited
Flowrite / Missive Template-based AI replies $5-15/mo ⚠️ Some
n8n + Gmail Workflow automation Free (self-host) ✅ Full
Custom Agent (this guide) Full control, learns your style ~$5-15/mo (API) ✅ Full

Our recommendation: Try Shortwave if you want an AI-native email client that just works. Use Superhuman if speed is everything. Build custom when you need your agent to integrate with your CRM, project management, and calendar — or when you want it to truly learn your style.

Build Your Email Agent in 45 Minutes

Step 1 (10 min)

Set Up Gmail API Access

Go to Google Cloud Console. Enable the Gmail API. Create OAuth 2.0 credentials. Download credentials.json. Run the auth flow to get a token. You need scopes: gmail.readonly, gmail.modify, gmail.compose.

Step 2 (10 min)

Build the Triage Pipeline

npm install googleapis @anthropic-ai/sdk. Copy the triage code from above. Run it once to classify your unread emails. Review the results — tweak the classification prompt based on your priorities.

Step 3 (10 min)

Add Draft Generation

Copy the smart draft code. Run it on one email that needs a reply. Review the draft in Gmail. Edit if needed. The key is getting your writing style prompt right — include 3-5 examples of your actual sent emails.

Step 4 (10 min)

Schedule It

Run triage every 30 minutes via cron. Run follow-up checks daily at 9 AM. Send yourself a morning digest via email or Slack. Use node-cron or GitHub Actions for scheduling.

Step 5 (5 min)

Train Your Style

Pull your last 50 sent emails. Feed them to Claude with: "Analyze this person's email writing style. Note: greeting format, sign-off, sentence length, formality level, use of emoji, typical response length." Save this as your style profile.

Email Agent Safety Rules (Non-Negotiable)

🔒 These rules are absolute

Email is the highest-stakes AI agent domain. One wrong auto-sent email can damage client relationships, violate compliance, or leak confidential data. These rules are non-negotiable:

  1. Never auto-send. Always create drafts. Human reviews and hits send.
  2. Never reply to phishing. Flag suspicious emails for manual review.
  3. Never commit to money, dates, or contracts without explicit user approval.
  4. Never forward or CC without explicit instruction.
  5. Log everything. Every draft created, every email triaged, every action taken. You need an audit trail.
  6. Rate limit drafts. Max 20 drafts per hour. If the agent is creating more, something is wrong.
  7. Separate contexts. Work email agent doesn't access personal email data and vice versa.

7 Mistakes That Kill Email Agent Trust

Mistake 1

Generic, robotic replies

"Thank you for your email. I will review and get back to you shortly." Nobody believes a human wrote that. Train your agent on YOUR actual sent emails — your greeting style, your sentence patterns, your sign-offs.

Mistake 2

Ignoring the thread context

If someone references "the issue we discussed last week" and your agent drafts a reply without knowing what that issue was, it'll be obviously AI-generated. Always include the full thread AND past emails with that person.

Mistake 3

Over-triaging (too aggressive with auto-archive)

If your agent archives an important email from a new sender, you'll miss it. Start conservative: only auto-archive obvious noise (newsletters, notifications). Gradually expand as you trust the classification.

Mistake 4

No writing style training

Your email agent should be indistinguishable from you. That means it needs to know: Do you use "Hi" or "Hey"? Do you use exclamation marks? How long are your typical replies? Do you use bullet points? Feed it 50+ examples.

Mistake 5

Drafting replies to emails that need thinking

Not every email should get a quick reply. Strategic emails, difficult conversations, and sensitive topics need human thought. Your agent should recognize these and flag them: "This looks like it needs your personal attention."

Mistake 6

No learning loop

Track which drafts you send as-is vs heavily edit vs delete. After 100 drafts, you have data to improve: "Drafts to VCs get edited 80% of the time — my agent is too casual for that context." Without tracking, the agent never improves.

Mistake 7

Forgetting about mobile

Your email agent creates drafts in Gmail. But if you check email on your phone, you might not see the AI-created drafts in the Drafts folder. Set up notifications: "3 drafts ready for review" via Slack or a push notification.

Take back your inbox

The AI Employee Playbook includes the complete email agent with Gmail API setup, style training, and safety rules — plus 12 other production-ready agents.

Get the Playbook — €29

What's Next

Start with triage only — classify and label your emails. Get comfortable with the accuracy. Then add draft generation for your most common reply types ("meeting scheduling", "quick questions", "status updates"). Finally, add follow-up tracking and action item extraction.

The goal isn't zero-email. It's zero wasted time on email. Your agent handles the processing. You handle the thinking. Together, 2.5 hours becomes 30 minutes — and you never miss a follow-up again.

Want the complete agent-building system?

The AI Employee Playbook covers the 3-file framework, memory systems, autonomy rules, and real production examples.

Get the Playbook — €29