integrations

AgentMail

Scan incoming agent emails for phishing with brin before your agent processes them

AgentMail gives AI agents their own email inboxes to send, receive, and act on emails. By wiring brin into the AgentMail webhook pipeline, you can scan every incoming message for phishing, credential harvesting, and social engineering before your agent sees it.

##Prerequisites

  • An AgentMail account and API key
  • A publicly reachable HTTPS endpoint to receive webhooks

##How it works

100%

AgentMail fires a message.received webhook whenever an email arrives in an agent's inbox. Your handler fetches the raw .eml via AgentMail's Get Raw Message API and POSTs it to brin's /email endpoint. Sending the raw RFC 822 content preserves all headers, MIME structure, and authentication signals (SPF, DKIM) for more accurate phishing detection. If the verdict is suspicious or dangerous, the handler labels it using AgentMail's Update Message API so the agent can skip or handle it accordingly.

##Setup

1. Register a webhook with AgentMail

Subscribe to message.received events so your handler is called on every inbound email.

Python
from agentmail import AgentMail
 
client = AgentMail(api_key="am_...")
 
client.webhooks.create(
    url="https://your-server.com/webhooks/agentmail",
    event_types=["message.received"],
)
TypeScript
import { AgentMailClient } from "agentmail";
 
const client = new AgentMailClient({ apiKey: "am_..." });
 
await client.webhooks.create({
  url: "https://your-server.com/webhooks/agentmail",
  eventTypes: ["message.received"],
});

2. Build a webhook handler that scans with brin

When a message.received event arrives, fetch the raw email and POST it to brin for analysis.

Python
import httpx
from agentmail import AgentMail
from fastapi import FastAPI, Request
 
app = FastAPI()
agentmail = AgentMail(api_key="am_...")
 
@app.post("/webhooks/agentmail")
async def handle_message_received(request: Request):
    payload = await request.json()
    message = payload["message"]
 
    raw = agentmail.inboxes.messages.get_raw(
        inbox_id=message["inbox_id"],
        message_id=message["message_id"],
    )
 
    async with httpx.AsyncClient() as http:
        eml = await http.get(raw.download_url)
 
        brin_resp = await http.post(
            "https://api.brin.sh/email",
            content=eml.content,
            headers={"Content-Type": "text/plain"},
        )
 
    result = brin_resp.json()
    verdict = result.get("verdict", "safe")
 
    if verdict in ("suspicious", "dangerous"):
        agentmail.inboxes.messages.update(
            inbox_id=message["inbox_id"],
            message_id=message["message_id"],
            add_labels=["dangerous"],
        )
        return {"status": "flagged", "verdict": verdict}
 
    process_email(message)
    return {"status": "processed"}
TypeScript
import express from "express";
import { AgentMailClient } from "agentmail";
 
const app = express();
app.use(express.json());
 
const agentmail = new AgentMailClient({ apiKey: "am_..." });
 
app.post("/webhooks/agentmail", async (req, res) => {
  const { message } = req.body;
 
  const raw = await agentmail.inboxes.messages.getRaw(
    message.inboxId,
    message.messageId,
  );
 
  const eml = await fetch(raw.downloadUrl);
  const emlBody = await eml.text();
 
  const brinResp = await fetch("https://api.brin.sh/email", {
    method: "POST",
    headers: { "Content-Type": "text/plain" },
    body: emlBody,
  });
 
  const result = await brinResp.json();
  const verdict = result.verdict ?? "safe";
 
  if (verdict === "suspicious" || verdict === "dangerous") {
    await agentmail.inboxes.messages.update(message.inboxId, message.messageId, {
      addLabels: ["dangerous"],
    });
    return res.json({ status: "flagged", verdict });
  }
 
  processEmail(message);
  res.json({ status: "processed" });
});
 
app.listen(3000);

3. Deploy and test

Deploy your webhook handler and send a test email to your agent's AgentMail inbox. Check the logs to confirm brin is scanning each message and returning a verdict.

##What gets detected

brin checks every email for the threat types listed under Web threats:

ThreatDescription
PhishingCredential harvesting forms or deceptive login pages
Social engineeringDeceptive content designed to manipulate agent decisions
CloakingContent that shows different material to agents vs. humans
Exfiltration sinksHidden redirects or JS designed to exfiltrate agent session data

Each threat is assigned a severity (critical, high, medium, low). See Threat Detection for the full taxonomy.

##Using the response

The brin response follows the standard API format:

JSON
{
  "score": 15,
  "verdict": "dangerous",
  "confidence": "high",
  "threats": [
    {
      "type": "phishing",
      "severity": "critical",
      "detail": "Credential harvesting form targeting Google login"
    }
  ]
}

You can also read verdicts from response headers (x-brin-verdict, x-brin-score) for lightweight checks without parsing JSON.