{"slug": "how-to-implement-human-in-the-loop-for-ai-emails", "title": "How to Implement Human-in-the-Loop for AI Emails", "summary": "A new human-in-the-loop workflow for AI-generated emails, demonstrated with Node.js and TypeScript using the Impri review API and nodemailer, replaces risky 'fire and forget' AI email sending with a controlled pipeline where an AI agent drafts, a human audits and edits, and only the approved version is sent. The implementation polls Impri for a human decision before executing the send command, ensuring production-ready fail-safe LLM agent deployment.", "body_md": "# How to Implement Human-in-the-Loop for AI Emails\n\n`approved`\n\nstatus.This approach transforms the AI workflow from a risky \"fire and forget\" system into a controlled pipeline: the agent drafts, a human audits/edits, and only then does the code execute the send command.\n\n## The Logic Flow\n\nInstead of a direct call to an SMTP server, the agent follows this sequence:\n\n1. **Draft Generation:** The agent produces the content.\n\n2. **External Holding:** The draft is pushed to a review system (like Impri) via API.\n\n3. **Human Intervention:** A reviewer reads the draft, makes necessary edits to the body or subject, and hits \"Approve.\"\n\n4. **Execution:** The system polls for the decision; if approved, it sends the *final edited version*, not the original AI draft.\n\n## Real-world Implementation: Node.js & TypeScript\n\nHere is a practical tutorial on how to build this approval gate using `nodemailer`\n\nand a review API.\n\n``` python\nimport nodemailer from \"nodemailer\";\n\nconst IMPRI_KEY = process.env.IMPRI_API_KEY!;\nconst IMPRI_BASE = \"https://api.impri.dev\";\n\nasync function sendWithApproval(opts: {\n to: string;\n subject: string;\n body: string;\n expiresIn?: number; // seconds; default 3600\n}): Promise<\"approved\" | \"rejected\" | \"expired\"> {\n // 1. Push the draft to review\n const push = await fetch(`${IMPRI_BASE}/v1/actions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${IMPRI_KEY}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n kind: \"email.send\",\n title: `Email to ${opts.to}: ${opts.subject}`,\n preview: {\n format: \"markdown\",\n body: `**To:** ${opts.to}\\n**Subject:** ${opts.subject}\\n\\n---\\n\\n${opts.body}`,\n },\n editable: [\"preview.body\"], \n expires_in: opts.expiresIn ?? 3600,\n }),\n });\n\n if (!push.ok) throw new Error(`Push failed: ${push.status}`);\n const { id: actionId } = await push.json();\n\n // 2. Poll until human decision\n let result: { status: string; decision?: { final_preview?: { body: string } } };\n for (;;) {\n const poll = await fetch(`${IMPRI_BASE}/v1/actions/${actionId}`, {\n headers: { Authorization: `Bearer ${IMPRI_KEY}` },\n });\n result = await poll.json();\n if (result.status !== \"pending\") break;\n await new Promise((r) => setTimeout(r, 10_000));\n }\n\n if (result.status !== \"approved\") {\n return result.status as \"rejected\" | \"expired\";\n }\n\n // 3. Send the human-approved version\n const approvedBody = result.decision!.final_preview!.body;\n\n const transporter = nodemailer.createTransport({\n host: process.env.SMTP_HOST,\n port: 587,\n auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },\n });\n\n await transporter.sendMail({\n from: process.env.SMTP_FROM,\n to: opts.to,\n subject: opts.subject,\n text: approvedBody,\n });\n\n // 4. Update audit log\n await fetch(`${IMPRI_BASE}/v1/actions/${actionId}/result`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${IMPRI_KEY}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ status: \"success\" }),\n });\n\n return \"approved\";\n}\n```\n\nBy treating human approval as a mandatory API response rather than a prompt suggestion, you create a fail-safe LLM agent deployment that is actually production-ready.\n\n[Next Mage-Flow: 4B Params vs 32B Giants →](/en/threads/2450/)", "url": "https://wpnews.pro/news/how-to-implement-human-in-the-loop-for-ai-emails", "canonical_source": "https://promptcube3.com/en/threads/2466/", "published_at": "2026-07-23 18:01:33+00:00", "updated_at": "2026-07-24 02:05:34.212261+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "developer-tools"], "entities": ["Impri", "nodemailer", "Node.js", "TypeScript"], "alternates": {"html": "https://wpnews.pro/news/how-to-implement-human-in-the-loop-for-ai-emails", "markdown": "https://wpnews.pro/news/how-to-implement-human-in-the-loop-for-ai-emails.md", "text": "https://wpnews.pro/news/how-to-implement-human-in-the-loop-for-ai-emails.txt", "jsonld": "https://wpnews.pro/news/how-to-implement-human-in-the-loop-for-ai-emails.jsonld"}}