Replicate handles model inference. MultiMail handles the email boundary — approval gates, delivery, and an audit trail for whatever your models produce.
Replicate gives agents access to hundreds of open and proprietary models through a single API. When those models generate text, images, or structured output that needs to reach a human inbox, you need a separate layer to handle delivery safely. Model output and email sending are different responsibilities with different failure modes.
MultiMail sits between Replicate's predictions and your recipients. It provides oversight modes that let you require human approval before any model-generated content leaves your system, log every send decision for compliance review, and route inbound replies back to the agent that sent the original message.
The integration is direct: call Replicate to run inference, pass the output to MultiMail's REST API or MCP server, and let MultiMail handle delivery policy. No shared SDK required — both services expose clean HTTP APIs that compose naturally in any language or agent framework.
Replicate predictions can produce content you wouldn't want sent without review. MultiMail's gated_send and gated_all modes hold outbound messages for human approval before delivery, regardless of how confident the model was.
Every send_email call through MultiMail records the message, sender identity, recipient, and timestamp. When model-generated emails are involved, this log is the evidence trail regulators and auditors ask for under CAN-SPAM and GDPR.
When recipients reply to a Replicate-generated email, MultiMail webhooks deliver the reply to your agent via check_inbox and read_email. The agent can continue the thread without polling or managing raw SMTP.
MultiMail mailboxes are owned by your account and cryptographically tied to your domain. The model that generated the content doesn't appear in email headers — your verified identity does.
High-stakes workflows (customer outreach, medical summaries) can require gated_all approval. Internal digest pipelines can run in monitored mode. The mode is set per mailbox, not per request.
import Replicate from 'replicate';
const replicate = new Replicate({ auth: process.env.REPLICATE_API_TOKEN });
"cm">// Generate email body from a prompt
const output = await replicate.run(
'meta/llama-3-8b-instruct',
{
input: {
prompt: 'Write a 3-sentence project status update for Q2 sprint completion. Tone: direct, no filler.',
max_tokens: 200
}
}
);
const body = Array.isArray(output) ? output.join('') : String(output);
"cm">// Send via MultiMail — oversight mode enforced server-side
const response = await fetch('https://api.multimail.dev/v1/send_email', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.MULTIMAIL_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
from: '[email protected]',
to: '[email protected]',
subject: 'Q2 Sprint Status Update',
body,
metadata: {
model: 'meta/llama-3-8b-instruct',
source: 'replicate'
}
})
});
const result = await response.json();
if (result.status === 'pending_approval') {
console.log(`Message queued for approval: ${result.message_id}`);
} else {
console.log(`Sent: ${result.message_id}`);
}Basic pattern: call Replicate's API for inference, then post the result to MultiMail's send_email endpoint. The MultiMail token enforces your mailbox's oversight mode automatically.
import replicate
import httpx
import os
MULTIMAIL_API_KEY = os.environ["MULTIMAIL_API_KEY"]
MULTIMAIL_BASE = "https://api.multimail.dev/v1"
def caption_and_queue(image_url: str, recipient: str) -> dict:
"cm"># Run Replicate vision model
output = replicate.run(
"salesforce/blip:2e1dddc8621f72155f24cf2e0adbde548458d3cab9f00c0139eea840d0ac4746",
input={"image": image_url, "task": "image_captioning"}
)
caption = str(output)
"cm"># Queue email — mailbox is configured gated_send, so it holds for approval
with httpx.Client() as client:
resp = client.post(
f"{MULTIMAIL_BASE}/send_email",
headers={"Authorization": f"Bearer {MULTIMAIL_API_KEY}"},
json={
"from": "[email protected]",
"to": recipient,
"subject": "Image Analysis Result",
"body": f"Caption generated by vision model:\n\n{caption}",
"metadata": {"model": "salesforce/blip", "source_image": image_url}
}
)
return resp.json()
def approve_pending() -> list:
with httpx.Client() as client:
pending = client.get(
f"{MULTIMAIL_BASE}/list_pending",
headers={"Authorization": f"Bearer {MULTIMAIL_API_KEY}"}
).json()
approved = []
for msg in pending.get("messages", []):
decision = client.post(
f"{MULTIMAIL_BASE}/decide_email",
headers={"Authorization": f"Bearer {MULTIMAIL_API_KEY}"},
json={"message_id": msg["id"], "action": "approve"}
).json()
approved.append(decision)
return approved
"cm"># Usage
result = caption_and_queue(
"https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PNG_transparency_demonstration_1.png/280px-PNG_transparency_demonstration_1.png",
"[email protected]"
)
print(result) "cm"># {"status": "pending_approval", "message_id": "msg_..."}Use a Replicate vision model to caption an image, then gate the resulting email on human approval before delivery. The list_pending and decide_email calls let a separate process handle the approval queue.
import Replicate from 'replicate';
import { Hono } from 'hono';
const app = new Hono();
const replicate = new Replicate({ auth: process.env.REPLICATE_API_TOKEN });
app.post('/webhooks/multimail', async (c) => {
const event = await c.req.json();
if (event.type !== 'email.received') {
return c.json({ ok: true });
}
"cm">// Read the full email via MultiMail
const emailResp = await fetch(
`https:"cm">//api.multimail.dev/v1/read_email?message_id=${event.message_id}`,
{ headers: { 'Authorization': `Bearer ${process.env.MULTIMAIL_API_KEY}` } }
);
const email = await emailResp.json();
"cm">// Generate reply with Replicate
const output = await replicate.run(
'meta/llama-3-8b-instruct',
{
input: {
prompt: `Reply to this email professionally in 2-3 sentences:\n\n${email.body}`,
max_tokens: 150,
system_prompt: 'You are a helpful assistant. Be concise and direct.'
}
}
);
const replyBody = Array.isArray(output) ? output.join('') : String(output);
"cm">// Send reply via MultiMail's reply_email to preserve thread
await fetch('https:"cm">//api.multimail.dev/v1/reply_email', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.MULTIMAIL_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
in_reply_to: event.message_id,
body: replyBody,
metadata: { model: 'meta/llama-3-8b-instruct', generated: true }
})
});
return c.json({ ok: true });
});
export default app;When a recipient replies to a Replicate-generated email, MultiMail fires a webhook. This handler reads the reply, runs another Replicate prediction for the response, and queues a follow-up through MultiMail.
"cm">// This pattern works when MultiMail MCP server is configured in your client.
"cm">// The agent calls Replicate directly, then uses MultiMail MCP tools for email actions.
"cm">// 1. Agent calls Replicate REST API for inference
const replicateResp = await fetch('https://api.replicate.com/v1/predictions', {
method: 'POST',
headers: {
'Authorization': `Token ${process.env.REPLICATE_API_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
version: 'ac944f2e49c55c7e965fc3d93ad9a7d9d947866d6793fb849dd6b4747d0c061c',
input: {
prompt: 'Summarize the following support ticket in one paragraph: ...',
max_new_tokens: 256
}
})
});
"cm">// Poll until complete (simplified)
let prediction = await replicateResp.json();
while (prediction.status === 'processing' || prediction.status === 'starting') {
await new Promise(r => setTimeout(r, 1000));
const poll = await fetch(`https:"cm">//api.replicate.com/v1/predictions/${prediction.id}`, {
headers: { 'Authorization': `Token ${process.env.REPLICATE_API_TOKEN}` }
});
prediction = await poll.json();
}
const summary = prediction.output?.join?.('') ?? prediction.output;
"cm">// 2. Use MultiMail MCP send_email tool to deliver the summary
"cm">// (In MCP context, this is a tool call — shown here as the equivalent REST call)
const sendResp = await fetch('https://api.multimail.dev/v1/send_email', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.MULTIMAIL_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
from: '[email protected]',
to: '[email protected]',
subject: 'Support Ticket Summary',
body: summary
})
});
console.log(await sendResp.json());If your agent runs inside an MCP-compatible client like Claude Desktop, MultiMail's 43 MCP tools are available natively. Pair them with a Replicate call to build a fully instrumented email pipeline.
Sign up at multimail.dev, create a mailbox (custom domain or @multimail.dev subdomain), and copy your API key from the dashboard. Set the mailbox oversight mode to gated_send for initial testing — this lets you inspect outbound messages before they deliver.
"cm"># Verify your key works
curl -s https://api.multimail.dev/v1/check_inbox \
-H &"cm">#039;Authorization: Bearer $MULTIMAIL_API_KEY' | jq .statusInstall the Replicate JavaScript or Python client and export your Replicate API token. You'll authenticate to both services independently — MultiMail via Bearer token, Replicate via its own token header.
npm install replicate
"cm"># Or for Python
uv pip install replicate
export REPLICATE_API_TOKEN=r8_your_token_here
export MULTIMAIL_API_KEY=mm_live_your_key_hereMake a Replicate prediction call, wait for the result, then post it to MultiMail's send_email endpoint. Start with a text generation model so you can inspect the full round trip before adding multimodal steps.
import Replicate from &"cm">#039;replicate';
const replicate = new Replicate({ auth: process.env.REPLICATE_API_TOKEN });
const output = await replicate.run(
&"cm">#039;meta/llama-3-8b-instruct',
{ input: { prompt: &"cm">#039;Write a 2-sentence test message.', max_tokens: 100 } }
);
const body = Array.isArray(output) ? output.join(&"cm">#039;') : String(output);
const resp = await fetch(&"cm">#039;https://api.multimail.dev/v1/send_email', {
method: &"cm">#039;POST',
headers: {
&"cm">#039;Authorization': `Bearer ${process.env.MULTIMAIL_API_KEY}`,
&"cm">#039;Content-Type': 'application/json'
},
body: JSON.stringify({
from: &"cm">#039;[email protected]',
to: &"cm">#039;[email protected]',
subject: &"cm">#039;Replicate + MultiMail test',
body
})
});
console.log(await resp.json());Because the mailbox is in gated_send mode, the message is queued. Use list_pending to see it, then decide_email to approve. Check your inbox to confirm delivery.
"cm"># List pending messages
curl -s https://api.multimail.dev/v1/list_pending \
-H &"cm">#039;Authorization: Bearer $MULTIMAIL_API_KEY' | jq '.messages[0].id'
"cm"># Approve by message ID
curl -s -X POST https://api.multimail.dev/v1/decide_email \
-H &"cm">#039;Authorization: Bearer $MULTIMAIL_API_KEY' \
-H &"cm">#039;Content-Type: application/json' \
-d &"cm">#039;{"message_id": "msg_the_id_from_above", "action": "approve"}'Configure a webhook endpoint in the MultiMail dashboard pointing to your agent server. When a recipient replies, MultiMail POSTs the event to your endpoint. Call read_email to fetch the body and feed it back to Replicate for a follow-up prediction.
"cm"># In your MultiMail dashboard: Settings > Webhooks > Add endpoint
"cm"># URL: https://your-agent.yourcompany.com/webhooks/multimail
"cm"># Events: email.received, email.approved, email.rejected
"cm"># Your webhook handler reads the reply:
curl -s &"cm">#039;https://api.multimail.dev/v1/read_email?message_id=msg_reply_id' \
-H &"cm">#039;Authorization: Bearer $MULTIMAIL_API_KEY' | jq .bodyEmail infrastructure built for AI agents. Verifiable identity, graduated oversight, and a 38-tool MCP server. Formally verified in Lean 4.