What You'll Build and Why

You build a multi-step AI agent in n8n that ingests incoming support emails, classifies them by urgency and topic, enriches the data with a CRM lookup, and sends a tailored draft reply. No coding required. The agent uses the OpenAI node (or Claude node) for language reasoning, a conditional router for triage, and an error handler that retries failures without dropping messages.

This is not a toy demo. You learn how to design agent architecture that actually works in production: handling API limits, parsing ambiguous user input, and logging decisions for audit. By the end, you have a reusable agent template you can adapt for lead scoring, invoice processing, or customer onboarding.

Prerequisites

  • An n8n instance (cloud or self-hosted). Sign up at n8n.io if you don't have one.
  • An OpenAI API key (or Anthropic API key for Claude). You use the ChatGPT node, but the pattern works with any LLM.
  • A Gmail account (for the email trigger) and a Google Sheet (for logging).
  • Basic familiarity with webhooks and JSON. If you have used Zapier, you are ready.

Step 1: Design the Agent Architecture

Before you drag a single node, think of your agent as a pipeline with four stages: Trigger, Parse & Enrich, Decide, Act. Each stage must have a fallback.

We use a webhook trigger so you can test the agent from any tool (Zapier, Make, or a simple POST from curl). The agent then calls an LLM to extract intent and entities, validates the output, looks up a contact in a dummy CRM (a Google Sheet), and routes to one of three actions: reply, escalate, or log as spam.

Why this pattern? Because single-step agents fail. If you ask an LLM to both classify and reply, a hallucinated classification can derail the entire response. Separating parse, enrich, and act gives you control points to inject business rules.

Your First Node: The Webhook Trigger

// Incoming webhook payload example (JSON)
{
  "from": "alice@acme.com",
  "subject": "Order #12345 missing item",
  "body": "I received my package but the blue widget is missing. Please resend."
}

Add a Webhook node. Keep it open to receive POST requests. Set the response to "Respond to Webhook" and choose a temporary response message like "Received". Later you update it to return the agent's final action.

Step 2: Build the LLM Parse Node

Add a ChatGPT node. Connect it to the webhook node. Paste the following system prompt:

You are an email triage assistant. Given the email below, extract:
- urgency: "high" if customer mentions "urgent", "missing", "not working", "broken", "asap", else "low"
- category: one of ["billing", "support", "sales", "spam"]
- summary: a one sentence summary of the issue

Respond ONLY with a JSON object. No extra text.

For the message input, use the webhook body fields: {{$json.body}} (or map individual fields). Set the node to output JSON mode (if available, otherwise rely on the prompt).

This is the parse stage. The LLM returns a structured object. Do not trust it blindly. You validate the output in the next step.

Validate the LLM Output

Add an IF node after the ChatGPT node. Use an expression to check that category is one of the allowed values and that urgency is not empty. If validation fails, route the email to a manual approval node (a pause) so a human can review. This simple guardrail prevents your agent from acting on garbage.

// Validation expression example
$json.category === "support" || $json.category === "billing" || $json.category === "sales" || $json.category === "spam"

Now you have a clean, validated data packet. The agent is ready to enrich and decide.

Step 3: Enrich with CRM Data

Connect a Google Sheets node. Use it to look up the customer's email in a sheet that acts as your CRM. You want to know the customer's lifetime value, number of previous tickets, and account tier. Add those columns to the sheet.

Set the operation to Get Many Rows and filter by the email field from the webhook input. If no match found, use a Set node to assign default values (e.g., tier: "standard", previous tickets: 0).

Why enrich? Because agents need context. An urgent issue from a VIP customer should trigger an escalation, while the same issue from a new user might be answered with a link to the knowledge base. Without enrichment, your agent is blind.

For a deeper dive on connecting external tools, see our AI dashboard guide.

Step 4: The Decision Router

Now you combine the parsed data with the CRM data to pick a path. Use a Switch node. Create three routes:

  • Route 1: Auto reply for low urgency support or billing questions with a known answer.
  • Route 2: Escalate to Slack for high urgency or VIP customers. Send a message with the summary and a link to manually intervene.
  • Route 3: Log and archive for spam or sales inquiries that do not fit.

Set the switch condition on the category and urgency fields combined. For example, if category == "support" AND urgency == "low", go to Route 1. If category == "support" AND urgency == "high", go to Route 2. If category == "spam", go to Route 3.

This routing is where you inject business logic. You can adjust thresholds, change destinations, or add more routes over time. The agent becomes smarter without touching a line of code.

Step 5: Build the Action Nodes with Error Handling

Each route needs an action node. For Route 1 (auto reply), add a Gmail node set to Send an email. Use the LLM from Step 2 to generate the reply body, but this time provide the enrichment context and a different system prompt:

You are a friendly support agent. Given the customer's issue and their account details, write a helpful reply. Include the solution if available, or ask clarifying questions. Sign with "AI Agent".

This call uses a second ChatGPT node. Always use a separate LLM call for generation to avoid leaking the triage logic into the reply.

Error handling is critical here. Surround each action node with an Error Trigger subworkflow. In n8n, you can connect an error output from a node to a new Workflow node that sends a notification to Slack or logs the failure. Set a retry count of 3 with a 5-second delay between attempts. If all retries fail, route the email back to manual review.

An agent that silently drops emails is worse than no agent. Build the error handler first, then add the happy path. For a real example of this pattern in customer support, check out our guide on AI support automation.

Step 6: Log Everything to a Google Sheet

After any route, add a Google Sheets node set to Append to a log sheet. Record the incoming email, parsed category, urgency, CRM data, action taken, and timestamp. This log becomes your audit trail and your training dataset. If the agent misbehaves, you can find the exact input and correct the prompt.

Logging also lets you track metrics: how many emails were auto-replied vs escalated, average resolution time, and error rates. You can build a simple dashboard with this data.

Step 7: Test the Agent End-to-End

Use curl or a tool like Postman to send a test payload to your webhook URL. Here is an example:

curl -X POST https://your-n8n-instance.com/webhook/email-triage \
  -H "Content-Type: application/json" \
  -d '{"from":"jane@example.com","subject":"Can I get a refund?","body":"I ordered the wrong size. Need help ASAP."}'

Watch the workflow execution in n8n's real-time view. Check each node's output. The agent should classify the email as high urgency, category billing, look up Jane in the CRM, trigger the escalation route, send a Slack notification, and log the entry. If something fails, inspect the error handler output. Adjust prompts or conditions and rerun.

You can also set the webhook to respond with a JSON summary of the action. This lets external systems (like Zapier or Make) call your agent and get a structured response.

Common Pitfalls and How to Avoid Them

1. LLM Output Parsing Errors

LLMs sometimes fail to output valid JSON. Always wrap the ChatGPT node in a Code node that tries to parse the JSON. If parsing fails, send the output to a manual fallback. Use n8n's try/catch in a Function node if needed.

2. API Rate Limits

OpenAI and Anthropic impose rate limits. If your agent processes many emails per minute, you will see 429 errors. Use n8n's built-in Wait node with a random delay between 500ms and 2s before each LLM call. Also add a retry on 429 status codes.

3. Sensitive Data Leakage

Your LLM prompt may contain customer PII. If you use a third-party API, data travels to their servers. For compliance, either use a self-hosted LLM or add a Code node to mask sensitive fields (email, name) before sending to the LLM, then unmask after.

4. Overengineering the First Version

Start with two routes and a single LLM. Add enrichment and error handling after you see the agent running. You can iterate quickly because n8n lets you change nodes without rebuilding the whole workflow.

Next Steps and Where to Go From Here

Your agent now works. The next level is to give it memory and tools. Connect a Simple Vector Store node (n8n's built-in vector store) so the agent can retrieve knowledge base articles before replying. That turns your agent from a rule follower into a problem solver. For guidance on that, see Build Your First Claude Skill.

You can also expose your agent as an API endpoint for your frontend app. Use the webhook response to return the agent's decision, and let your app call it on form submissions. Finally, set up a schedule (cron trigger) to process a batch of emails every hour, or use a trigger that monitors a new row in a Google Sheet. Your agent is now a production-ready component you can reuse across lead scoring, order processing, and more.

For a more advanced example, see our no-code lead gen bot guide.

Remember: the best agents are not the ones with the most nodes. They are the ones that handle errors gracefully and log every decision. Build your n8n agent with that philosophy, and you have a system that actually works.

Cover photo by Pachon in Motion on Pexels.