The problem with most AI agent tutorials
I've watched 40+ n8n AI agent tutorials on YouTube. Most of them stop at "here's how to connect OpenAI to your workflow."
That's not an agent. That's a chatbot with extra steps.
A real AI agent makes decisions, calls tools based on those decisions, and handles the mess when something breaks. It doesn't just return a completion—it routes requests, manages state, and tries again when APIs time out.
This tutorial walks through building one from scratch. No templates. No "just clone my workflow." You'll see every node, every expression, and every error handler I'd actually ship.

What we're building: a lead-triage agent
The agent takes inbound leads from a form, decides whether they're worth a human call, and either books a calendar slot or sends a polite "not a fit" email.
Three jobs:
- Classify the lead using OpenAI (budget + use-case signals).
- Route based on classification—qualified leads get calendar invites, unqualified get a templated reply.
- Handle failures—if the calendar API is down, fall back to a direct email with Calendly link.
This structure maps to 90% of the AI agent work I've built for clients. Replace "lead triage" with "support ticket routing" or "order exception handling" and the bones are identical.
If you've never built an n8n workflow before, start with something simpler—maybe our n8n Slack automation guide for a gentler intro. This tutorial assumes you know how to add nodes and test steps.
Scaffolding the workflow: trigger, agent loop, and outputs
Open n8n. Create a new workflow.
Step 1: Add a Webhook trigger. Set method to POST. Copy the test URL—we'll use a Typeform or Tally form to POST leads here, but for now just test with a manual curl.
Your webhook should expect JSON like this:
{
"email": "founder@startup.com",
"company_size": "8",
"budget": "2000/month",
"use_case": "We spend 15 hours a week copy-pasting Salesforce deals into Notion."
}
Step 2: Add an OpenAI node. Model: gpt-4o. System prompt:
You are a lead qualification assistant. Given a form submission, reply with exactly one word: QUALIFIED or UNQUALIFIED. Qualify if budget ≥ $1500/month AND use-case mentions repetitive cross-tool work. Otherwise, UNQUALIFIED.
User message (use an expression):
Email: {{ $json.email }}
Company size: {{ $json.company_size }}
Budget: {{ $json.budget }}
Use case: {{ $json.use_case }}
Step 3: Add an IF node after OpenAI. Condition: {{ $json.choices[0].message.content.trim().toUpperCase() }} equals QUALIFIED.
Now you have two branches. Wire them up but leave them empty for now.

The qualified branch: book a meeting via Google Calendar
For qualified leads, we want to create a calendar invite and email them the link.
Add a Google Calendar node on the "true" branch. Action: "Create an event."
- Summary:
Discovery call – {{ $('Webhook').item.json.email }} - Start time: Use an expression to pick tomorrow at 10 AM in your timezone. Example:
{{ DateTime.now().plus({ days: 1 }).set({ hour: 10, minute: 0 }).toISO() }} - Duration: 30 minutes.
- Attendees:
{{ $('Webhook').item.json.email }}
Add a Send Email node (I use Resend or SendGrid). Subject: "Let's talk—here's your calendar invite."
Body:
Hi,
You're a great fit. I've booked us 30 minutes tomorrow at 10 AM.
Check your calendar or click the link in the invite.
– Antonio
Make sure to pull {{ $('Google Calendar').item.json.htmlLink }} into the email if you want to include a direct event link.
Test the webhook with a qualified payload. You should see a calendar event and an email go out.
The unqualified branch: polite rejection template
On the "false" IF branch, add a Send Email node.
Subject: "Not quite a fit—but here's what I'd try."
Body:
Hi {{ $('Webhook').item.json.email.split('@')[0] }},
Thanks for reaching out. Based on your use-case, I don't think a custom build is the best next step—your setup might work better with a no-code tool like Zapier or Make.
If you want a second opinion, here's a free automation opportunity scanner that'll show you where the ROI is hiding.
Good luck.
– Antonio
Notice the inline link to the Opportunity Scanner. If someone isn't a fit for a build, I still want to give them something useful—and that tool converts ~12% of visitors into scoping calls once they see the math.
Adding memory: store context in a Google Sheet or Notion DB
Most AI agents need to remember something between runs. For lead triage, I log every decision so I can audit classification accuracy.
Add a Google Sheets node (or Notion node if you prefer) right after the IF node, on both branches.
Action: "Append row."
Columns:
- Timestamp:
{{ DateTime.now().toISO() }} - Email:
{{ $('Webhook').item.json.email }} - Decision:
{{ $('OpenAI').item.json.choices[0].message.content }} - Budget:
{{ $('Webhook').item.json.budget }}
Now every lead is logged. If you notice "QUALIFIED" leads aren't converting, you can tweak the classification prompt and compare before/after in the sheet.
This is the simplest form of agent memory. For multi-turn conversations (like a Slack bot that remembers the last 5 messages), you'd store thread history in a database and pass it into the OpenAI context window each time.

Error handling: what happens when the calendar API times out
Production agents break. APIs time out. Rate limits hit. The OpenAI node returns gibberish.
n8n's error handling is clunky but functional. Here's the pattern I use:
Wrap the Google Calendar node in an error trigger. Right-click the Calendar node → Settings → "Continue on fail" = true.
Add an IF node after Calendar. Condition: {{ $json.error }} exists.
- True branch (error occurred): Send a fallback email with your Calendly link instead of a Calendar invite.
- False branch (success): Continue to the normal confirmation email.
Example fallback email body:
Hi,
You're a great fit, but our calendar system hiccuped. Book a time here: [calendly.com/yourlink]
– Antonio
This keeps the workflow moving even when Google Calendar is down. I've seen calendar APIs fail ~2% of the time during heavy load—worth handling.
For the OpenAI node, add a similar check: if $json.choices[0].message.content is empty or doesn't match "QUALIFIED" or "UNQUALIFIED," route to a manual review queue (e.g., a Slack message to yourself with the raw form data).
Testing the full loop: use real webhook payloads
Before you wire this to a live form, test with curl:
Qualified payload:
curl -X POST https://your-n8n-instance.app/webhook/lead-triage \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"company_size": "10",
"budget": "3000/month",
"use_case": "Manual Salesforce to Notion sync eating 20 hours/week"
}'
Unqualified payload:
curl -X POST https://your-n8n-instance.app/webhook/lead-triage \
-H "Content-Type: application/json" \
-d '{
"email": "test2@example.com",
"company_size": "2",
"budget": "500/month",
"use_case": "Just exploring options"
}'
Check:
- Does the qualified lead get a calendar invite?
- Does the unqualified lead get the rejection email?
- Does every lead appear in your Google Sheet?
If yes, you're done. If no, open the execution log and look for the first node that returned unexpected data.
"An AI agent is just a workflow that asks a question, acts on the answer, and doesn't explode when the answer is weird."
When to build this yourself vs. hiring it out
This tutorial gives you the bones. But production agents have more surface area:
- Retry logic when APIs return 429 or 503.
- Logging and observability—I pipe every OpenAI call to a PostHog event so I can see latency and token cost trends.
- Versioned prompts—store your system prompts in Notion or a JSON file so you can A/B test classification accuracy without redeploying.
- Multi-step reasoning—sometimes you need the agent to call multiple tools in sequence (e.g., check inventory, then check shipping rates, then send quote).
If you're automating one internal workflow and you have a weekend, build it yourself. If you're automating 5+ workflows or the logic touches money/compliance, it's worth hiring someone who ships n8n builds full-time.
I scope and ship custom AI agents in 2–3 weeks, fixed price, direct access to me—no project managers. Most clients come in after spending a month on a half-working workflow and realising the error-handling is the hard part.
What to automate next
Once you've built one agent, the pattern repeats:
- Support ticket triage: Classify urgency, route to specialist or auto-reply with KB article.
- Order exception handling: Detect refund requests vs. address changes, auto-process the safe ones.
- Meeting prep: Pull CRM data + recent emails, summarize in Slack 10 minutes before the call.
If you're not sure where the ROI is, run your site through the Opportunity Scanner—it'll rank your top 3 automations by hours saved and show you the annual cost of doing nothing.
Or if you want to see how long you're taking to reply to leads (a huge conversion lever), try the Lead Response Speed Analyzer. Most companies think they reply in under an hour. The median is 18 hours.
Go build it
You now know how to wire up an AI agent in n8n that classifies input, routes decisions, and doesn't fall over when an API times out.
No fluff. No "just use this template." You saw every node.
If you get stuck or want a second pair of eyes on your workflow, email me—antonio@sinqra.io. I'll tell you if it's a 10-minute fix or if you should just hire it out.
And if you build something cool, send me a screenshot. I collect these.
