Email infrastructure for Inngest workflows

MultiMail gives Inngest functions auditable, agent-safe email with graduated oversight — from gated approval to fully autonomous sending.


Inngest orchestrates durable, event-driven functions with built-in retries, fan-out, and scheduled execution. When those functions send email — onboarding sequences, lifecycle alerts, transactional confirmations — you need guarantees that Inngest itself doesn't provide: identity verification, human approval gates, and a full audit trail of who sent what and when.

MultiMail's REST API integrates directly inside any Inngest step. Each `step.run()` block can call `send_email`, `decide_email`, or `list_pending` without any additional SDK — just a `fetch` call with your `mm_live_...` bearer token. Inngest handles retry logic and durable state; MultiMail handles email identity, deliverability, and oversight.

The combination is especially useful for AI-driven workflows: an Inngest function can draft and queue emails through MultiMail's `gated_send` mode, pause execution until a human approves via `decide_email`, then resume and record the outcome — all within a single durable function run.

Built for Inngest developers

Human approval without polling hacks

MultiMail's `gated_send` mode queues outbound email and fires an approval webhook when a human acts. Your Inngest function can `step.waitForEvent()` on that webhook, eliminating manual polling and keeping the function durable across approval delays of minutes or days.

Per-step audit trail

Every MultiMail API call from inside a `step.run()` block is recorded with the message ID, sender identity, oversight mode, and decision outcome. Because Inngest replays steps on retry, MultiMail's idempotency keys prevent duplicate sends even when a step runs more than once.

Identity verification before sending

MultiMail cryptographically verifies the sending domain before delivery. Inngest functions often run in background contexts where the originating identity is ambiguous — MultiMail makes the verified sender explicit on every outbound message, satisfying CAN-SPAM and DMARC alignment requirements.

Graduated autonomy across workflow stages

You can set different oversight modes per Inngest function. An early-stage onboarding function can run in `gated_all` while a mature transactional receipt function runs in `autonomous` — both use the same MultiMail mailbox and API key.

Inbound email as Inngest events

MultiMail webhooks deliver inbound email as JSON payloads that map directly onto Inngest event schemas. A `multimail/email.received` event can trigger a classification function, a support ticket function, or an agent response function without any custom webhook adapter.


Try it with your agent

No code, no dashboard. Paste this to your AI agent — it connects MultiMail, creates an inbox, and builds the flow for you.

1. Get MultiMail ready before writing code: read https://multimail.dev/llms.txt, connect the hosted MultiMail MCP server exactly as documented there, create a free inbox through the MCP flow, activate it, set up a verified sending domain, and configure the inbox oversight mode to gated_send. 2. Wire MultiMail into the Inngest agent using real AgentKit primitives: use @inngest/agent-kit, define the email agent with createAgent, and add MultiMail through the agent’s mcpServers configuration using the streamable-http transport and the hosted MCP server details from llms.txt. Run this agent from an Inngest function, and put agent execution inside step.run so each email workflow is durable, retried, and visible in Inngest traces. 3. Give the agent only these email capabilities from MultiMail’s MCP tools: check the inbox for relevant incoming mail, compose a reply as a draft for review, and send or schedule email. Do not add any direct HTTP calls, custom MultiMail endpoints, webhook assumptions, or invented headers. 4. Send a test email through the Inngest function to an address I control. The message should identify itself as a MultiMail plus Inngest test, include the inbox address, and report whether MultiMail returned the send as pending approval. 5. Keep the first run and all initial production runs in gated_send. The agent may prepare and request sends, but I must review and approve before anything is delivered. After the test passes, document where to switch later to monitored or autonomous, but do not enable either mode now.

Step by step

1

Install Inngest and get a MultiMail API key

Install the Inngest SDK and create a MultiMail account to get your `mm_live_...` API key. You will call the MultiMail REST API directly — no additional package needed.

2

Create a MultiMail mailbox

Create the mailbox your Inngest functions will send from. You can use a `@multimail.dev` subdomain or bring your own domain.

3

Send email from a step

Call `https://api.multimail.dev/send_email` inside a `step.run()` block. Pass an `Idempotency-Key` header derived from the Inngest event ID so retries don't duplicate sends.

4

Forward MultiMail webhooks as Inngest events

In your webhook endpoint, forward the MultiMail payload to Inngest using `inngest.send()`. This lets Inngest functions react to inbound email and approval decisions as typed events.

5

Set your oversight mode per function

Choose the right `oversight_mode` for each Inngest function based on risk. Transactional receipts can use `autonomous`; agent-drafted outreach should start with `gated_send` until you have confidence in the output quality.


Common questions

Does MultiMail have a native Inngest integration or SDK?
No. MultiMail integrates with Inngest via its REST API. You call `https://api.multimail.dev` endpoints directly inside `step.run()` blocks using `fetch`. This keeps the integration lightweight and compatible with any Inngest deployment (Inngest Cloud, self-hosted, or local dev).
What happens if MultiMail returns an error and Inngest retries the step?
Pass an `Idempotency-Key` header on every `send_email` call, derived from the Inngest event ID and step name. MultiMail will deduplicate requests with the same key within 24 hours, so Inngest retries are safe and won't produce duplicate emails.
How do I implement human-in-the-loop approval without polling?
Send the email with `oversight_mode: 'gated_send'`, then use `step.waitForEvent('multimail/email.decided', { timeout: '48h' })`. Configure your MultiMail webhook to POST approval events to your webhook endpoint, which forwards them to Inngest via `inngest.send()`. The function resumes automatically when the event arrives.
Can I use MultiMail with Inngest's fan-out (step.sendEvent)?
Yes. A parent Inngest function can fan out to child functions via `step.sendEvent()`, and each child can independently call the MultiMail API. Use distinct idempotency keys per child (include the fan-out index or child event ID) to ensure each send is deduplicated correctly.
What oversight mode should I use for transactional email like receipts and password resets?
Use `autonomous` for transactional email where the content is deterministic and machine-generated. Reserve `gated_send` or `gated_all` for agent-drafted content where a human should review before delivery.
How do I test MultiMail calls in Inngest's local dev environment?
Use a `mm_test_...` API key from the MultiMail dashboard. Test keys route through MultiMail's sandbox: emails are recorded and visible in your dashboard but are never delivered to real recipients. The same REST API endpoints and response shapes apply, so no code changes are needed when switching from test to live.

Explore more

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.