
how to build an email agent with the claude agent sdk
Build an AI email agent using Anthropic's Claude Agent SDK with custom tools like fetchInbox and sendReply, plus a faster path using agent-native email.
A Claude Agent SDK email agent is an autonomous program built on Anthropic's SDK that can monitor an inbox, triage incoming messages, compose replies, and take actions based on email content, all without human intervention. Building one requires defining custom tools like fetchInbox, searchEmails, and sendReply, then connecting them to an email backend where the agent can operate independently.
The SDK gives you the scaffolding. But the email part? That's where most people get stuck.
What the Claude Agent SDK actually gives you#
Anthropic released the Claude Agent SDK to make it easier to build agents that use tools, run in loops, and make decisions autonomously. You define tools (functions the agent can call), hook them into the agent lifecycle, and let Claude figure out when to call what.
For an email agent, the flow looks like this: the agent receives a trigger (a new email, a scheduled check, a user prompt), decides what to do (read, reply, forward, escalate), calls the right tool, and loops back to wait for the next event.
The SDK handles the reasoning layer well. It ships with built-in tools for web search, web fetch, code execution, bash, and text editing. What it doesn't ship with is email. There's no fetchInbox tool in the box. No sendReply. No searchEmails. You build those yourself.
That's not a limitation, it's the design. The SDK is a general agent framework, not an email client. Your job is to wire it up to whatever email backend your agent needs.
The three tools every email agent needs#
At minimum, your Claude email agent needs three custom tools:
fetchInbox pulls new messages from the mailbox. It should return structured data: sender, subject, body, timestamp, and any attachments. The agent uses this to decide what needs attention.
searchEmails lets the agent find specific messages by keyword, sender, date range, or thread. Without this, the agent can only react to whatever's on top. With it, the agent can answer questions like "did we get a reply from Acme Corp last week?"
sendReply composes and sends a response. You'll want to include thread context so the agent can maintain conversation continuity instead of sending disjointed one-offs.
Here's the skeleton in the SDK's tool format:
const fetchInboxTool = {
name: "fetchInbox",
description: "Fetch unread emails from the agent's inbox",
input_schema: {
type: "object",
properties: {
limit: { type: "number", description: "Max emails to return" },
unreadOnly: { type: "boolean", description: "Only unread messages" }
}
},
handler: async ({ limit = 10, unreadOnly = true }) => {
// Your email backend call goes here
const emails = await emailClient.getMessages({ limit, unreadOnly });
return emails;
}
};
The pattern repeats for searchEmails and sendReply. Define the schema, write the handler, register the tool with the agent. Claude handles the reasoning about when to use each tool. You handle how the tool actually talks to the email system.
The part nobody talks about: where does the inbox come from?#
This is where tutorials get hand-wavy. They show you how to define fetchInbox but skip over what emailClient actually connects to. You have a few options, and they come with different tradeoffs.
Option 1: connect to Gmail via MCP or OAuth#
Most examples wire Claude up to a personal Gmail account through OAuth or a Gmail MCP server. Composio has a popular Gmail MCP integration. It works for demos. For production agents, it creates real problems.
OAuth tokens expire. When they do, your autonomous agent stops functioning until a human re-authenticates. If you're running the agent overnight or over a weekend, that's a gap. Gmail also rate-limits API access, and those limits weren't designed for agents that poll every 30 seconds.
The bigger issue is identity. Your agent is sending from your email address. If the agent makes a mistake, misfires a reply, or gets exploited through a prompt injection attack hidden in an email body, it's your name and reputation on the line.
Option 2: set up your own mail server#
You could run Postfix, configure DNS records, set up SPF, DKIM, and DMARC, manage TLS certificates, handle bounce processing, and maintain deliverability. This gives you full control. It also takes days to set up and ongoing effort to maintain. For a side project or prototype, that's a lot of overhead before your agent sends its first message.
Option 3: use agent-native email infrastructure#
This is what LobsterMail was built for. Instead of connecting your agent to a human's inbox or running your own server, the agent provisions its own mailbox programmatically. No OAuth flow, no human sign-up, no DNS configuration.
import { LobsterMail } from '@lobsterkit/lobstermail';
const lm = await LobsterMail.create();
const inbox = await lm.createSmartInbox({ name: 'My Email Agent' });
console.log(inbox.address); // my-email-agent@lobstermail.ai
That inbox object becomes the backend for your fetchInbox and sendReply tools. The agent gets its own address, its own identity, and its own send/receive capability without sharing a human's credentials.
Wiring LobsterMail into your Claude Agent SDK tools#
Here's how the custom tools look when backed by LobsterMail:
import { LobsterMail } from '@lobsterkit/lobstermail';
const lm = await LobsterMail.create();
const inbox = await lm.createSmartInbox({ name: 'Support Agent' });
const fetchInboxTool = {
name: "fetchInbox",
description: "Fetch emails from the agent's dedicated inbox",
input_schema: {
type: "object",
properties: {
limit: { type: "number", description: "Max emails to return" }
}
},
handler: async ({ limit = 10 }) => {
const emails = await inbox.receive({ limit });
return emails.map(e => ({
id: e.id,
from: e.from,
subject: e.subject,
body: e.text,
receivedAt: e.receivedAt,
injectionScore: e.security?.injectionScore
}));
}
};
const sendReplyTool = {
name: "sendReply",
description: "Send a reply email from the agent's inbox",
input_schema: {
type: "object",
properties: {
to: { type: "string", description: "Recipient email" },
subject: { type: "string", description: "Email subject" },
body: { type: "string", description: "Email body text" }
},
required: ["to", "subject", "body"]
},
handler: async ({ to, subject, body }) => {
return await inbox.send({ to, subject, text: body });
}
};
Notice the injectionScore field in the fetch handler. LobsterMail scores every incoming email for prompt injection risk, which matters when your agent is autonomously reading and acting on email content. A high injection score means someone might be trying to manipulate your agent through a crafted email body. Your agent can use that score to decide whether to process, flag, or ignore a message.
Hosting and monitoring your email agent#
Anthropic's docs describe several hosting patterns for agents built with the SDK. For an email agent, the most practical setup is a long-running process that polls for new messages on an interval, or a webhook-triggered function that activates when mail arrives.
The polling approach is simpler to start with:
async function runEmailAgent() {
while (true) {
const emails = await fetchInboxTool.handler({ limit: 5 });
if (emails.length > 0) {
// Pass emails to Claude for triage and response
await agent.processEmails(emails);
}
await sleep(30_000); // Check every 30 seconds
}
}
For production, webhooks are more efficient. LobsterMail supports webhook notifications on email arrival, so your agent only wakes up when there's something to process.
The SDK also provides lifecycle hooks (PreToolUse, PostToolUse, Stop) that let you add logging, validation, and safety checks. For an email agent, a PreToolUse hook on sendReply is a good place to enforce rate limits or require human approval for certain types of outbound messages.
Running multiple email agents without collisions#
If you need several Claude agents handling different tasks (support triage, order confirmations, newsletter responses), each agent should have its own inbox. Sharing a single inbox across agents creates race conditions where two agents try to reply to the same message, or worse, one agent processes and archives a message before the other sees it.
With LobsterMail, each agent provisions its own address. support-agent@lobstermail.ai, orders-agent@lobstermail.ai, newsletter-agent@lobstermail.ai. No shared credentials, no collision risk, no identity confusion. The free tier covers your first inbox with 1,000 emails per month. The Builder plan ($9/mo) gives you up to 10 inboxes and 5,000 emails per month.
The faster path#
If you want to skip the SDK tool-definition step entirely, LobsterMail also works as an MCP server. Add one line to your Claude agent's MCP config and your agent gets email tools (create inbox, send, receive, search) without writing any custom tool handlers. The MCP server docs have the setup details.
If you want your agent to handle email on its own, . Paste the instructions and your agent takes it from there.
Frequently asked questions
What is the Claude Agent SDK used for?
The Claude Agent SDK is Anthropic's framework for building autonomous AI agents that use tools, make decisions in loops, and execute multi-step workflows. It provides the reasoning layer while you supply domain-specific tools like email, database access, or API integrations.
Does Anthropic include email tools in the Claude Agent SDK?
No. The SDK ships with built-in tools for web search, web fetch, bash, code execution, and text editing. Email tools like fetchInbox, searchEmails, and sendReply need to be defined as custom tools connected to your chosen email backend.
Can Claude autonomously respond to emails?
Yes. When you define email tools and register them with a Claude agent, the agent can read incoming messages, decide how to respond based on content and context, compose replies, and send them without human intervention. Adding safety hooks like rate limits or human-approval gates for sensitive replies is recommended.
What is the risk of using a personal Gmail inbox for an AI email agent?
OAuth tokens expire and require human re-authentication, which breaks autonomous operation. The agent also sends from your personal address, so any mistakes or prompt injection exploits carry your identity. Gmail's API rate limits weren't designed for agent polling patterns either.
How do I give each Claude agent its own dedicated email address?
Use an agent-native email provider like LobsterMail. The agent calls createSmartInbox({ name: 'My Agent' }) and gets an address like my-agent@lobstermail.ai in one line of code. No DNS setup or human sign-up required.
What is MCP and how does it work with the Claude Agent SDK?
MCP (Model Context Protocol) is a standard for giving AI agents access to external tools and data sources. Instead of writing custom tool handlers, you can connect an MCP server (like LobsterMail's) to your Claude agent and it gets pre-built tools for email, databases, or other services automatically.
How does natural language email search work in a Claude email agent?
You define a searchEmails tool that accepts parameters like keywords, sender, and date range. Claude translates the user's natural language query ("find last week's email from the shipping company") into the right tool parameters and calls the search function.
How do I run multiple Claude email agents without inbox collisions?
Give each agent its own inbox. Sharing an inbox across agents causes race conditions where multiple agents try to process or reply to the same message. LobsterMail lets each agent provision a separate address programmatically.
What rate limits should I know about when Claude agents send email at scale?
Rate limits depend on your email provider. LobsterMail's free tier allows 1,000 emails per month. The Builder plan ($9/mo) supports 500 emails per day and 5,000 per month. Gmail's API has its own quotas that are typically lower for automated access.
How do I protect my Claude email agent from prompt injection attacks in emails?
Prompt injection in email means someone crafts a message body designed to manipulate your agent's behavior. LobsterMail scores every incoming email for injection risk. Your agent can check this score before processing and skip or flag messages with high risk. See the security docs for details.
Where can I find official Claude Agent SDK email agent examples?
Anthropic maintains a demo repository on GitHub with several agent examples. The email agent example shows the basic tool-definition pattern, though you'll need to supply your own email backend.
How do I test a Claude email agent locally before deploying?
Run the agent locally with a test inbox. LobsterMail's free tier works well for this since the agent can provision a real inbox with no setup. Send test emails to the inbox address and verify that your agent triages, replies, and logs correctly before moving to production.


