FlowKit

Generating AI email reply drafts with n8n: the Gmail Draft node explained

Published 17 July 2026 · 6 min read

Replying to a business email usually follows the same handful of patterns: acknowledge receipt, propose a time slot, ask for a detail, confirm you're on it. These are low-value-add replies that still eat time — and that it would be reckless to let an LLM send without review. The right n8n architecture for this isn't automatic sending, it's an automatic draft: the model writes the reply, the draft lands in your Gmail, you review it and click Send. Here's how to build this workflow with the Gmail node, including the threading pitfalls that rarely make it into tutorials.

Why a draft, not a direct send

The most tempting automation — email received, reply generated, reply sent — is also the riskiest. An LLM can invent a price that no longer applies, confirm an availability that isn't actually yours, or misread the tone of a complaint. On an email triage or a digest, a misclassification just means one more review pass. On a reply sent straight to a client, a hallucination becomes a commitment made in your name.

A draft changes the nature of the risk: the worst-case scenario becomes "a badly written draft you delete," not "a wrong email that already reached a client." That's exactly the trade-off behind the "Generate AI reply drafts in Gmail" workflow in the AI Inbox Pack (€79): the AI prepares, you decide.

The four-node architecture

The workflow fits in a short chain:

  1. Gmail Trigger — watches the inbox and fires on every new message, carrying subject, sender, snippet, and crucially the threadId.
  2. Filter — discards noise before spending a single LLM call: no-reply senders, emails containing an unsubscribe link, newsletters.
  3. LLM chain (Basic LLM Chain) with a sub-model node (Claude or GPT) — drafts the reply following a strict prompt.
  4. Gmail node, Draft resource, Create operation — drops the generated text as a draft, attached to the original thread via threadId.

If you don't already have email triage upstream, start with our guide on automating email triage with AI and n8n: wiring this draft workflow onto an existing classification (only drafting for the "client" category, for instance) avoids generating drafts for emails that don't need one.

Step 1 — Filter before drafting

Drafting a reply for every incoming email wastes LLM calls and fills your drafts folder with noise. A Filter node, right after the trigger, applies two or three cumulative conditions:

  • The sender address doesn't contain no-reply or noreply.
  • The message body doesn't contain an unsubscribe link (a near-certain sign of a newsletter or an automated notification).
  • Optional: the to field matches your direct address, to skip emails where you're only CC'd.

This filter takes seconds to write and catches most false positives before the model is even involved.

Step 2 — A prompt that preserves caution

The prompt is where the workflow's reliability is decided. Three non-negotiable rules:

You draft a professional reply in [your language], to be inserted into the following conversation thread:

From: {{ $json.from }}
Subject: {{ $json.subject }}
Received message: {{ $json.text }}

Instructions:
- Direct, professional tone, 1 to 3 paragraphs maximum.
- Always end with a clear next step (question, confirmation, date).
- If any information is unknown to you (price, deadline, availability), insert a placeholder like [PRICE] or [DATE] — never invent a commitment.
- Signature: {{ $json.signature }}

The critical point is the third instruction. A well-guided model writes "I can confirm a delivery time of [DELAY] business days" instead of inventing a plausible number. That's the placeholder you fill in in three seconds during review, versus an embarrassing correction if the email had already gone out. Wire the model (Claude or GPT) as an ai_languageModel sub-node on the chain — see our guide on connecting Claude or GPT to n8n if that's not set up yet.

Step 3 — Create the draft with the Gmail node

On the Gmail node, configure:

  • Resource: Draft
  • Operation: Create
  • Subject: Re: {{ $json.subject }}
  • Message: the LLM's output ({{ $json.output }} or equivalent depending on your parser)
  • Email Type: Text (or HTML if your prompt generates lightweight HTML)

For the draft to slot into the existing conversation instead of creating a new, isolated thread, fill in the Thread ID field with the threadId value coming from the Gmail Trigger. That's what separates a draft that shows up cleanly under the received message from one that lands as a brand-new email with no context.

The threading gotcha to know before going to production

Here's the detail few tutorials mention: even with threadId set correctly, creating a draft through the Gmail API doesn't always add the References and In-Reply-To headers that a mail client uses to visually attach a message to its thread. This is a behavior documented by the n8n community, not a misconfiguration on your end.

In the large majority of cases the draft stays correctly attached to the thread and shows up where you'd expect. But before wiring this workflow onto a production inbox, test it on a few real exchanges in your own account: open the generated draft in Gmail and check that it appears under the original message without duplicating the thread. If the behavior doesn't satisfy you, one alternative is to skip pre-filling the Re: subject and let the user manually hit "Reply" on the received message, then paste in the generated text — less automatic, but with zero threading ambiguity.

Step 4 — Notify without forcing a read

A silent draft sitting in a folder you open once a week loses all its value. Add a lightweight notification branch — Slack or Telegram — right after the draft is created:

✉️ Draft ready: reply to {{ $json.from }} ({{ $json.subject }})

No need for the full content in the notification: the goal is just to flag that a draft is waiting, not to duplicate the Gmail interface inside Slack.

Combining it with an urgency score

If you're already running an email classification with a priority level (see the urgency scoring workflow from the same pack), only generate drafts for the categories that warrant it — typically "client" and "administrative" — and let invoices or notifications follow their own path. That cuts both the volume of drafts to review and the token cost, since only emails that genuinely call for a written reply trigger the LLM chain.

The mistakes that make this workflow unusable

  • Drafting for everyone: without an upstream filter, the drafts folder fills up with proposed replies to newsletters. You stop checking it within a week.
  • A prompt with no placeholder: a model left to its own devices invents plausible numbers instead of flagging an unknown — the worst possible outcome for a draft meant to save time safely.
  • Jumping straight to automatic sending because "the drafts have always looked fine" after a few tests: the temptation is real, but a sample of ten emails doesn't cover the edge cases (a complaint, a negotiation, an ambiguous situation) where a hallucination gets expensive.
  • Forgetting to handle Gmail node errors (API quota, expired token): add an Error Workflow as described in our guide on handling errors in n8n, so you're notified if the draft-creation node fails silently.

Starting from the ready-made workflow

This guide rebuilds exactly the architecture of the "Generate AI reply drafts in Gmail" workflow, one of the four workflows in the AI Inbox Pack (€79): IMAP triage, urgency scoring, daily digest, and Gmail draft generation, with the placeholder-driven prompt already tuned and the anti-newsletter filter in place. If you want the full FlowKit ecosystem — inbox, RAG assistant, and compliance — the Complete FlowKit Bundle (€269) bundles all three packs.

Drafting a reply instead of sending it directly isn't a half-measure — it's the one setting that lets AI do the heavy lifting without ever giving it the final word on what goes out under your name.

FAQ

Frequently asked questions

Can the workflow send the reply directly instead of creating a draft?

Technically yes: you'd just swap the Draft resource's Create operation for the Message resource's Send operation. It's strongly discouraged for customer replies — an LLM can hallucinate a price, a deadline, or a commitment, and the mistake goes out with zero human filter. Reserve automatic sending for generic acknowledgements with no variable content.

Why does my reply draft break the Gmail conversation thread?

This is a documented behavior of the Gmail node: even with threadId set correctly, a draft created through the API doesn't always add the References and In-Reply-To headers that let Gmail visually attach it to the existing thread. In most cases the draft still attaches correctly to the threadId and shows up inside the conversation, but test it systematically on your own account before going to production — on some accounts, a thread can appear duplicated.

Should I use Claude or GPT to draft the replies?

Both work well through the sub-model node wired to the LLM chain; the choice mostly comes down to perceived writing quality in your target language and your billing preferences. Claude tends to follow explicit caution instructions more reliably ("never invent a price"), which matters on a task whose output potentially goes out to a client.

AI Inbox Pack

€79