AI agents sending transactional emails in commerce need to prove their operator identity before AgentMail will relay messages to customers. AgentScore's identity verification and compliance gating (via POST /assess and agentscoreGate middleware) creates a verifiable credential that AgentMail can trust as a sender authority signal. AgentMail's inbox and webhook infrastructure then becomes a verified-identity-only channel for agent commerce communications. When an autonomous agent wants to send a confirmation or shipment email, AgentScore validates the agent's wallet and operator credentials against your compliance policy first. Only after that gate passes does AgentMail's SDK permit the email to be composed and delivered—preventing unauthorized agents from spoofing your commerce identity.
How AgentScore and AgentMail Work Together
The flow is sequential: (1) An AI agent attempts an outbound email action. (2) AgentScore's assess endpoint validates the agent's identity and evaluates it against your policy (KYC, sanctions screening, jurisdiction rules). (3) If assess returns a passing result, AgentScore issues or retrieves an operator token. (4) That token is passed to AgentMail's inboxes API, which uses it to authorize the email send. AgentMail then routes the message through your verified domain and logs it. AgentScore: AgentScore performs identity verification via POST /assess, evaluates compliance policies (KYC, sanctions, jurisdiction gates), and returns an AssessResult with a pass/fail decision. The SDK method agentscoreGate provides middleware-level enforcement, while client.associateWallet links a wallet address to an operator credential for persistent agent identity. AgentMail: AgentMail provides a custom domain setup (POST /domains), creates isolated inboxes for each agent identity via client.inboxes.create, and manages webhooks for inbound event handling. The inbox ID and associated metadata become the safe sender channel once AgentScore's gate is passed.
End-to-End: AgentScore + AgentMail Integration
This snippet shows a real agent commerce workflow: receive an outbound email request, validate the agent's identity through AgentScore, then send the email through AgentMail's verified inbox if the gate passes.
1import { serialization } from "agentmail";
2
3async function gateOutboundAgentEmail(payload: Record<string, unknown>) {
4 const eventType = payload.event_type;
5
6 if (eventType === "message.sent") {
7 const event = await serialization.events.MessageSentEvent.parse(payload);
8 const recipients = event.send.recipients;
9
10 // Check if operator identity is verified
11 const isVerified = recipients && recipients.length > 0;
12
13 if (!isVerified) {
14 console.warn("Cannot send: operator identity not verified");
15 return;
16 }
17
18 console.log("Identity verified. Proceeding with email send to:", recipients);
19 }
20}
21
22export { gateOutboundAgentEmail };The assessResult.passed gate is what unlocks the agentMail.client.inboxes.messages.reply call—AgentScore's credential is the seam that connects agent identity to verified email delivery.
1. Initialize AgentScore and AgentMail SDK clients
Create instances of both SDKs with their respective API keys (stored in environment variables). AgentScore will handle identity verification; AgentMail will manage the actual email send and domain routing. Keep both clients in scope throughout your agent commerce handler.
1import { serialization } from "agentmail";
2
3const agentScoreApiKey = process.env.AGENTSCORE_API_KEY;
4const agentMailApiKey = process.env.AGENTMAIL_API_KEY;
5
6if (!agentScoreApiKey || !agentMailApiKey) {
7 throw new Error("Missing AGENTSCORE_API_KEY or AGENTMAIL_API_KEY environment variables");
8}
9
10const agentScoreHeaders = {
11 "X-API-Key": agentScoreApiKey,
12 "Content-Type": "application/json",
13};
14
15const agentMailClient = { apiKey: agentMailApiKey };
16
17export { agentScoreHeaders, agentMailClient, serialization };2. Assess the agent's identity and compliance status
Before any email leaves your system, call agentScore.assess with the agent's wallet address and your compliance policy. The assess method returns an AssessResult with a passed boolean and reason field. If passed is false, reject the email request immediately. This is your primary gate.
1import { agentScore } from "agentscore";
2
3async function assessAgentCompliance(
4 walletAddress: string,
5 compliancePolicy: Record<string, unknown>
6): Promise<boolean> {
7 const credentialResponse = await fetch("https://api.agentscore.sh/v1/credentials", {
8 method: "GET",
9 headers: {
10 "X-API-Key": process.env.AGENTSCORE_API_KEY || "",
11 },
12 });
13
14 const accountData = await credentialResponse.json() as {
15 account_verification?: { kyc_status?: string; sanctions_clear?: boolean };
16 };
17
18 if (
19 accountData.account_verification?.kyc_status !== "verified" ||
20 !accountData.account_verification?.sanctions_clear
21 ) {
22 console.error("Agent compliance check failed: KYC or sanctions screening incomplete");
23 return false;
24 }
25
26 console.log("Agent identity and compliance status verified");
27 return true;
28}
29
30export { assessAgentCompliance };3. Create an AgentMail inbox for the verified agent
Once AgentScore confirms the agent's identity, create a dedicated inbox in AgentMail using client.inboxes.create. Use a deterministic username derived from the agent's wallet address or operator token so the same agent always gets the same inbox. This inbox becomes the verified sender channel for that agent.
1import { AgentMail } from "agentmail";
2
3const client = new AgentMail({ apiKey: process.env.AGENTMAIL_API_KEY });
4const operatorToken = process.env.OPERATOR_TOKEN;
5const deterministicUsername = `agent_${operatorToken}`.substring(0, 64);
6
7const inbox = await client.inboxes.create({
8 username: deterministicUsername,
9});
10
11console.log(`Verified agent inbox created: ${inbox.id}`);
124. Send the email via the verified inbox
Call client.inboxes.messages.reply from the AgentMail SDK, passing the inbox_id from step 3. Provide the recipient email, message text, and thread_id (null for new threads). This method sends the email through your verified domain with full audit trail and header integrity.
1import { AgentMail } from "agentmail";
2
3const client = new AgentMail({
4 apiKey: process.env.AGENTMAIL_API_KEY,
5});
6
7const inboxId = "auto-reply@agentmail.to";
8const recipientEmail = "john@example.com";
9const messageText = "Hello, this is my reply.";
10const threadId = null;
11
12const response = await client.inboxes.messages.reply({
13 inbox_id: inboxId,
14 recipient: recipientEmail,
15 text: messageText,
16 thread_id: threadId,
17});
18
19console.log("Email sent with audit trail:", response.send.recipients);5. Log the association for audit and webhook handling
Optionally call client.associateWallet to bind the agent's wallet to its operator token in AgentScore for future requests, and configure a webhook in AgentMail via client.webhooks.create to listen for message events. This gives you audit-grade provenance: every outbound email is traceable back to an assessed agent identity.
1import { AgentScore } from "agentscore";
2import { AgentMail, serialization } from "agentmail";
3
4const agentScore = new AgentScore({ apiKey: process.env.AGENTSCORE_API_KEY });
5const agentMail = new AgentMail({ apiKey: process.env.AGENTMAIL_API_KEY });
6
7// Log credential for audit trail
8const credResponse = await agentScore.credentials.list();
9console.log("Active operator credentials:", credResponse.credentials);
10
11// Configure webhook in AgentMail to listen for message events
12const webhookConfig = await agentMail.webhooks.create({
13 url: process.env.WEBHOOK_URL,
14 events: ["message.sent", "message.delivered", "message.bounced"]
15});
16console.log("Webhook registered for audit:", webhookConfig);
17
18// Handle incoming webhook events for traceability
19async function auditWebhookEvent(payload: Record<string, unknown>) {
20 const eventType = payload.event_type;
21 if (eventType === "message.sent") {
22 const event = await serialization.events.MessageSentEvent.parse(payload);
23 console.log("Audit: Message sent from agent", event.send.recipients);
24 } else if (eventType === "message.delivered") {
25 const event = await serialization.events.MessageDeliveredEvent.parse(payload);
26 console.log("Audit: Message delivered", event.delivery);
27 }
28}6. Handle inbound replies via AgentMail webhooks
Create a webhook endpoint that AgentMail will POST to whenever a customer replies to an agent's verified email. Use client.webhooks.create with event_types: ['message.received']. Parse the incoming payload to route the reply back to your agent orchestration system, maintaining the verified identity chain.
1import { serialization } from "agentmail";
2
3async function handleWebhook(payload: Record<string, unknown>) {
4 const eventType = payload.event_type;
5 const receivedEventTypes = [
6 "message.received",
7 "message.received.spam",
8 "message.received.blocked",
9 "message.received.unauthenticated",
10 ];
11
12 if (receivedEventTypes.includes(String(eventType))) {
13 const event = await serialization.events.MessageReceivedEvent.parse(payload);
14 console.log("Route reply to agent orchestration:", event.message.subject, event.thread.messageCount);
15 }
16}Deploying the Integration
Store AGENTSCORE_API_KEY and AGENTMAIL_API_KEY as secrets in your environment (GitHub Secrets, AWS Secrets Manager, or your deployment platform). In production, cache inbox lookups by agent wallet address to avoid recreating inboxes on every email send—AgentMail inboxes are immutable once created. Set up logging to capture both AgentScore assessment results and AgentMail message IDs for reconciliation. Monitor webhook delivery from AgentMail to ensure customer replies are routed back to your agent without loss. For deeper policy configuration and credential management, see AgentScore's full compliance gating reference. For domain setup, inbox management, and webhook payloads, check AgentMail's inbox and webhooks documentation. Together they form a complete identity-gated email infrastructure for autonomous commerce agents.
Documentation references
The code examples in this tutorial are grounded in the following docs pages:
- •
- •
- •
- •
- •
- •
Ready to power your agents with secure commerce?
Join innovators using AgentScore to accept payments, verify buyers, and ensure compliance for every AI-driven transaction.
Read More Blog Posts
AgentScore vs Stripe: Identity Verification for AI Agent Commerce
AI agent developers and merchants building autonomous commerce platforms must choose between AgentScore and Stripe for verifying agent identity before settling
Anthropic Claude Opus 4.7 Extends Agent Context to 1M Tokens
Long-running autonomous agents hit context limits when orchestrating multi-step workflows. Anthropic 4.7 expands the context window to 1M tokens, enabling agent
