Inngest took the parts of writing a real application that always suck — queues, retries, cron, long-running jobs — and collapsed them into a single primitive: the event-driven function. It's the right partner for Lumbox, because inbound email is the event layer most agent backends are missing.
The wiring
Lumbox fires a webhook when mail arrives. Point that webhook at an Inngest event endpoint. Inngest's function handles the parsed email with full retry + observability.
// Point Lumbox webhook at: https://inn.gs/e/YOUR_INGEST_KEY
// Events emitted as "lumbox.email.received"
import { inngest } from "./client";
export const handleInboundEmail = inngest.createFunction(
{ id: "handle-inbound-email" },
{ event: "lumbox.email.received" },
async ({ event, step }) => {
const { from, subject, text, extracted } = event.data;
if (extracted.otp) {
await step.run("resolve-pending-signup", async () => {
return resolvePendingSignup(from, extracted.otp);
});
}
await step.run("log-to-crm", () => logEmail(from, subject, text));
},
);
Scheduled follow-ups
Use Inngest's step.sleep to schedule a follow-up email in a day, a week, a month. Lumbox handles the send, Inngest handles the durability.
export const followUp = inngest.createFunction(
{ id: "follow-up" },
{ event: "signup.completed" },
async ({ event, step }) => {
await step.sleep("wait-3-days", "3d");
await step.run("send-followup", () =>
lumbox.inboxes.send(AGENT_INBOX, {
to: event.data.email,
subject: "How's it going?",
text: "Checking in from your onboarding agent.",
}),
);
},
);