Triage support emails and draft replies for human review

Sharing a workflow I built for support inboxes that were drowning in cold-start tickets: every email needed a human to read it, figure out category and urgency, then write a reply from scratch before anything could happen. Task: Sharing a workflow I built for support inboxes that were drowning in cold-start tickets: every email needed a human to read it, figure out category and urgency, then write a reply from scratch before anything could happen. Here is the chain: new email trigger, AI classifies it (billing, technical, complaint, etc.), rates urgency, summarizes in one line, and drafts a reply. Everything logs to a sheet for reporting, then the classification and draft land in Slack for a person to review before sending. Deliberately kept a human in the loop on sending. The AI draft is good, but a fully automated reply to a real customer is a different bar than a good first draft. 5 nodes, about 20 minutes to wire up with an OpenAI compatible key, Gmail, Sheets, and Slack. Workflow JSON: Nice approach. I’d keep the AI classification and the actual sending step completely separate, especially since a human is still approving the reply. I’d structure it roughly like: Email Trigger → Normalize → AI Classification → Validate JSON → Priority/Category Routing → Draft Reply → Human Approval → Send For the AI output, I’d use a strict schema such as: Then validate the output before using category or priority for routing. This prevents an unexpected AI response from breaking the workflow. I’d also store the original message ID/thread ID with the draft. That makes it easier to reply in the correct email thread and prevents duplicate processing if the trigger is retried. For the human approval step, I’d probably make the approval action update a status such as approved, rejected, or needs_edit rather than relying only on a boolean. That gives you a clean separation between AI interpretation → deterministic routing → human approval → sending. One thing I’d be interested in testing is whether priority should be entirely AI-generated or whether some hard rules should override the AI, e.g. billing/security keywords always forcing high priority. Sharing a workflow I built for support inboxes that were drowning in cold-start tickets: every email needed a human to read it, figure out category and urgency, then write a reply from scratch before anything could happen. Here is the chain: new email trigger, AI classifies it (billing, technical, complaint, etc.), rates urgency, summarizes in one line, and drafts a reply. Everything logs to a sheet for reporting, then the classification and draft land in Slack for a person to review before sending. Deliberately kept a human in the loop on sending. The AI draft is good, but a fully automated reply to a real customer is a different bar than a good first draft. 5 nodes, about 20 minutes to wire up with an OpenAI compatible key, Gmail, Sheets, and Slack. Nice one, and good call keeping a human on the send. Two things I’d fix before running this in production: The Code node uses .first(), so if two emails arrive in the same poll, only one gets processed. Map over $input.all() instead. With simple: false, Gmail’s from is an object. Use from.text, or you’ll see [object Object] in Slack. Also worth adding a try/catch around JSON.parse and an IF node to drop spam before it reaches Slack. Next step I’d suggest: swap the Slack message for Send and Wait with an Approve button that triggers a Gmail reply in the thread. Same human check, but no copy-pasting. Related topics; tools: n8n. Human role: Everything logs to a sheet for reporting, then the classification and draft land in Slack for a person to review before sending.; limitations: Prerequisites include n8n, OpenAI-compatible API key, Gmail, Sheets, and Slack credentials. Commenters noted technical flaws: the Code node uses .first() which drops emails if multiple arrive in one poll, and Gmail's 'from' field requires .text to avoid '[object Object]' in Slack. Proposed improvements include adding JSON validation, spam filtering, and using 'Send and Wait' for approval instead of manual copy-paste..

Tools

n8n

Published on Agent Work Atlas:

Overview

Sharing a workflow I built for support inboxes that were drowning in cold-start tickets: every email needed a human to read it, figure out category and urgency, then write a reply from scratch before anything could happen.

Workflow

Sharing a workflow I built for support inboxes that were drowning in cold-start tickets: every email needed a human to read it, figure out category and urgency, then write a reply from scratch before anything could happen. Here is the chain: new email trigger, AI classifies it (billing, technical, complaint, etc.), rates urgency, summarizes in one line, and drafts a reply. Everything logs to a sheet for reporting, then the classification and draft land in Slack for a person to review before sending. Deliberately kept a human in the loop on sending. The AI draft is good, but a fully automated reply to a real customer is a different bar than a good first draft. 5 nodes, about 20 minutes to wire up with an OpenAI compatible key, Gmail, Sheets, and Slack. Workflow JSON: Nice approach. I’d keep the AI classification and the actual sending step completely separate, especially since a human is still approving the reply. I’d structure it roughly like: Email Trigger → Normalize → AI Classification → Validate JSON → Priority/Category Routing → Draft Reply → Human Approval → Send For the AI output, I’d use a strict schema such as: Then validate the output before using category or priority for routing. This prevents an unexpected AI response from breaking the workflow. I’d also store the original message ID/thread ID with the draft. That makes it easier to reply in the correct email thread and prevents duplicate processing if the trigger is retried. For the human approval step, I’d probably make the approval action update a status such as approved, rejected, or needs_edit rather than relying only on a boolean. That gives you a clean separation between AI interpretation → deterministic routing → human approval → sending. One thing I’d be interested in testing is whether priority should be entirely AI-generated or whether some hard rules should override the AI, e.g. billing/security keywords always forcing high priority. Sharing a workflow I built for support inboxes that were drowning in cold-start tickets: every email needed a human to read it, figure out category and urgency, then write a reply from scratch before anything could happen. Here is the chain: new email trigger, AI classifies it (billing, technical, complaint, etc.), rates urgency, summarizes in one line, and drafts a reply. Everything logs to a sheet for reporting, then the classification and draft land in Slack for a person to review before sending. Deliberately kept a human in the loop on sending. The AI draft is good, but a fully automated reply to a real customer is a different bar than a good first draft. 5 nodes, about 20 minutes to wire up with an OpenAI compatible key, Gmail, Sheets, and Slack. Nice one, and good call keeping a human on the send. Two things I’d fix before running this in production: The Code node uses .first(), so if two emails arrive in the same poll, only one gets processed. Map over $input.all() instead. With simple: false, Gmail’s from is an object. Use from.text, or you’ll see [object Object] in Slack. Also worth adding a try/catch around JSON.parse and an IF node to drop spam before it reaches Slack. Next step I’d suggest: swap the Slack message for Send and Wait with an Approve button that triggers a Gmail reply in the thread. Same human check, but no copy-pasting. Related topics

Reported result

The source does not report measured outcomes, success rates, or time savings. It only states the workflow was built in about 20 minutes with 5 nodes. No evidence proves execution results or business impact. A measurable acceptance check would be: track the percentage of AI drafts accepted without edit versus those requiring significant revision over 100 tickets.

Human role

Everything logs to a sheet for reporting, then the classification and draft land in Slack for a person to review before sending.

Limitations

Prerequisites include n8n, OpenAI-compatible API key, Gmail, Sheets, and Slack credentials. Commenters noted technical flaws: the Code node uses .first() which drops emails if multiple arrive in one poll, and Gmail's 'from' field requires .text to avoid '[object Object]' in Slack. Proposed improvements include adding JSON validation, spam filtering, and using 'Send and Wait' for approval instead of manual copy-paste.

Try it

Build an n8n workflow to triage support emails for [replaceable: business context, e.g., SaaS billing]. Inputs: Gmail inbox [replaceable: email address], OpenAI API key, Google Sheet ID [replaceable: sheet name], Slack channel ID [replaceable: channel]. Steps: 1. Create a Gmail Trigger node polling every minute. 2. Add an HTTP Request node to OpenAI with a system prompt to classify category (billing, technical, complaint, spam), urgency (low, medium, high), summarize in one sentence, and draft a polite reply. 3. Add a Code node to parse the JSON response, ensuring you map over $input.all() to handle multiple emails and use from.text for the sender. 4. Add a Google Sheets node to log From, Subject, Category, Urgency, Summary, and Date. 5. Add a Slack node to post the summary and draft for review. 6. Do NOT add an auto-send node. 7. Run a dry test with 3 sample emails. 8. Verify the Slack message displays correctly and the Sheet logs data. 9. Confirm with a human reviewer that the drafts are usable before considering the workflow complete. Handle errors by adding a try/catch in the Code node and an IF node to drop spam before Slack.

Original source

Source reports are not independently verified. Publication date is the catalog publication date, not the original article date.

More cases · Marketing & sales