
Agentmail
Wire AgentMail inbound email events into your app with registered HTTP webhooks instead of polling.
Overview
Agentmail is an agent skill for the Build phase that documents how to register and manage AgentMail HTTP webhooks for real-time email events.
Install
npx skills add https://github.com/agentmail-to/agentmail-skills --skill agentmailWhat is this skill?
- Documents required eventTypes when creating webhooks via TypeScript or Python AgentMailClient
- Covers message.received and related event types for inbox-driven workflows
- Lists, creates, and deletes webhook endpoints against your public HTTPS URL
- Points local dev without a public URL to websockets documentation instead of webhooks
Adoption & trust: 1.7k installs on skills.sh; 15 GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
You need inbound email to trigger your backend reliably in production but are unsure how to register AgentMail webhooks with the correct required event types.
Who is it for?
Solo builders deploying a public API or worker that must process AgentMail message.received and related events on their own server.
Skip if: Local-only development without a public URL—use the skill’s websockets guidance instead of HTTP webhooks.
When should I use this skill?
Production applications with public endpoints, event-driven architectures, or when you need to process email events on your server.
What do I get? / Deliverables
After following the skill, you have a registered HTTPS webhook, know which events fire, and can list or delete endpoints from the AgentMail client.
- Registered webhook with explicit eventTypes list
- Runnable create/list/delete webhook snippets
Recommended Skills
Journey fit
Webhook registration and event handling sit in the integrations slice of building a product that receives email. AgentMail client setup for create/list/delete webhooks is third-party API integration work, not launch distribution.
How it compares
Use for server-push email events via AgentMail webhooks, not as a substitute for MCP search or generic SMTP tutorials.
Common Questions / FAQ
Who is agentmail for?
Indie developers and agent builders integrating AgentMail into SaaS or automation backends that need real-time inbox notifications over HTTP.
When should I use agentmail?
During Build integrations when you have a production public endpoint and want event-driven handling of received messages; skip webhooks for local dev without a URL.
Is agentmail safe to install?
Review the Security Audits panel on this Prism page and treat API keys and webhook URLs as secrets in your own deployment.
SKILL.md
READMESKILL.md - Agentmail
# Webhooks Webhooks provide real-time HTTP notifications when email events occur. Use webhooks when you have a public URL endpoint. ## When to Use - Production applications with public endpoints - Event-driven architectures - When you need to process events on your server For local development without a public URL, use [websockets.md](websockets.md) instead. ## Setup Register a webhook endpoint to receive events. `eventTypes` / `event_types` is **required** — you must pass the list of events the webhook should receive. ```typescript import { AgentMailClient } from "agentmail"; const client = new AgentMailClient({ apiKey: "YOUR_API_KEY" }); // Create webhook const webhook = await client.webhooks.create({ url: "https://your-server.com/webhooks", eventTypes: ["message.received"], }); // List webhooks const webhooks = await client.webhooks.list(); // Delete webhook await client.webhooks.delete(webhook.webhookId); ``` ```python from agentmail import AgentMail client = AgentMail(api_key="YOUR_API_KEY") # Create webhook webhook = client.webhooks.create( url="https://your-server.com/webhooks", event_types=["message.received"], ) # List webhooks webhooks = client.webhooks.list() # Delete webhook client.webhooks.delete(webhook_id=webhook.webhook_id) ``` ## Event Types | Event | Description | | -------------------- | ------------------------------------- | | `message.received` | New email received in inbox | | `message.sent` | Email successfully sent | | `message.delivered` | Email delivered to recipient's server | | `message.bounced` | Email failed to deliver | | `message.complained` | Recipient marked email as spam | | `message.rejected` | Email rejected before sending | | `domain.verified` | Custom domain verification completed | ## Payload Structure All webhook payloads follow this structure: ```json { "type": "event", "event_type": "message.received", "event_id": "evt_123abc", "message": { "inbox_id": "inbox_456def", "thread_id": "thd_789ghi", "message_id": "msg_123abc", "from": "Jane Doe <jane@example.com>", "to": ["Agent <agent@agentmail.to>"], "subject": "Question about my account", "text": "Full text body", "html": "<html>...</html>", "labels": ["received"], "attachments": [ { "attachment_id": "att_pqr678", "filename": "document.pdf", "content_type": "application/pdf", "size": 123456 } ], "created_at": "2023-10-27T10:00:00Z" }, "thread": {} } ``` ## Handling Webhooks Your endpoint should: 1. Return `200 OK` immediately 2. Process the payload asynchronously ### Express (TypeScript) ```typescript import express from "express"; const app = express(); app.use(express.json()); app.post("/webhooks", (req, res) => { const payload = req.body; if (payload.event_type === "message.received") { // Queue for async processing processEmail(payload.message); } res.status(200).send("OK"); // Return immediately }); ``` ### Flask (Python) ```python from flask import Flask, request app = Flask(__name__) @app.route("/webhooks", methods=["POST"]) def handle_webhook(): payload = request.json if payload["event_type"] == "message.received": # Queue for async processing process_email.delay(payload["message"]) return "OK", 200 # Return immediately ``` ## Webhook Verification Verify webhook signatures to ensure requests are from AgentMail. ### TypeScript ```typescript import crypto from "crypto"; import express from "express"; function verifySignature( payload: Buffer, signature: string, secret: string ): boolean { const expected = crypto .createHmac("sha256", secret) .update(payload) .digest("hex"); const expectedBuf = Buffer.from(expected, "hex"); const signatureBuf = Buffer.from(signature, "hex"); // timingSafeEqual thr