AI-Powered Email Triage with Marvin

Use Marvin's classification and extraction functions to intelligently process email, then route and respond through MultiMail with configurable human oversight.


Marvin is a lightweight AI engineering toolkit by Prefect focused on building reliable AI features. It provides simple functions for classification, extraction, transformation, and generation — making it ideal for email processing tasks like triage, categorization, and response generation. MultiMail provides the email infrastructure that connects Marvin's intelligence to actual inboxes.

By combining Marvin with MultiMail, you can classify inbound emails by intent and urgency, extract structured data from email content, generate appropriate responses, and route everything through managed mailboxes with human oversight. Marvin handles the AI reasoning, MultiMail handles the email delivery.

Integration is straightforward: use Marvin's functions to process email data fetched from MultiMail's API, then send responses back through MultiMail. No complex framework setup required — just function calls.

Built for Marvin developers

Email Classification at Scale

Marvin's classify function categorizes inbound emails by type, urgency, or department with a single function call. Combined with MultiMail's inbox, you can build automated email triage that routes messages to the right handlers.

Data Extraction from Emails

Use marvin.extract() to pull structured data from email bodies — order numbers, dates, amounts, names. This extracted data drives automated workflows while MultiMail manages the email infrastructure.

Simple AI Functions

Marvin's functions (classify, extract, transform, generate) are single-purpose and composable. Each one maps to a specific email processing step, making workflows easy to understand and debug.

Response Generation

Use marvin.generate() to create email responses based on classification and extracted context. MultiMail's gated_send mode ensures generated responses get human review before delivery.

No Framework Lock-in

Marvin functions are standalone Python functions. You can use them with any email processing architecture, swap individual steps, or combine with other tools alongside MultiMail.


Get started in minutes

Classify Inbound Emails
python
import marvin
import requests
from enum import Enum

MULTIMAIL_API = "https://api.multimail.dev/v1"
HEADERS = {"Authorization": "Bearer mm_live_your_api_key"}

class EmailCategory(Enum):
    SUPPORT = "support"
    SALES = "sales"
    BILLING = "billing"
    PARTNERSHIP = "partnership"
    SPAM = "spam"

class Urgency(Enum):
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"

def triage_inbox(mailbox_id: str):
    resp = requests.get(
        f"{MULTIMAIL_API}/mailboxes/{mailbox_id}/inbox",
        headers=HEADERS, params={"limit": 20}
    )
    for email in resp.json().get("emails", []):
        content = f"Subject: {email[&"cm">#039;subject']}\n\n{email['body']}"
        category = marvin.classify(content, labels=EmailCategory)
        urgency = marvin.classify(content, labels=Urgency)

        # Tag the email in MultiMail
        requests.post(f"{MULTIMAIL_API}/tag", headers=HEADERS, json={
            "message_id": email["message_id"],
            "tags": [category.value, urgency.value]
        })
        print(f"{email[&"cm">#039;subject']}: {category.value} ({urgency.value})")

triage_inbox("your_mailbox_id")

Use Marvin's classify function to categorize emails fetched from MultiMail.

Extract Data and Generate Replies
python
from pydantic import BaseModel

class SupportTicket(BaseModel):
    customer_name: str
    issue_summary: str
    product_mentioned: str
    account_id: str | None = None

def process_support_email(email: dict) -> dict:
    content = f"Subject: {email[&"cm">#039;subject']}\n\n{email['body']}"

    # Extract structured data
    ticket = marvin.extract(content, target=SupportTicket)[0]

    # Generate a response
    reply_body = marvin.generate(
        n=1,
        instructions=f"Write a professional support reply acknowledging "
        f"the issue: {ticket.issue_summary}. Address the customer as "
        f"{ticket.customer_name}. Be empathetic and provide next steps."
    )[0]

    # Send via MultiMail (gated_send queues for approval)
    resp = requests.post(f"{MULTIMAIL_API}/reply", headers=HEADERS, json={
        "message_id": email["message_id"],
        "body": reply_body
    })
    return {"ticket": ticket.model_dump(), "reply": reply_body, "result": resp.json()}

# Process a support email
email = {"subject": "Login issue", "body": "Hi, I&"cm">#039;m John from Acme Corp...",
         "message_id": "msg_abc123"}
result = process_support_email(email)

Extract structured data from emails and generate context-aware responses.

Transform Email Content
python
def forward_with_summary(email: dict, forward_to: str, mailbox_id: str):
    """Forward an email with an AI-generated executive summary."""
    content = f"Subject: {email[&"cm">#039;subject']}\n\n{email['body']}"

    # Transform the email into an executive summary
    summary = marvin.cast(
        content,
        instructions="Summarize this email in 2-3 bullet points for an executive audience. "
        "Focus on action items and decisions needed."
    )

    # Send the summary as a forwarded email via MultiMail
    resp = requests.post(f"{MULTIMAIL_API}/send", headers=HEADERS, json={
        "mailbox_id": mailbox_id,
        "to": forward_to,
        "subject": f"[Summary] {email[&"cm">#039;subject']}",
        "body": f"Executive Summary:\n\n{summary}\n\n---\nOriginal email below:\n\n{email[&"cm">#039;body']}"
    })
    return resp.json()

result = forward_with_summary(
    email={"subject": "Q3 Budget Review", "body": "Detailed budget analysis..."},
    forward_to="[email protected]",
    mailbox_id="your_mailbox_id"
)

Use Marvin's transform to rewrite emails for different audiences or formats.


Step by step

1

Create a MultiMail Account and API Key

Sign up at multimail.dev, create a mailbox, and generate an API key. Your key will start with mm_live_.

2

Install Dependencies

Install Marvin and requests for calling the MultiMail API.

bash
pip install marvin requests
3

Fetch and Classify Emails

Use the MultiMail API to fetch inbox messages, then classify each with marvin.classify() using your custom label enums.

bash
category = marvin.classify(email_content, labels=EmailCategory)
4

Extract Data and Generate Replies

Use marvin.extract() to pull structured data from emails and marvin.generate() to compose responses.

5

Send and Review

Send replies through MultiMail's API. Review and approve pending emails in the dashboard when using gated_send mode.


Common questions

What Marvin functions are most useful for email processing?
marvin.classify() for categorizing emails by type/urgency, marvin.extract() for pulling structured data like names and order numbers, marvin.cast() for transforming email content into summaries or different formats, and marvin.generate() for composing responses. Each handles a specific step in the email processing pipeline.
How does Marvin compare to full agent frameworks for email?
Marvin provides individual AI functions rather than an agent loop. This is simpler and more predictable — each function does one thing well. For complex multi-step email workflows, you orchestrate Marvin functions yourself or combine them with a workflow tool like ControlFlow (also by Prefect).
Can I use Marvin's classification to auto-route emails?
Yes. Classify inbound emails by department or type, then use MultiMail's tag_email endpoint to label them. Your application logic can then route tagged emails to appropriate mailboxes or handlers. In gated_send mode, any auto-generated replies still require human approval.
How do I handle emails that Marvin can't classify confidently?
Marvin's classify function always returns a label from your enum. For edge cases, add an OTHER or UNCERTAIN category and route those to a human review queue. MultiMail's gated_send mode provides an additional safety net for replies to ambiguously classified emails.
Can I combine Marvin with ControlFlow for complex email workflows?
Yes. Marvin and ControlFlow are both by Prefect and designed to work together. Use Marvin functions for individual AI tasks (classify, extract, generate) within ControlFlow task flows for orchestrating multi-step email processing pipelines with dependency management.

Explore more

The only agent email with a verifiable sender

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