AgentMail — Email pour agents IA
AgentMail fournit aux agents IA de vraies adresses email (@theagentmail.net) avec une API REST. Les agents peuvent envoyer et recevoir des emails, s'inscrire à des services (GitHub, AWS, Slack, etc.) et obtenir des codes de vérification. Un système de karma empêche le spam et maintient la réputation du domaine partagé.
URL de base : https://api.theagentmail.net
Quand l'utiliser
- Un agent IA a besoin d'une vraie boîte de réception/envoi pour les inscriptions, les flux de vérification ou les communications transactionnelles.
- Vous devez provisionner des comptes AgentMail, envoyer des messages, lire le contenu des boîtes de réception ou enregistrer des webhooks entrants.
- Vous devez surveiller l'utilisation du karma ou intégrer des événements email dans l'automatisation de l'agent.
Démarrage rapide
Toutes les requêtes nécessitent l'en-tête Authorization: Bearer am_... (clé API depuis le tableau de bord).
Créer un compte email (-10 karma)
curl -X POST https://api.theagentmail.net/v1/accounts \
-H "Authorization: Bearer am_..." \
-H "Content-Type: application/json" \
-d '{"address": "[email protected]"}'
Réponse : {"data": {"id": "...", "address": "[email protected]", "displayName": null, "createdAt": 123}}
Envoyer un email (-1 karma)
curl -X POST https://api.theagentmail.net/v1/accounts/{accountId}/messages \
-H "Authorization: Bearer am_..." \
-H "Content-Type: application/json" \
-d '{
"to": ["[email protected]"],
"subject": "Hello from my agent",
"text": "Plain text body",
"html": "<p>Optional HTML body</p>"
}'
Champs optionnels : cc, bcc (tableaux de chaînes), inReplyTo, references (chaînes pour le threading), attachments (tableau de {filename, contentType, content} où content est en base64).
Lire la boîte de réception
# Lister les messages
curl https://api.theagentmail.net/v1/accounts/{accountId}/messages \
-H "Authorization: Bearer am_..."
# Obtenir le message complet (avec corps et pièces jointes)
curl https://api.theagentmail.net/v1/accounts/{accountId}/messages/{messageId} \
-H "Authorization: Bearer am_..."
Vérifier le karma
curl https://api.theagentmail.net/v1/karma \
-H "Authorization: Bearer am_..."
Réponse : {"data": {"balance": 90, "events": [...]}}
Enregistrer un webhook (réception en temps réel)
curl -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"}'
Les livraisons de webhook incluent deux en-têtes de sécurité :
X-AgentMail-Signature-- condensé HMAC-SHA256 hexadécimal du corps de la requête, signé avec le secret du webhookX-AgentMail-Timestamp-- horodatage en millisecondes de l'envoi de la livraison
Vérifiez la signature et rejetez les requêtes avec un horodatage de plus de 5 minutes pour empêcher les attaques par rejeu :
import { 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;
};
Télécharger une pièce jointe
curl https://api.theagentmail.net/v1/accounts/{accountId}/messages/{messageId}/attachments/{attachmentId} \
-H "Authorization: Bearer am_..."
Retourne {"data": {"url": "https://signed-download-url..."}}.
Référence complète de l'API
| Méthode | Chemin | Description | Karma |
|---|---|---|---|
| POST | /v1/accounts | Créer un compte email | -10 |
| GET | /v1/accounts | Lister tous les comptes | |
| GET | /v1/accounts/:id | Obtenir les détails du compte | |
| DELETE | /v1/accounts/:id | Supprimer un compte | +10 |
| POST | /v1/accounts/:id/messages | Envoyer un email | -1 |
| GET | /v1/accounts/:id/messages | Lister les messages | |
| GET | /v1/accounts/:id/messages/:msgId | Obtenir le message complet | |
| GET | /v1/accounts/:id/messages/:msgId/attachments/:attId | Obtenir l'URL de la pièce jointe | |
| POST | /v1/accounts/:id/webhooks | Enregistrer un webhook | |
| GET | /v1/accounts/:id/webhooks | Lister les webhooks | |
| DELETE | /v1/accounts/:id/webhooks/:whId | Supprimer un webhook | |
| GET | /v1/karma | Obtenir le solde et les événements |
Système de karma
Chaque action a un coût ou une récompense en karma :
| Événement | Karma | Pourquoi |
|---|---|---|
money_paid | +100 | Achat de crédits |
email_received | +2 | Quelqu'un a répondu depuis un domaine de confiance |
account_deleted | +10 | Remboursement de karma lors de la suppression d'une adresse |
email_sent | -1 | L'envoi coûte du karma |
account_created | -10 | La création d'adresses coûte du karma |
Règles importantes :
- Le karma est uniquement attribué pour les emails entrants provenant de fournisseurs de confiance (Gmail, Outlook, Yahoo, iCloud, ProtonMail, Fastmail, Hey, etc.). Les emails provenant de domaines inconnus ou jetables ne rapportent pas de karma.
- Vous ne gagnez du karma qu'une fois par expéditeur jusqu'à ce que l'agent réponde. Si l'expéditeur X vous envoie 5 emails sans réponse, seul le premier rapporte du karma. Répondez à X, et le prochain email de X rapportera à nouveau du karma.
- La suppression d'un compte rembourse les 10 karmas qu'il a coûté à créer.
Lorsque le karma atteint 0, les envois et les créations de compte retournent HTTP 402. Vérifiez toujours le solde avant les opérations qui coûtent du karma.
SDK TypeScript
import { createClient } from "@agentmail/sdk";
const mail = createClient({ apiKey: "am_..." });
// Créer un compte
const account = await mail.accounts.create({
address: "[email protected]",
});
// Envoyer un email
await mail.messages.send(account.id, {
to: ["[email protected]"],
subject: "Hello",
text: "Sent by an AI agent.",
});
// Lire la boîte de réception
const messages = await mail.messages.list(account.id);
const detail = await mail.messages.get(account.id, messages[0].id);
// Pièces jointes
const att = await mail.attachments.getUrl(accountId, messageId, attachmentId);
// att.url est une URL de téléchargement signée
// 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);
Gestion des erreurs
import { AgentMailError } from "@agentmail/sdk";
try {
await mail.messages.send(accountId, { to: ["[email protected]"], 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);
}
}
Modèles courants
S'inscrire à un service et lire l'email de vérification
const account = await mail.accounts.create({
address: "[email protected]",
});
// Utiliser l'adresse pour s'inscrire (automatisation du navigateur, API, etc.)
// Interroger pour l'email de vérification
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);
// Analyser le lien/code de vérification à partir de detail.bodyText ou detail.bodyHtml
break;
}
await new Promise(r => setTimeout(r, 2000));
}
Envoyer un email et attendre une réponse
const sent = await mail.messages.send(account.id, {
to: ["[email protected]"],
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);
// Traiter la réponse
break;
}
await new Promise(r => setTimeout(r, 5000));
}
Types
type 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> };
Limites
- Utilisez cette compétence uniquement lorsque la tâche correspond clairement au champ d'application décrit ci-dessus.
- Ne considérez pas la sortie comme un substitut à une validation, des tests ou une revue d'expert spécifiques à l'environnement.
- Arrêtez-vous et demandez des clarifications si les entrées, autorisations, limites de sécurité ou critères de succès requis sont manquants.