Agentmail
Give AI agents their own email inboxes using the AgentMail API. Use when building email agents, sending/receiving emails programmatically, managing inboxes, handling attachments, organizing with labels, creating drafts for human approval, or setting up real-time notifications via webhooks/websockets. Supports multi-tenant isolation with pods.From its SKILL.md
npx -y skills add skshadan/kage --skill agentmailAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.1 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it
AgentMail SDK
AgentMail is an API-first email platform for AI agents. Install the SDK and initialize the client.
Installation
# TypeScript/Node
npm install agentmail
# Python
pip install agentmail
Setup
import { AgentMailClient } from "agentmail";
const client = new AgentMailClient({ apiKey: "YOUR_API_KEY" });
from agentmail import AgentMail
client = AgentMail(api_key="YOUR_API_KEY")
Inboxes
Create scalable inboxes on-demand. Each inbox has a unique email address.
// Create inbox (auto-generated address)
const autoInbox = await client.inboxes.create();
// Create with custom username and domain
const customInbox = await client.inboxes.create({
username: "support",
domain: "yourdomain.com",
});
// List, get, delete
const inboxes = await client.inboxes.list();
const fetchedInbox = await client.inboxes.get({
inboxId: "[email protected]",
});
await client.inboxes.delete({ inboxId: "[email protected]" });
# Create inbox (auto-generated address)
inbox = client.inboxes.create()
# Create with custom username and domain
inbox = client.inboxes.create(username="support", domain="yourdomain.com")
# List, get, delete
inboxes = client.inboxes.list()
inbox = client.inboxes.get(inbox_id="[email protected]")
client.inboxes.delete(inbox_id="[email protected]")
Messages
Always send both text and html for best deliverability.
// Send message
await client.inboxes.messages.send({
inboxId: "[email protected]",
to: "[email protected]",
subject: "Hello",
text: "Plain text version",
html: "<p>HTML version</p>",
labels: ["outreach"],
});
// Reply to message
await client.inboxes.messages.reply({
inboxId: "[email protected]",
messageId: "msg_123",
text: "Thanks for your email!",
});
// List and get messages
const messages = await client.inboxes.messages.list({
inboxId: "[email protected]",
});
const message = await client.inboxes.messages.get({
inboxId: "[email protected]",
messageId: "msg_123",
});
// Update labels
await client.inboxes.messages.update({
inboxId: "[email protected]",
messageId: "msg_123",
addLabels: ["replied"],
removeLabels: ["unreplied"],
});
# Send message
client.inboxes.messages.send(
inbox_id="[email protected]",
to="[email protected]",
subject="Hello",
text="Plain text version",
html="<p>HTML version</p>",
labels=["outreach"]
)
# Reply to message
client.inboxes.messages.reply(
inbox_id="[email protected]",
message_id="msg_123",
text="Thanks for your email!"
)
# List and get messages
messages = client.inboxes.messages.list(inbox_id="[email protected]")
message = client.inboxes.messages.get(inbox_id="[email protected]", message_id="msg_123")
# Update labels
client.inboxes.messages.update(
inbox_id="[email protected]",
message_id="msg_123",
add_labels=["replied"],
remove_labels=["unreplied"]
)
Threads
Threads group related messages in a conversation.
// List threads (with optional label filter)
const threads = await client.inboxes.threads.list({
inboxId: "[email protected]",
labels: ["unreplied"],
});
// Get thread details
const thread = await client.inboxes.threads.get({
inboxId: "[email protected]",
threadId: "thd_123",
});
// Org-wide thread listing
const allThreads = await client.threads.list();
# List threads (with optional label filter)
threads = client.inboxes.threads.list(inbox_id="[email protected]", labels=["unreplied"])
# Get thread details
thread = client.inboxes.threads.get(inbox_id="[email protected]", thread_id="thd_123")
# Org-wide thread listing
all_threads = client.threads.list()
Attachments
Send attachments with Base64 encoding. Retrieve from messages or threads.
// Send with attachment
const content = Buffer.from(fileBytes).toString("base64");
await client.inboxes.messages.send({
inboxId: "[email protected]",
to: "[email protected]",
subject: "Report",
text: "See attached.",
attachments: [
{ content, filename: "report.pdf", contentType: "application/pdf" },
],
});
// Get attachment
const fileData = await client.inboxes.messages.getAttachment({
inboxId: "[email protected]",
messageId: "msg_123",
attachmentId: "att_456",
});
import base64
# Send with attachment
content = base64.b64encode(file_bytes).decode()
client.inboxes.messages.send(
inbox_id="[email protected]",
to="[email protected]",
subject="Report",
text="See attached.",
attachments=[{"content": content, "filename": "report.pdf", "content_type": "application/pdf"}]
)
# Get attachment
file_data = client.inboxes.messages.get_attachment(
inbox_id="[email protected]",
message_id="msg_123",
attachment_id="att_456"
)
Drafts
Create drafts for human-in-the-loop approval before sending.
// Create draft
const draft = await client.inboxes.drafts.create({
inboxId: "[email protected]",
to: "[email protected]",
subject: "Pending approval",
text: "Draft content",
});
// Send draft (converts to message)
await client.inboxes.drafts.send({
inboxId: "[email protected]",
draftId: draft.draftId,
});
# Create draft
draft = client.inboxes.drafts.create(
inbox_id="[email protected]",
to="[email protected]",
subject="Pending approval",
text="Draft content"
)
# Send draft (converts to message)
client.inboxes.drafts.send(inbox_id="[email protected]", draft_id=draft.draft_id)
Pods
Multi-tenant isolation for SaaS platforms. Each customer gets isolated inboxes.
// Create pod for a customer
const pod = await client.pods.create({ clientId: "customer_123" });
// Create inbox within pod
const inbox = await client.inboxes.create({ podId: pod.podId });
// List resources scoped to pod
const inboxes = await client.inboxes.list({ podId: pod.podId });
# Create pod for a customer
pod = client.pods.create(client_id="customer_123")
# Create inbox within pod
inbox = client.inboxes.create(pod_id=pod.pod_id)
# List resources scoped to pod
inboxes = client.inboxes.list(pod_id=pod.pod_id)
Idempotency
Use clientId for safe retries on create operations.
const inbox = await client.inboxes.create({
clientId: "unique-idempotency-key",
});
// Retrying with same clientId returns the original inbox, not a duplicate
inbox = client.inboxes.create(client_id="unique-idempotency-key")
# Retrying with same client_id returns the original inbox, not a duplicate
Real-Time Events
For real-time notifications, see the reference files:
- webhooks.md - HTTP-based notifications (requires public URL)
- websockets.md - Persistent connection (no public URL needed)
What ships with it: 2 files
12.7 KB alongside SKILL.md
references/
- webhooks.md5.3 KB
- websockets.md7.4 KB