Email Threading That Keeps Agents in Context

MultiMail tracks thread identity, conversation history, and reply headers so your AI agent never loses context or forks a conversation incorrectly.


Why this matters

Email agents fail in subtle, trust-destroying ways when thread context is missing. An agent that replies to the wrong message in a chain, repeats information already addressed three emails ago, or sends a response that omits the References header — breaking thread grouping in every major email client — looks broken even if the underlying logic is correct. These failures are hard to catch in testing because they depend on real conversation state that unit tests do not model. The root cause is usually the same: the agent fetched the most recent message and replied to it in isolation, without access to the thread as a whole.


How MultiMail solves this

MultiMail exposes email conversations as first-class objects. Each thread has a stable thread_id and an ordered list of its emails. When your agent calls get_thread, it receives the full conversation — every email's id, sender, subject, and direction, not just the latest. To reply, you call reply_email against the email's id; MultiMail computes and attaches the RFC 2822 In-Reply-To and References headers for you, so downstream mail clients group the conversation correctly regardless of which client receives the reply.

1

Fetch the thread

Call get_thread with the mailbox_id and thread_id to retrieve every email in the conversation, ordered chronologically. Each entry includes the email's id, sender, subject, direction, and timestamp (the thread list omits bodies — read an email by id for full content). The response also surfaces the participant list, message_count, and whether there's an unanswered inbound email.

2

Load conversation history

The get_thread response includes a messages array with every message in the thread. Pass this ordered history to your LLM so it can draft a reply with full awareness of what has already been said, committed to, or asked — not just the most recent message.

3

Draft a contextual reply

Your agent generates a reply grounded in the full thread history. Because the complete conversation is available, the agent avoids repeating resolved items, surfaces only what is genuinely new, and matches the tone and commitments established earlier in the thread.

4

Send with correct reply headers

Call reply_email against the id of the specific email you are replying to (POST /v1/mailboxes/{mailbox_id}/reply/{email_id}). MultiMail resolves the thread, then constructs and attaches the In-Reply-To and References headers automatically — no manual header manipulation required in your agent code.

5

Track delivery and handle inbound replies

Webhooks fire on delivery confirmation, bounces, and inbound replies. The message.received payload carries the email_id; read that email to get its thread_id, then load the thread — so your agent can process the next message in the conversation reactively without polling check_inbox.


Try it with your agent

Pick your platform, copy the prompt, and paste it to your AI agent — it sets up MultiMail and builds the whole flow. Nothing to fill in.

1. Get MultiMail ready: read https://multimail.dev/llms.txt, connect the MCP server, create a free inbox, and set up a verified sender. 2. In Zendesk, use triggers with webhooks to detect new or updated tickets where the latest public comment needs an email reply, and use the Zendesk API to read the full ticket conversation before drafting. 3. For each qualifying ticket, match the requester, subject, ticket status, priority, and prior public comments to the correct MultiMail thread, then draft a reply that answers only the unresolved issue and avoids repeating earlier guidance. 4. Send replies through MultiMail in monitored mode so I can inspect outcomes while the workflow runs, and schedule follow-ups only when the ticket remains pending or awaiting customer response. 5. Ask me only for Zendesk admin access, the sending domain details, and the brand voice rules needed to go live.

What you get

RFC 2822 threading headers set automatically

MultiMail computes and attaches In-Reply-To and References headers on every reply_email call. Replies group correctly in Gmail, Outlook, Apple Mail, and any RFC 2822-compliant client without any header construction in your agent code.

Full conversation history in a single API call

get_thread returns every email in the thread ordered chronologically — id, sender, subject, direction, and timestamp. Read each email by id to pull its body, and your LLM receives the complete context it needs to write a coherent reply — not just the most recent message.

Stable thread IDs across inbound and outbound messages

Thread identity is tracked server-side. Whether the next message arrives from the customer or is sent by your agent, it is appended to the same thread object under the same thread_id. No client-side state or header parsing required.

Reactive processing via webhooks

Inbound reply webhooks carry the email_id; one read resolves its thread. For high-volume deployments handling thousands of conversations, your agent processes new replies reactively rather than polling check_inbox on an interval.

Works across all MCP clients and the REST API

get_thread and reply_email are available as MCP tools (Claude Desktop, Cursor, Windsurf) and as direct REST endpoints. Threading header logic is handled server-side identically across both paths.


Recommended oversight mode

Recommended
monitored
Thread-aware reply agents handle high volumes of conversational email where per-message approval creates unacceptable latency. Monitored mode lets agents send autonomously while routing every outbound message to a human reviewer who can intervene if the agent drifts off-context or misreads thread history. Start with gated_send during the first week of deployment to validate that thread context is being used correctly across varied thread lengths, then promote to monitored once reply quality is consistent.

Common questions

Does MultiMail thread emails sent from external clients correctly?
Yes. When an inbound email arrives with a References or In-Reply-To header matching an existing thread, MultiMail appends it to that thread automatically. Your agent does not parse headers itself — the inbound webhook gives you the email_id, and reading that email returns its resolved thread_id.
What happens if a customer reply accidentally starts a new thread?
If an inbound message has no matching thread reference, MultiMail creates a new thread for it. You can flag the new email for human review by calling set_tags (PUT /v1/mailboxes/{mailbox_id}/emails/{email_id}/tags) with a label like needs-review, or implement logic to detect suspiciously short threads that may be orphaned replies.
How many messages can a thread hold?
There is no hard cap on thread length. get_thread returns all messages in the thread. For long threads, consider passing only the most recent N messages to your LLM to stay within context window limits — the messages array is ordered chronologically so you can slice from the end.
Can I use get_thread with LangChain or CrewAI?
Yes. Wrap the REST calls for get_thread and reply_email (or the MultiMail MCP tools of the same name) as LangChain tools or CrewAI task actions. Pass the thread's emails list directly as the agent's conversation memory.
What oversight mode should I use while testing thread handling?
Use gated_send during initial development. This lets you inspect each reply before it reaches the recipient, making it easy to catch cases where the agent missed context from earlier in the thread or repeated already-resolved items. Promote to monitored once quality is consistent across threads of five or more messages.
Does the MCP server set threading headers correctly?
Yes. The reply_email MCP tool accepts mailbox_id and email_id (the email you're replying to) and delegates all header construction to the MultiMail API. You do not specify raw headers in MCP tool arguments — threading is managed server-side, identical to the REST and SDK paths.
How do I find the thread_id for an existing email?
For emails sent via send_email, the 202 response includes the thread_id assigned to the conversation. For inbound mail, the webhook gives you the email_id; read that email (read_email) and its response includes the thread_id. You can then call get_thread with that thread_id to load the whole conversation.

Explore more use cases

The only agent email with a verifiable sender

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