n8n is an open-source workflow automation tool that has quietly become one of the most capable platforms for building AI-powered automations. Unlike Zapier or Make, you can self-host it, inspect every data transformation, and plug in AI models at any point in a workflow. This tutorial walks through building a practical automation from scratch using n8n's AI nodes.

What You Will Build

A workflow that monitors a shared Gmail inbox, uses an LLM to classify and summarize each incoming email, and routes the result to either a Slack channel or a Notion database depending on the category. This pattern covers the most common n8n + AI use case: read data, process it with an AI model, write to the right destination.

Prerequisites

  • n8n installed locally (Docker) or an n8n Cloud account
  • A Google account (for Gmail access)
  • An OpenAI or Anthropic API key
  • Basic understanding of JSON

Step 1: Install n8n

The fastest way to run n8n locally is with Docker:

docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -v ~/.n8n:/home/node/.n8n \
  docker.n8n.io/n8nio/n8n

Open http://localhost:5678 in your browser. If you prefer a managed instance, n8n Cloud provides the same interface without any infrastructure setup.

For production self-hosting with persistent storage and a database, use Docker Compose:

# Create a docker-compose.yml
services:
  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: always
    ports:
      - "5678:5678"
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - N8N_ENCRYPTION_KEY=your-random-key-here
    volumes:
      - n8n_data:/home/node/.n8n
 
  postgres:
    image: postgres:16
    environment:
      - POSTGRES_DB=n8n
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=n8n
    volumes:
      - postgres_data:/var/lib/postgresql/data
 
volumes:
  n8n_data:
  postgres_data:

Step 2: Connect Your Credentials

Before building the workflow, set up your credentials. In n8n, credentials are stored encrypted and reused across workflows.

  1. Go to Settings > Credentials > New Credential
  2. Add your Gmail OAuth2 credentials (follow the Google Cloud Console guide in n8n docs)
  3. Add an OpenAI API credential (or Anthropic if you prefer Claude)
  4. Add your Slack Bot Token and Notion Integration Token

Store your OpenAI key under a name like OpenAI Production so you can reference it across multiple workflows.

Step 3: Create the Workflow

Click New Workflow, then start adding nodes.

Trigger: Gmail

Add a Gmail Trigger node as the starting point. Configure it to:

  • Watch the INBOX label
  • Poll every minute (or use push with a webhook if your n8n instance has a public URL)
  • Return the full email including body text, sender, and subject

AI Node: Classify and Summarize

This is the core of the workflow. Add an OpenAI Chat Model node connected to a Basic LLM Chain node.

Configure the Basic LLM Chain with a system prompt like this:

You are an email classifier. Given an email, return a JSON object with two fields:
- "category": one of "support", "sales", "billing", "other"
- "summary": a 1-2 sentence plain-English summary of what the sender needs

Return only valid JSON, no extra text.

Set the user message to use the n8n expression:

Subject: {{ $json.subject }}
From: {{ $json.from.value[0].address }}
Body: {{ $json.text }}

The Basic LLM Chain node automatically passes the prompt to your connected chat model and returns the raw text response.

Parse the JSON Response

Add a Code node after the LLM chain to parse the model output:

const raw = $input.first().json.text;
 
let parsed;
try {
  parsed = JSON.parse(raw);
} catch (e) {
  // Fallback if model returned markdown-wrapped JSON
  const match = raw.match(/```json\s*([\s\S]*?)```/);
  parsed = match ? JSON.parse(match[1]) : { category: "other", summary: raw };
}
 
return [{ json: { ...parsed, originalEmail: $input.first().json } }];

Route Based on Category

Add a Switch node with two rules:

  • If category equals support or billing → route to Slack
  • Everything else → route to Notion

Destination: Slack

Add a Slack node. Post to #support-inbox with a message template:

*New {{ $json.category }} email*
From: {{ $json.originalEmail.from.value[0].address }}
Summary: {{ $json.summary }}
Subject: {{ $json.originalEmail.subject }}

Destination: Notion

Add a Notion node set to Create Page in a database. Map the fields:

  • Title → $json.originalEmail.subject
  • Category → $json.category
  • Summary → $json.summary
  • Sender → $json.originalEmail.from.value[0].address
  • Date → $json.originalEmail.date

Step 4: Handle Errors

n8n workflows fail silently by default. Add error handling at two points.

First, enable Continue on Fail on the LLM node so a bad API response does not crash the entire run. The Code node fallback above handles malformed model output.

Second, add an Error Trigger workflow:

  1. Create a new workflow with an Error Trigger node
  2. Connect it to a Slack node that posts to #alerts
  3. In your main workflow, go to Workflow Settings > Error Workflow and select this error handler

Every unhandled exception in the main workflow will now notify your Slack channel with the workflow name, error message, and run ID.

Step 5: Test and Activate

Before activating, test each node manually:

  1. Click the Gmail trigger and select Fetch Test Event to pull a real email
  2. Execute each downstream node one by one to verify data flows correctly
  3. Check that the Switch node routes correctly for different category values
  4. Confirm Slack messages and Notion pages appear as expected

Once satisfied, toggle the workflow to Active. n8n will now poll Gmail every minute automatically.

Extending This Pattern

The same structure scales to more complex automations:

  • Replace Gmail with an RSS feed or a webhook to process any text input
  • Add a Pinecone or Qdrant vector store node to perform semantic search before the LLM step, giving the model relevant context from past emails
  • Chain multiple LLM calls: one to classify, a second to draft a reply, a third to check the reply for tone
  • Use the n8n AI Agent node for tasks that require the model to decide which tools to call, rather than following a fixed path

n8n's visual editor makes it easy to see exactly where data enters, how it transforms, and where it exits. That observability is its main practical advantage over code-only solutions.

Practical Tips

  • Pin test data. After fetching a test event, pin it to the node so re-running always uses the same input. This avoids burning API credits every time you adjust a downstream node.

  • Use expressions, not hardcoded values. Expressions like {{ $json.subject }} are evaluated at runtime and keep your workflow adaptable. Hardcoded strings break when input schemas change.

  • Limit LLM output length. Set max_tokens on your OpenAI node to a reasonable number (512 for classification tasks). Unbounded responses cost more and are harder to parse.

  • Version your workflows. n8n's built-in history saves snapshots when you save. For team environments, export workflows as JSON and store them in Git.

  • Self-host for sensitive data. If your emails contain PII or internal business data, running n8n on your own infrastructure means that data never leaves your network.

Try n8n

n8n Cloud gives you a managed instance with built-in OAuth for all major services, automatic updates, and execution logging — without configuring Docker or a database.

Try n8n