agentmail-sdk
Comprehensive guide to the AgentMail Python and TypeScript SDKs. Use when building AI agents that need their own email inboxes, sending or receiving emails programmatically, managing threads and conversations, handling attachments, creating drafts for human-in-the-loop approval, setting up real-time notifications via webhooks or WebSockets, configuring custom domains, managing allow/block lists, using pods for multi-tenant isolation, or integrating email into any AI agent workflow. Covers the full AgentMail API with code examples, best practices, and production patterns.
What this skill does
# AgentMail SDK
AgentMail is an API-first email platform built for AI agents. Unlike transactional email APIs (Resend, SendGrid) that focus on one-way sending, AgentMail provides full two-way email inboxes that agents can create, send from, receive into, and manage programmatically.
Key capabilities:
- Instant inbox creation (milliseconds, no domain setup needed)
- Two-way conversations with native thread management
- Reply extraction (`extracted_text`) strips quoted history automatically
- WebSocket and webhook support for real-time inbound
- Human-in-the-loop drafts for agent oversight
- Multi-tenant isolation with pods
- Allow/block lists for sender filtering
- IMAP and SMTP access for legacy integrations
## Installation and setup
```bash
# Python
pip install agentmail
# TypeScript / Node.js
npm install agentmail
```
Get your API key from https://console.agentmail.to/ or via the Agent sign-up API (see below).
**Python:**
```python
from agentmail import AgentMail
client = AgentMail(api_key="YOUR_API_KEY")
# Or set AGENTMAIL_API_KEY env var and omit api_key:
# client = AgentMail()
```
**TypeScript:**
```typescript
import { AgentMailClient } from "agentmail";
const client = new AgentMailClient({ apiKey: "YOUR_API_KEY" });
```
## Agent sign-up (programmatic, no console needed)
Create an account and get an API key entirely from code. No browser required.
> Requires `agentmail>=0.4.15` (Python) / `agentmail>=0.x` (TypeScript). If your installed
> SDK raises `AttributeError: 'AgentMail' object has no attribute 'agent'`, upgrade first.
```python
client = AgentMail() # no api_key needed for sign-up
response = client.agent.sign_up(
human_email="[email protected]",
username="my-agent",
)
# response.api_key -> store this securely
# response.inbox_id -> [email protected]
# response.organization_id
# Verify with OTP sent to your email
client = AgentMail(api_key=response.api_key)
client.agent.verify(otp_code="123456")
```
```typescript
const client = new AgentMailClient();
const response = await client.agent.signUp({
humanEmail: "[email protected]",
username: "my-agent",
});
// response.apiKey, response.inboxId, response.organizationId
const authedClient = new AgentMailClient({ apiKey: response.apiKey });
await authedClient.agent.verify({ otpCode: "123456" });
```
The sign-up endpoint is idempotent: calling again with the same email rotates the API key and resends the OTP.
## Inboxes
Create scalable inboxes on-demand. Each inbox has a unique email address. No domain verification needed for `@agentmail.to`.
```python
from agentmail.inboxes.types import CreateInboxRequest
# Create inbox (auto-generated address)
inbox = client.inboxes.create()
# inbox.inbox_id, inbox.email
# Create with options. All create kwargs go inside a CreateInboxRequest.
inbox = client.inboxes.create(
request=CreateInboxRequest(
username="support",
domain="yourdomain.com", # optional, defaults to agentmail.to
display_name="Support Agent",
client_id="support-v1", # idempotency key, safe to retry
),
)
# List all inboxes
inboxes = client.inboxes.list()
# Paginate: client.inboxes.list(limit=20, page_token=inboxes.next_page_token)
# Get, update, delete
inbox = client.inboxes.get(inbox_id="[email protected]")
client.inboxes.update(inbox_id="[email protected]", display_name="New Name")
client.inboxes.delete(inbox_id="[email protected]")
```
```typescript
const inbox = await client.inboxes.create({
username: "support",
domain: "yourdomain.com",
displayName: "Support Agent",
clientId: "support-v1",
});
const inboxes = await client.inboxes.list();
const fetched = await client.inboxes.get("[email protected]");
await client.inboxes.update("[email protected]", { displayName: "New Name" });
await client.inboxes.delete("[email protected]");
```
Custom domains require a paid plan. Default `@agentmail.to` inboxes are free.
## Messages
### Send
Always provide both `text` and `html` for best deliverability. Maximum 50 recipients across to + cc + bcc combined.
```python
sent = client.inboxes.messages.send(
inbox_id="[email protected]",
to="[email protected]", # string or list
subject="Hello from AgentMail",
text="Plain text body",
html="<p>HTML body</p>", # optional but recommended
cc="[email protected]", # optional, string or list
bcc="[email protected]", # optional, string or list
reply_to="[email protected]", # optional
labels=["outreach"], # optional
attachments=[{ # optional
"filename": "report.pdf",
"content": base64_content, # Base64-encoded
"content_type": "application/pdf",
}],
)
# sent.message_id, sent.thread_id
```
```typescript
const sent = await client.inboxes.messages.send("[email protected]", {
to: "[email protected]",
subject: "Hello from AgentMail",
text: "Plain text body",
html: "<p>HTML body</p>",
cc: "[email protected]",
labels: ["outreach"],
attachments: [{
filename: "report.pdf",
content: base64Content,
contentType: "application/pdf",
}],
});
```
### List and get
```python
# List messages in an inbox. Note: .list() returns MessageItem objects
# (metadata only — subject, from, labels, timestamps, etc.) with NO body
# content. To read .text / .html / .extracted_text you must fetch the full
# message with .get().
response = client.inboxes.messages.list(
inbox_id="[email protected]",
limit=10, # optional, default varies
labels=["unread"], # optional, filter by label
)
for item in response.messages:
# item is a MessageItem (metadata only). Fetch the full Message for body:
msg = client.inboxes.messages.get(
inbox_id=item.inbox_id,
message_id=item.message_id,
)
# Use extracted_text for reply content without quoted history
content = msg.extracted_text or msg.text
print(msg.subject, content)
# Paginate
while response.next_page_token:
response = client.inboxes.messages.list(
inbox_id="[email protected]",
page_token=response.next_page_token,
)
# Get a specific message
msg = client.inboxes.messages.get(
inbox_id="[email protected]",
message_id="<[email protected]>",
)
# Get raw MIME content
raw = client.inboxes.messages.get_raw(
inbox_id="[email protected]",
message_id="<[email protected]>",
)
```
```typescript
const response = await client.inboxes.messages.list("[email protected]", {
limit: 10,
labels: ["unread"],
});
const msg = await client.inboxes.messages.get(
"[email protected]",
"<[email protected]>",
);
```
**Important**: when processing inbound replies, always use `extracted_text` / `extracted_html` instead of `text` / `html`. These fields strip quoted history and signatures, giving you only the new content. This is powered by Talon reply extraction.
Also note: some email clients (Gmail, Outlook) send forwards as HTML-only. Always treat `html` as the primary content source and `text` as optional.
### Reply
Replying adds the message to the existing thread.
```python
reply = client.inboxes.messages.reply(
inbox_id="[email protected]",
message_id="<[email protected]>",
text="Thanks for your email!",
html="<p>Thanks for your email!</p>", # optional
attachments=[...], # optional
reply_all=False, # optional, defaults to False
)
```
```typescript
const reply = await client.inboxes.messages.reply(
"[email protected]",
"<[email protected]>",
{ text: "Thanks for your email!" },
);
```
### Forward
```python
client.inboxes.messages.forward(
inbox_id="[email protected]",
message_id="<[email protected]>",
to="[email protected]",
text="FYI, see below.", # optional prepended text
)
```
```typescriptRelated in Backend & APIs
jfrog
IncludedInteract with the JFrog Platform via the JFrog CLI and REST/GraphQL APIs. Use this skill when the user wants to manage Artifactory repositories, upload or download artifacts, manage builds, configure permissions, manage users and groups, work with access tokens, configure JFrog CLI servers, search artifacts, manage properties, set up replication, manage JFrog Projects, run security audits or scans, look up CVE details, query exposures scan results from JFrog Advanced Security, manage release bundles and lifecycle operations, aggregate or export platform data, or perform any JFrog Platform administration task. Also use when the user mentions jf, jfrog, artifactory, xray, distribution, evidence, apptrust, onemodel, graphql, workers, mission control, curation, advanced security, exposures, or any JFrog product name.
cupynumeric-migration-readiness
IncludedPre-migration readiness assessor for porting NumPy to cuPyNumeric. Use BEFORE substantial porting work begins when the user asks whether code will scale on GPU, whether they should migrate to cuPyNumeric, which NumPy patterns transfer cleanly, what must be refactored before porting, or mentions pre-port assessment, scaling analysis, or refactor planning. Inspect the user's source code, look up NumPy usage, cross-reference the cuPyNumeric API support manifest, and distinguish distributed-scaling-friendly patterns from blockers such as unsupported APIs, scalar synchronization, host round-trips, Python/object-heavy control flow, shape/data-dependent branching, and in-place mutation hazards. Produce a verdict of READY, LIGHT REFACTOR, SIGNIFICANT REFACTOR, or NOT RECOMMENDED, with concrete refactor pointers.
alibabacloud-data-agent-skill
IncludedInvoke Alibaba Cloud Apsara Data Agent for Analytics via CLI to perform natural language-driven data analysis on enterprise databases. Data Agent for Analytics is an intelligent data analysis agent developed by Alibaba Cloud Database team for enterprise users. It automatically completes requirement analysis, data understanding, analysis insights, and report generation based on natural language descriptions. This tool supports: discovering data resources (instances/databases/tables) managed in DMS, initiating query or deep analysis sessions, real-time progress tracking, and retrieving analysis conclusions and generated reports. Use this Skill when users need to query databases, analyze data trends, generate data reports, ask questions in natural language, or mention "Data Agent", "data analysis", "database query", "SQL analysis", "data insights".
token-optimizer
IncludedReduce OpenClaw token usage and API costs through smart model routing, heartbeat optimization, budget tracking, and native 2026.2.15 features (session pruning, bootstrap size limits, cache TTL alignment). Use when token costs are high, API rate limits are being hit, or hosting multiple agents at scale. The 4 executable scripts (context_optimizer, model_router, heartbeat_optimizer, token_tracker) are local-only — no network requests, no subprocess calls, no system modifications. Reference files (PROVIDERS.md, config-patches.json) document optional multi-provider strategies that require external API keys and network access if you choose to use them. See SECURITY.md for full breakdown.
resend-cli
IncludedUse this skill when the task is specifically about operating Resend from an AI agent, terminal session, or CI job via the official resend CLI: installing/authenticating the CLI, sending/listing/updating/cancelling emails, batch sends, domains and DNS, webhooks and local listeners, inbound receiving, contacts, topics, segments, broadcasts, templates, API keys, profiles, or debugging Resend CLI/API failures. Trigger on mentions of Resend CLI, `resend`, `resend doctor`, `resend emails send`, `resend domains`, `resend webhooks listen`, `resend emails receiving`, or agent-friendly terminal automation.
alibabacloud-odps-maxframe-coding
IncludedUse this skill for MaxFrame SDK development and documentation navigation on Alibaba Cloud MaxCompute (ODPS). Helps answer MaxFrame API, concept, official example, and supported pandas API questions; create data processing programs; read/write MaxCompute tables; debug jobs (remote or local); and build custom DPE runtime images. Trigger when users mention MaxFrame, MaxCompute with MaxFrame, ODPS table processing, DPE runtime, MaxFrame docs/examples, DataFrame/Tensor operations, or GPU runtime setup. Works for both English and Chinese queries about Alibaba Cloud data processing with MaxFrame.