Control AI Email Autonomy as a Policy, Not a Prompt

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.


Why this matters

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.


How MultiMail solves this

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.

1

Assign an oversight mode when creating the mailbox

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.

2

Agent actions are gated or logged according to the mode

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.

3

Human reviewers process the approval queue

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.

4

Monitor behavior and adjust the policy

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.

5

Expand autonomy incrementally as trust is earned

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.


Implementation

Create a mailbox with gated_send oversight
bash
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.

Process the pending approval queue
python
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.

Upgrade a mailbox from gated_send to monitored
python
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.

Handle approval webhook events
python
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.

Read-only mode for audit and analysis agents
bash
"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.


What you get

Enforcement is server-side, not prompt-side

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.

Audit trail for EU AI Act and CAN-SPAM compliance

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.

Incremental trust reduces deployment risk

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.

Approval queue handles high-volume gracefully

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.

Separate modes per mailbox, per agent

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.


Recommended oversight mode

Recommended
gated_send
gated_send is the right default for most agent email deployments because it balances operational safety with throughput. The agent can read and classify inbound email autonomously — which is where most of the volume and latency sensitivity lives — while outbound sends are held for human review. This prevents the most consequential failure mode (an agent sending incorrect, off-brand, or compliance-violating email to real recipients) without requiring approval on every read operation. Once the agent has a 30-day track record with low complaint rates and high reviewer approval rates, upgrading to monitored is a single API call.

Common questions

Can an agent change its own oversight mode?
No. Oversight modes can only be changed by API calls authenticated with an operator-level token (mm_live_... or mm_test_... tokens scoped to mailbox management). Agent tokens scoped to email operations cannot modify the oversight_mode field. This boundary is enforced server-side.
What happens to pending messages if I downgrade the mode?
Messages already in the pending queue are not affected by a mode change — they remain in the queue until approved or rejected. The new mode applies only to actions the agent takes after the change. If you want to cancel all pending sends simultaneously, use the cancel_message endpoint on each pending item before downgrading.
How long do messages stay in the pending queue before expiring?
By default, pending messages expire after 72 hours if not acted on. Expired messages are cancelled and logged. You can configure a custom expiry per mailbox (minimum 1 hour, maximum 30 days) when creating or updating the mailbox. The agent receives an email.expired webhook event when a pending message times out.
Does monitored mode still send a notification to the operator on every send?
Yes. In monitored mode, the agent's send_email call executes immediately, but a notification is dispatched to the webhook URL configured on the mailbox. If no webhook is configured, monitored mode behaves like autonomous mode — the sends execute without any operator notification. Always configure an approval_webhook when using monitored mode.
How do I demonstrate compliance with the EU AI Act's human oversight requirements?
The EU AI Act requires that high-risk AI systems maintain meaningful human oversight and that operators can intervene. MultiMail's audit log provides a timestamped record of every agent action and every human approval or rejection decision. You can export this log via the API for inclusion in conformity assessments. Using gated_all or gated_send mode for customer-facing communications creates a documented human-in-the-loop for each outbound message.
Can I set different oversight modes for inbound processing versus outbound sending?
Oversight modes apply at the mailbox level and govern all operations on that mailbox. If you need different policies for inbound triage versus outbound replies, use two mailboxes: one in read_only or monitored mode for the agent that reads and classifies, and one in gated_send mode for the agent that drafts replies. Both mailboxes can share the same underlying domain.
What does the agent receive when its send is blocked or queued?
The send_email and reply_email responses include a status field. In gated modes, status will be "pending" along with a message_id and estimated_review_time. In read_only mode, the response is a 403 with error: action_blocked and a reason field explaining the oversight_mode constraint. Agents should check the status field and handle the pending case explicitly rather than assuming immediate delivery.

Explore more use cases

The only agent email with a verifiable sender

Email infrastructure built for AI agents. Verifiable identity, graduated oversight, and a 50-tool MCP server. Formally verified in Lean 4.