MultiMail's five oversight modes give operators an explicit control plane for agent trust — from read-only observation to full autonomy — with audit trails and upgrade paths built in.
Most teams deploying AI agents on email face a binary choice: let the agent send freely (risky) or require human approval on everything (a bottleneck that erases the productivity gain). There's no operational model for phasing in autonomy as agents demonstrate reliability. The result is either unsafe production sends or a review queue that nobody actually reviews. Compliance frameworks like the EU AI Act and CAN-SPAM require documented human oversight for high-risk automated communications — but 'we prompt the model to be careful' doesn't satisfy an auditor.
MultiMail models agent email autonomy as a first-class policy decision. Each mailbox has an oversight_mode — one of five levels — that determines what the agent can do without human approval. You assign a mode when you create the mailbox, adjust it via API as trust is established, and get a full audit trail of every action and approval event. The mode is enforced server-side, so it can't be overridden by a misbehaving agent or a prompt injection attack.
Every MultiMail mailbox has an oversight_mode field. Set it to read_only, gated_all, gated_send, monitored, or autonomous at creation time. The mode is stored server-side and applies to all agent actions on that mailbox regardless of how the agent was instructed.
When the agent calls send_email or reply_email, MultiMail checks the mailbox mode before acting. In gated_send mode, reads execute immediately but sends are held in a pending queue. In monitored mode, sends execute and a notification is dispatched to the operator. The agent receives a status indicating whether the action was executed, queued, or blocked.
For gated modes, list_pending returns all actions awaiting approval. Reviewers call decide_email with approve or reject plus an optional reason. Approved messages are sent immediately; rejected messages are cancelled and the rejection reason is logged. Webhooks fire on both outcomes so downstream systems stay in sync.
The audit log captures every agent action, approval decision, and mode change. When a support agent has processed 500 inbound tickets without a false positive, you have evidence to justify upgrading from gated_send to monitored. Call the mailbox update endpoint to change the mode; the new policy takes effect immediately on the next action.
The mode ladder is designed to be climbed: read_only → gated_all → gated_send → monitored → autonomous. Each rung represents a documented, reversible trust decision. If behavior degrades — higher complaint rates, off-topic sends, approval queue anomalies — downgrade the mode via API. The change is instant and requires no redeployment.
curl -X POST https://api.multimail.dev/mailboxes \
-H &"cm">#039;Authorization: Bearer $MULTIMAIL_API_KEY...' \
-H &"cm">#039;Content-Type: application/json' \
-d &"cm">#039;{
"address": "[email protected]",
"display_name": "Acme Support Agent",
"oversight_mode": "gated_send",
"approval_webhook": "https://ops.acme.com/webhooks/email-approvals"
}&"cm">#039;The agent can read and search freely, but all outbound sends are held for human approval before delivery.
import requests
HEADERS = {"Authorization": "Bearer $MULTIMAIL_API_KEY..."}
BASE = "https://api.multimail.dev"
"cm"># Fetch pending sends
pending = requests.get(
f"{BASE}/mailboxes/[email protected]/pending",
headers=HEADERS
).json()
for item in pending["messages"]:
print(f"To: {item[&"cm">#039;to']}")
print(f"Subject: {item[&"cm">#039;subject']}")
print(f"Preview: {item[&"cm">#039;body_preview']}")
decision = input("Approve? (y/n): ").strip().lower()
requests.post(
f"{BASE}/emails/{item[&"cm">#039;id']}/decide",
headers=HEADERS,
json={
"action": "approve" if decision == "y" else "reject",
"reason": None if decision == "y" else "Off-topic for support queue"
}
)Fetch all outbound messages awaiting human review, then approve or reject each one. Use this in your internal ops dashboard or Slack bot.
import requests
HEADERS = {"Authorization": "Bearer $MULTIMAIL_API_KEY..."}
"cm"># Upgrade trust level after reviewing 30-day audit log
response = requests.patch(
"https://api.multimail.dev/mailboxes/[email protected]",
headers=HEADERS,
json={
"oversight_mode": "monitored",
"change_reason": "30-day audit: 0 complaint rate, 97% CSAT on agent-handled tickets"
}
)
data = response.json()
print(f"Mode updated to: {data[&"cm">#039;oversight_mode']}")
print(f"Effective at: {data[&"cm">#039;updated_at']}")After an agent has demonstrated reliable behavior, escalate its trust level. The new mode takes effect immediately — no redeployment needed.
from flask import Flask, request, jsonify
import hmac, hashlib
app = Flask(__name__)
WEBHOOK_SECRET = "whsec_..."
@app.route("/webhooks/email-approvals", methods=["POST"])
def handle_approval():
sig = request.headers.get("X-MultiMail-Signature", "")
body = request.get_data()
expected = hmac.new(
WEBHOOK_SECRET.encode(), body, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(sig, expected):
return jsonify({"error": "invalid signature"}), 401
event = request.json
if event["type"] == "email.approved":
"cm"># Message was sent — update agent context
print(f"Sent: {event[&"cm">#039;data']['subject']} to {event['data']['to']}")
elif event["type"] == "email.rejected":
# Notify agent of rejection reason
print(f"Rejected: {event[&"cm">#039;data']['reason']}")
return jsonify({"ok": True})MultiMail fires a webhook when an agent action is approved or rejected. Use this to update your agent's context or trigger downstream workflows.
"cm"># Create a read-only mailbox for an analytics agent
curl -X POST https://api.multimail.dev/mailboxes \
-H &"cm">#039;Authorization: Bearer $MULTIMAIL_API_KEY...' \
-H &"cm">#039;Content-Type: application/json' \
-d &"cm">#039;{
"address": "[email protected]",
"display_name": "Acme Audit Agent",
"oversight_mode": "read_only"
}&"cm">#039;
"cm"># Agent can read but send attempts return 403
curl -X POST https://api.multimail.dev/emails/send \
-H &"cm">#039;Authorization: Bearer $MULTIMAIL_API_KEY...' \
-d &"cm">#039;{"from": "[email protected]", "to": "[email protected]", "subject": "test"}'
"cm"># Response: {"error": "action_blocked", "reason": "oversight_mode is read_only"}An agent in read_only mode can check_inbox, read_email, and manage_contacts but cannot send, reply, or tag. Useful for reporting agents that should never touch live email state.
Oversight modes are enforced by the MultiMail API, not by instructions in the agent's system prompt. A prompt injection attack or a misconfigured agent cannot override the mode. The mailbox's oversight_mode is the source of truth.
Every agent action, mode change, and approval decision is logged with a timestamp and actor. The EU AI Act requires documented human oversight for high-risk automated systems; CAN-SPAM requires identifiable senders and opt-out handling. MultiMail's audit log gives you the paper trail both regulations expect.
Starting a new agent in gated_all mode costs nothing but reviewer time. As the agent proves reliable, upgrading to gated_send and then monitored is a single API call — no code changes, no redeployment, no downtime. Reverting is equally instant if behavior degrades.
In gated_send mode, agents can generate hundreds of pending sends without blocking. Reviewers process the queue in batches via list_pending and decide_email. Approved messages are delivered in the order they were queued, maintaining thread coherence even after delayed approval.
A single deployment can run multiple agents at different trust levels simultaneously. Your triage agent might be in monitored mode while your customer-facing reply agent stays in gated_send. Each mailbox carries its own mode independently.
Email infrastructure built for AI agents. Verifiable identity, graduated oversight, and a 50-tool MCP server. Formally verified in Lean 4.