Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Email infrastructure for AI agents. Create accounts, send/receive emails, manage webhooks, and check karma balance via the AgentMail API.
.claude/skills/sickn33-agentmail/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 131% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 48% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 82% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 92% | 0% |
AgentMail gives AI agents real email addresses (@theagentmail.net) with a REST API. Agents can send and receive email, sign up for services (GitHub, AWS, Slack, etc.), and get verification codes. A karma system prevents spam and keeps the shared domain's reputation high.
Base URL: https://api.theagentmail.net
All requests require Authorization: Bearer am_... header (API key from dashboard).
bashcurl -X POST https://api.theagentmail.net/v1/accounts \ -H "Authorization: Bearer am_..." \ -H "Content-Type: application/json" \ -d '{"address": "my-agent@theagentmail.net"}'
Response: {"data": {"id": "...", "address": "my-agent@theagentmail.net", "displayName": null, "createdAt": 123}}
bashcurl -X POST https://api.theagentmail.net/v1/accounts/{accountId}/messages \ -H "Authorization: Bearer am_..." \ -H "Content-Type: application/json" \ -d '{ "to": ["recipient@example.com"], "subject": "Hello from my agent", "text": "Plain text body", "html": "<p>Optional HTML body</p>" }'
Optional fields: cc, bcc (string arrays), inReplyTo, references (strings for threading), attachments (array of {filename, contentType, content} where content is base64).
bash# List messages curl https://api.theagentmail.net/v1/accounts/{accountId}/messages \ -H "Authorization: Bearer am_..." # Get full message (with body and attachments) curl https://api.theagentmail.net/v1/accounts/{accountId}/messages/{messageId} \ -H "Authorization: Bearer am_..."
bashcurl https://api.theagentmail.net/v1/karma \ -H "Authorization: Bearer am_..."
Response: {"data": {"balance": 90, "events": [...]}}
bashcurl -X POST https://api.theagentmail.net/v1/accounts/{accountId}/webhooks \ -H "Authorization: Bearer am_..." \ -H "Content-Type: application/json" \ -d '{"url": "https://my-agent.example.com/inbox"}'
Webhook deliveries include two security headers:
X-AgentMail-Signature -- HMAC-SHA256 hex digest of the request body, signed with the webhook secretX-AgentMail-Timestamp -- millisecond timestamp of when the delivery was sentVerify the signature and reject requests with timestamps older than 5 minutes to prevent replay attacks:
typescriptimport { createHmac } from "crypto"; const verifyWebhook = (body: string, signature: string, timestamp: string, secret: string) => { if (Date.now() - Number(timestamp) > 5 * 60 * 1000) return false; return createHmac("sha256", secret).update(body).digest("hex") === signature; };
bashcurl https://api.theagentmail.net/v1/accounts/{accountId}/messages/{messageId}/attachments/{attachmentId} \ -H "Authorization: Bearer am_..."
Returns {"data": {"url": "https://signed-download-url..."}}.
| Method | Path | Description | Karma | |--------|------|-------------|-------| | POST | /v1/accounts | Create email account | -10 | | GET | /v1/accounts | List all accounts | | | GET | /v1/accounts/:id | Get account details | | | DELETE | /v1/accounts/:id | Delete account | +10 | | POST | /v1/accounts/:id/messages | Send email | -1 | | GET | /v1/accounts/:id/messages | List messages | | | GET | /v1/accounts/:id/messages/:msgId | Get full message | | | GET | /v1/accounts/:id/messages/:msgId/attachments/:attId | Get attachment URL | | | POST | /v1/accounts/:id/webhooks | Register webhook | | | GET | /v1/accounts/:id/webhooks | List webhooks | | | DELETE | /v1/accounts/:id/webhooks/:whId | Delete webhook | | | GET | /v1/karma | Get balance + events | |
Every action has a karma cost or reward:
| Event | Karma | Why | |---|---|---| | money_paid | +100 | Purchase credits | | email_received | +2 | Someone replied from a trusted domain | | account_deleted | +10 | Karma refunded when you delete an address | | email_sent | -1 | Sending costs karma | | account_created | -10 | Creating addresses costs karma |
Important rules:
When karma reaches 0, sends and account creation return HTTP 402. Always check balance before operations that cost karma.
typescriptimport { createClient } from "@agentmail/sdk"; const mail = createClient({ apiKey: "am_..." }); // Create account const account = await mail.accounts.create({ address: "my-agent@theagentmail.net", }); // Send email await mail.messages.send(account.id, { to: ["human@example.com"], subject: "Hello", text: "Sent by an AI agent.", }); // Read inbox const messages = await mail.messages.list(account.id); const detail = await mail.messages.get(account.id, messages[0].id); // Attachments const att = await mail.attachments.getUrl(accountId, messageId, attachmentId); // att.url is a signed download URL // Webhooks await mail.webhooks.create(account.id, { url: "https://my-agent.example.com/inbox", }); // Karma const karma = await mail.karma.getBalance(); console.log(karma.balance);
typescriptimport { AgentMailError } from "@agentmail/sdk"; try { await mail.messages.send(accountId, { to: ["a@b.com"], subject: "Hi", text: "Hey" }); } catch (e) { if (e instanceof AgentMailError) { console.log(e.status); // 402, 404, 401, etc. console.log(e.code); // "INSUFFICIENT_KARMA", "NOT_FOUND", etc. console.log(e.message); } }
typescriptconst account = await mail.accounts.create({ address: "signup-bot@theagentmail.net", }); // Use the address to sign up (browser automation, API, etc.) // Poll for verification email for (let i = 0; i < 30; i++) { const messages = await mail.messages.list(account.id); const verification = messages.find(m => m.subject.toLowerCase().includes("verify") || m.subject.toLowerCase().includes("confirm") ); if (verification) { const detail = await mail.messages.get(account.id, verification.id); // Parse verification link/code from detail.bodyText or detail.bodyHtml break; } await new Promise(r => setTimeout(r, 2000)); }
typescriptconst sent = await mail.messages.send(account.id, { to: ["human@company.com"], subject: "Question about order #12345", text: "Can you check the status?", }); for (let i = 0; i < 60; i++) { const messages = await mail.messages.list(account.id); const reply = messages.find(m => m.direction === "inbound" && m.timestamp > sent.timestamp ); if (reply) { const detail = await mail.messages.get(account.id, reply.id); // Process reply break; } await new Promise(r => setTimeout(r, 5000)); }
typescripttype Account = { id: string; address: string; displayName: string | null; createdAt: number }; type Message = { id: string; from: string; to: string[]; subject: string; direction: "inbound" | "outbound"; status: string; timestamp: number }; type MessageDetail = Message & { cc: string[] | null; bcc: string[] | null; bodyText: string | null; bodyHtml: string | null; inReplyTo: string | null; references: string | null; attachments: AttachmentMeta[] }; type AttachmentMeta = { id: string; filename: string; contentType: string; size: number }; type KarmaBalance = { balance: number; events: KarmaEvent[] }; type KarmaEvent = { id: string; type: string; amount: number; timestamp: number; metadata?: Record<string, unknown> };
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 9,024 | 11,289 | +25% | 1 | 1 | 0% | 1,933 | 4,467 | +131% | 0 | 0 | — |
case-02 | fail→pass | 17,869 | 10,309 | -42% | 1 | 1 | 0% | 2,918 | 4,320 | +48% | 0 | 0 | — |
case-03 | fail→pass | 15,832 | 11,760 | -26% | 1 | 1 | 0% | 2,848 | 5,303 | +86% | 0 | 0 | — |
case-04 | fail→pass | 18,043 | 2,216 | -88% | 1 | 1 | 0% | 1,612 | 2,932 | +82% | 0 | 0 | — |
case-05 | fail→pass | 9,141 | 2,582 | -72% | 1 | 1 | 0% | 1,566 | 3,002 | +92% | 0 | 0 | — |
case-06 | fail→pass | 16,230 | 4,152 | -74% | 1 | 1 | 0% | 2,386 | 3,274 | +37% | 0 | 0 | — |
case-07 | pass→pass | 10,725 | 3,963 | -63% | 1 | 1 | 0% | 2,015 | 3,011 | +49% | 0 | 0 | — |
case-08 | pass→pass | 12,693 | 6,073 | -52% | 1 | 1 | 0% | 2,033 | 3,635 | +79% | 0 | 0 | — |
case-09 | fail→pass | 4,679 | 1,698 | -64% | 1 | 1 | 0% | 833 | 2,889 | +247% | 0 | 0 | — |
case-10 | fail→pass | 8,334 | 2,349 | -72% | 1 | 1 | 0% | 1,565 | 3,027 | +93% | 0 | 0 | — |
case-11 | pass→pass | 8,002 | 4,194 | -48% | 1 | 1 | 0% | 1,584 | 3,369 | +113% | 0 | 0 | — |
case-12 | pass→pass | 13,667 | 1,951 | -86% | 1 | 1 | 0% | 1,921 | 2,813 | +46% | 0 | 0 | — |
case-13 | pass→pass | 7,954 | 5,182 | -35% | 1 | 1 | 0% | 1,482 | 3,696 | +149% | 0 | 0 | — |
case-14 | fail→pass | 8,397 | 5,921 | -29% | 1 | 1 | 0% | 1,643 | 3,418 | +108% | 0 | 0 | — |
case-15 | fail→pass | 9,268 | 2,107 | -77% | 1 | 1 | 0% | 1,925 | 2,899 | +51% | 0 | 0 | — |
case-16 | fail→pass | 3,740 | 3,230 | -14% | 1 | 1 | 0% | 792 | 2,859 | +261% | 0 | 0 | — |
case-17 | pass→pass | 5,662 | 2,688 | -53% | 1 | 1 | 0% | 1,246 | 2,988 | +140% | 0 | 0 | — |
case-18 | fail→pass | 6,535 | 1,922 | -71% | 1 | 1 | 0% | 1,316 | 2,852 | +117% | 0 | 0 | — |
case-19 | fail→pass | 8,431 | 3,216 | -62% | 1 | 1 | 0% | 1,805 | 3,117 | +73% | 0 | 0 | — |
case-20 | pass→pass | 17,023 | 9,646 | -43% | 1 | 1 | 0% | 3,459 | 4,465 | +29% | 0 | 0 | — |
case-21 | pass→pass | 14,526 | 9,725 | -33% | 1 | 1 | 0% | 2,815 | 4,414 | +57% | 0 | 0 | — |
case-22 | pass→pass | 6,717 | 5,334 | -21% | 1 | 1 | 0% | 1,457 | 3,643 | +150% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +59 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.