How-to · Automate

How to build an n8n workflow that triages your inbox with Claude, labels it and drafts replies

An n8n workflow that reads new mail, asks Claude what each one is, labels it, drafts a reply for the ones that need one and logs every decision to a sheet. It never sends anything, and we show the five settings that quietly break it.

SansserTested by us
Advanced40 min9 steps
You'll usen8nGmailClaudeGoogle Sheets
The problem

I want AI to sort my inbox, not send anything. Automate your inbox with n8n and Claude: Gmail trigger settings, an AI Agent that returns strict JSON, labels, draft replies, loop guards and human review.

Step 1

Decide what the workflow is allowed to do

Before we build anything we write down what the workflow may do, because the thing that makes inbox automation safe is not the model, it is the list of actions it cannot take. Our list has four things on the allowed side: read new mail, add a label, create a draft, and write one row per email to a Google Sheet. The forbidden side is longer: send, reply, forward, archive, delete, mark as spam, or touch anything already labelled.

The reason is simple. A classifier is wrong a few percent of the time, even a good one. A wrong label costs us ten seconds. A wrong email sent to a client costs us the client. So the human stays the one who presses send, and the workflow only gets the inbox into a state where that takes five minutes instead of an hour.

Decide the labels now, and keep it to four to six. More than that and the model starts splitting hairs, and so do you when you review it. Ours are urgent, needs-reply, fyi, newsletter and receipt. Every email gets exactly one. We also decide who gets an automatic draft: only needs-reply, and only from people outside our own domain.

63 unread. Three of them need an answer today. We find those three at eleven, after reading the other sixty.
63 emails, 4 labelled triage/urgent, 11 drafts waiting in Drafts, one row per email in the sheet. We read the four, check the drafts, press send on the good ones.
Step 2

Make the labels and the sheet before you touch n8n

Make the Gmail labels first. Open Gmail, scroll the left sidebar to the bottom and click Create new label. Make one called ai-triaged. This is the guard label. The trigger will skip anything that carries it, and the last node in the workflow applies it, so an email can only go through once. Then make one label per category, with a prefix so they sort together: triage/urgent, triage/needs-reply, triage/fyi, triage/newsletter, triage/receipt.

Then make the sheet. One Google Sheet, one tab, a header row with these columns: date, from, subject, label, confidence, reason, draft_created, message_id. The sheet is the audit trail. When the model gets something wrong, the reason column tells us why, and that is what we use to fix the prompt in step 4.

In n8n, open Credentials and add a Gmail OAuth2 credential and a Google Sheets OAuth2 credential. Both use the same Google Cloud project, so set up the OAuth consent screen once and enable both the Gmail and Sheets APIs on it. The n8n docs for each node link to the exact steps. On n8n cloud the credential dialogs offer a sign-in button and most of this is done for you.

Before the first node
Step 3

Set the Gmail Trigger the way that does not miss mail

The Gmail Trigger node is where most triage workflows silently break, and a thread on the n8n community forum from 2 August 2026 lists the three settings that did it to one builder. We hit all three too. Set the node like this.

Event: Message Received. Poll Time: every 5 minutes is fine for a personal inbox, every minute if you want it to feel instant. Simplify: turn it off. With Simplify on, the trigger returns only the snippet, the first hundred-odd characters, and your model classifies a sentence instead of an email. Off, you get the full text and the headers.

Under Filters, set Search to this Gmail query: -from:me -label:ai-triaged. The first part excludes the mail we sent ourselves. The second excludes anything the workflow has already processed. Set Read Status to Unread and read. The default of unread only sounds right until you open an email on your phone before the poll runs, and that email is skipped for ever. Leave Max Emails per Poll at the default of 10 while testing. It goes up to 50, and you will want that on the first run over a backlog.

Do not add a Label filter here. The guard works through the search string, and a label filter on top of it only narrows the poll in ways you did not mean.

n8nn8n · Gmail Trigger
Gmail TriggerParameters
Event
Message Received
Poll Time
Every 5 minutes
SimplifyOff, or the model only sees the snippet
Filters · Search
-from:me -label:ai-triaged
Filters · Read StatusNot unread only: mail you opened on your phone would be skipped
Unread and read
Max Emails per PollUp to 50 for the first run over a backlog
10
Recreated from the node as documented on 28 October 2026.

TipTest the search string in Gmail's own search box first. If it returns the mail you expect there, it will in the trigger.

Step 4

Write the prompt and the schema with the builder

Now the prompt. We write it once, with the builder below, and paste it into two places in the next step: the System Message of the AI Agent and the JSON example of the Structured Output Parser. Fill in your labels with a one-line definition each. The definitions do the work. "urgent: a real person needs something from us today" classifies better than "urgent: important emails", because the model can test the first sentence against the email and cannot test the second.

Say who gets an automatic draft. Keep it narrow at first: people outside our company who asked a question. Pick a tone. Add one escalation rule, the thing that always counts as urgent no matter what the email looks like, such as any mention of an overdue invoice or a contract.

The builder also gives you the Gmail search string from step 3 and the JSON that the parser expects. The JSON has five fields and we keep it that way. Every field you add is one more way for the model to produce something the parser rejects. The confidence number is not calibrated and never will be, but it is a useful sort key in the sheet: the low-confidence rows are the ones to read first on Friday.

Triage prompt and schema
Your text
Step 5

Add the AI Agent and make it return strict JSON

Add an AI Agent node after the trigger. Recent n8n versions use the Tools Agent, and that is what we want. Set Prompt (User Message) to Define below and give it an expression that puts the email in front of the model with clear markers: the subject, the sender, then the body. If the body is long we cut it at 6,000 characters; a newsletter does not need its footer classified. Pick the field names from the trigger's output panel rather than typing them, because they differ between Simplify on and off. Ours, with Simplify off, look like this:

Subject: {{ $json.subject }}
From: {{ $json.from.text }}
Body:
{{ ($json.text || '').slice(0, 6000) }}

Open Options, add System Message, and paste the first block from the builder. Then turn on Require Specific Output Format. A new connector appears under the node for an output parser. Add a Structured Output Parser there, choose the JSON Example schema type and paste the second block from the builder. The parser turns the example into a schema and rejects answers that do not match it. If you prefer to write a JSON Schema by hand, do, but do not use $ref; the node does not resolve it.

Set Max Iterations in Options to 3. The default is 10, and an agent with no tools that cannot satisfy the parser will loop ten times at your expense before it fails. Three is enough for a retry and still cheap. The result arrives in the next node under output, so a label is {{ $json.output.label }}.

n8nn8n · AI Agent
AI AgentParameters
Agent
Tools Agent
Prompt (User Message)
Define below
PromptSubject, From, Body as an expression
Subject: {{ $json.subject }} …
Require Specific Output FormatAdds the Output Parser connector under the node
Options · System MessagePasted from the builder in step 4
You triage email for a small team…
Options · Max IterationsDefault is 10
3
Recreated from n8n, October 2026. Labels as they appear in the app.
Step 6

Connect Claude as the model, and read this before you pick one

Click the Model connector under the agent and add Anthropic Chat Model. Create an Anthropic credential with an API key from the Claude Console. Then pick the model. For classification we use claude-haiku-5-5: it is the cheapest current model at $0.10 per million input tokens and $0.50 per million output tokens, and triage is a task it does as well as the bigger ones. For the draft-writing agent in step 7 we use claude-sonnet-5-5 at $2 and $10.

Under Options turn on Prompt Caching and choose 5 Minutes. The system message is the same for every email, so after the first call it is read from cache at a fraction of the price. With the 1 Hour choice the cache survives quiet spells, which suits a five-minute poll on a slow inbox.

Two warnings, both true as of 28 October 2026. First, the n8n docs page for this node lists model names that are out of date, so pick the model from the dropdown the node loads from the API, or type the id, rather than copying from the docs. Second, there is an open issue on the n8n repository, number 42209, filed 26 October 2026: version 1.5 of the node sends a thinking disabled parameter that claude-sonnet-5-5 rejects with a 400 error. If your Sonnet calls fail with a 400 and your Haiku calls do not, that is the issue, not your prompt. Read the thread for the current state before you change anything else.

n8nn8n · Anthropic Chat Model
AI AgentModelAnthropic Chat Model
Credential to connect with
Anthropic account
Modelclaude-sonnet-5-5 for the draft agent in step 7
claude-haiku-5-5
Options · Prompt Caching5 Minutes, or 1 Hour on a slow inbox
Model list and the open 400 issue (#42209) checked on 28 October 2026. If the dropdown and the docs disagree, trust the dropdown.
Step 7

Route by label: add the label, log the row, draft only where asked

Add a Switch node after the agent. Use Rules mode with one rule per label, each comparing {{ $json.output.label }} to the label name, and give every output a name so the canvas stays readable. Every branch then does the same two things in the same order: a Gmail node with Resource Message and Operation Add Label that adds the triage label, then a Google Sheets node with Operation Append Row that writes the row with the fields from the output and the message id.

The needs-reply branch gets one more thing in the middle: a second AI Agent with claude-sonnet-5-5 as its model and the draft prompt below as its system message. It takes the email and the triage reason and writes a reply. Its output goes to a Gmail node with Resource Draft and Operation Create, with the subject prefixed Re: and the thread id from the trigger so the draft sits inside the conversation. Nothing in this workflow uses the Send or Reply operations, and we suggest you search the exported workflow JSON for the word send before you activate it.

The urgent branch adds an alert. A Slack message or a push notification works, and it should contain the sender, the subject and the one-line reason, nothing more. The very last node on every branch is a Gmail Add Label with ai-triaged. It goes last on purpose: if anything before it fails, the email is picked up again on the next poll.

System Message · the draft agent (claude-sonnet-5-5)
Tone: warm and short.

Write a reply to the email below on behalf of our team. Answer only what was asked. If we need to check something before we can answer, say we will come back within a day and do not invent a date. Never promise a price, a discount or a delivery date. Do not mention that this was drafted by an AI. Sign off with our first name only.

Output the reply text and nothing else: no subject line, no quoted email, no notes to us.

TipPut the triage reason in the draft agent's prompt too. A draft that knows why the email was flagged answers the right question.

Step 8

Add the guards, then test with Execute workflow

Now the guards that keep this from running twice or running wild. The first you already have: the trigger skips anything labelled ai-triaged and the label is applied last. The second is the -from:me in the search, so our own sent mail never comes back round. The third is order: if you want the workflow to mark mail as read, do it after the draft is created, never before, or a failure between the two leaves you with a read email, no draft, and nothing that will ever touch it again.

On the Anthropic model node open Settings and turn on Retry On Fail, with three tries and a thirty-second wait between them. An overloaded response from the API is normal for a few seconds at a time and a retry fixes it. Give the call a timeout of 60 seconds so a stuck request does not hold the poll.

Then make a second small workflow that starts with an Error Trigger node and sends you a message with the workflow name and the error. Point the triage workflow at it in its settings. Without this a broken workflow fails silently and you find out in a week.

Test with the Execute workflow button, but know that a manual run fetches recent mail without the poll's memory, so it can process emails the live workflow already handled. Test on a label with two or three emails, check the sheet and the drafts, then activate. When something looks wrong, the tree below is the order we check.

Step 9

Know what it costs and review it weekly

The cost is low enough that the real budget is your attention, but run the numbers so you know. The calculator uses the current prices for claude-haiku-5-5 and claude-sonnet-5-5 and assumes every email costs about 1,200 input tokens, which covers the system message, the headers and a typical body, and that a classification answer is about 80 tokens. Drafts cost more because Sonnet reads the email again and writes about 300 tokens. Prompt caching takes the system message part of the input down further, so treat the result as a ceiling.

Then the review habit, which is the part that makes the system get better instead of slowly worse. Once a week, open the sheet. Sort by confidence, lowest first. Read twenty rows. For each wrong label, do not add a rule to the prompt; rewrite the definition of the label it should have been, in a form the model can test. Then look at the drafts you did not use and ask why. Usually it is tone, and the tone line in the draft prompt is one sentence away from fixing it.

After a month you will know which label you never open. Delete it and let that mail fall into fyi. Fewer labels, better labels, is the direction this always goes.

Monthly API cost

Prices per million tokens as listed on the Claude models page on 28 October 2026: Haiku 5.5 $0.10 in and $0.50 out, Sonnet 5.5 $2 in and $10 out. Caching the system message lowers the input side further. Your n8n plan is extra.

Check

You're done when

Questions

Questions people are asking

Can n8n read my Gmail and sort it automatically? Yes. The Gmail Trigger polls your inbox, an AI Agent node with Claude decides the label, and Gmail nodes apply it. It needs a Google OAuth credential and a workflow built like the one above, with a guard label so each email is handled once.

Why does my n8n AI agent keep creating duplicate drafts? Usually one of three things: manual Execute workflow runs reprocess mail the live run already handled, the ai-triaged guard label is applied before the draft node or not at all, or two polls overlap because one run did not finish. The tree in step 8 walks through each.

Claude or ChatGPT for email classification in n8n? Both work through the AI Agent node. We use claude-haiku-5-5 because it is cheap and follows the JSON format reliably, and claude-sonnet-5-5 for drafts. Whichever you pick, the Structured Output Parser is what makes the output usable, not the model.

How much does it cost per month? For 60 emails a day with drafts on a third of them, around $3 a month in API usage at October 2026 prices, plus your n8n plan. Classification with Haiku is cents; the Sonnet drafts are most of it. The calculator in step 9 takes your own numbers.

Will it ever send an email without me? Not this workflow. It uses only Add Label, Create Draft and Append Row. Search the exported workflow JSON for send and reply before you activate it, and keep it that way when you edit it later. The human presses send.

Sources

  1. n8n Docs, Gmail Trigger node documentation docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.gmailtrigger
  2. n8n Docs, AI Agent node documentation docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent
  3. n8n Docs, Anthropic Chat Model node documentation docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatanthropic
  4. n8n Community, AI inquiry triage: three Gmail Trigger settings that quietly broke my classifier, Aug 2026 community.n8n.io/t/ai-inquiry-triage-three-gmail-trigger-settings-that-quietly-broke-my-classifier/305838
  5. GitHub, n8n-io/n8n issue #42209: Anthropic Chat Model v1.5 sends thinking disabled, Oct 2026 github.com/n8n-io/n8n/issues/42209
  6. Claude Developer Platform, Models overview platform.claude.com/docs/en/models/overview
  7. Claude Developer Platform, Prompt caching platform.claude.com/docs/en/build-with-claude/prompt-caching
Newsletter

One email a week. Written by people.

New how-tos, the tools we tested and what we think, in one short email.

Free · Unsubscribe anytime