Price quote builder AI agent
Tell it what the client needs; it builds a quote from your price list, checks the maths, saves it and drafts the email.
How it works
- You describe the client and what they need.
- The agent matches each item to your price list and shows the totals with VAT.
- After you confirm, it saves the quote with a number.
- It drafts the quote email to the client in Gmail.
What it can do
Unlike a fixed flow, an agent decides which of its tools to use, in what order — and remembers the conversation.
- Builds itemised quotes from your price list
- Applies discounts within your limits
- Adds VAT and totals
- Drafts the client email
System prompt
The instructions that shape the agent. It's already inside the n8n template — copy it into Make or Zapier, and adjust the YOUR_… parts.
You build price quotes for YOUR_COMPANY's sales team. Currency: YOUR_CURRENCY. VAT: YOUR_VAT_RATE. Today is {{ $now.toFormat('d LLLL yyyy') }}.
Tools:
- "Price list": our products and services (code, name, unit, unit price, min quantity, max discount %). Always read it first.
- "Save quote": saves a confirmed quote to the Quotes sheet and returns nothing else.
- "Draft quote email": creates a Gmail draft to the client with the quote (never sends).
Process:
1. Ask for the client name, email and what they need, if missing.
2. Match each item to the price list. Show a table: item, quantity, unit price, line total; then subtotal, discount, VAT and grand total.
3. Ask the user to confirm, then save the quote with number Q-{{ $now.toFormat('yyMMdd') }}-<2 random digits>.
4. Offer to draft the email to the client.
Rules:
- Use only prices from the price list. If an item isn't there, say so and leave it out.
- Never give a discount above an item's max discount %. If asked for more, say a manager must approve.
- Double-check the arithmetic before showing totals.Safety rules
Built into the prompt and the tools:
- Uses only your prices
- Never goes over each item's max discount
- Drafts emails, never sends them
Uses your own AI key (Claude, OpenAI or another model). Cost depends on the model and conversation length — a small, fast model keeps most conversations to a fraction of a cent.
Diagram
Build it
Pick your tool — same automation, step by step.
Copy and paste straight into an n8n canvas (Ctrl+V), or download and use Import from File. Then connect your own credentials and replace every YOUR_… placeholder. AI steps use a Claude model node — swap it for OpenAI, Gemini or Ollama if you prefer.
Show code (247 lines)
{
"name": "Price quote builder AI agent (Flowngn)",
"nodes": [
{
"parameters": {
"content": "## Price quote builder AI agent\nTell it what the client needs; it builds a quote from your price list, checks the maths, saves it and drafts the email.\n\n**Setup**\n1. Open each node and connect your own credentials.\n2. Replace every YOUR_… placeholder.\n3. Test once, then activate.\n\nFree template from Flowngn",
"height": 260,
"width": 340
},
"id": "425c281e-a6bd-4ffe-aab5-92854b17b971",
"name": "Setup notes",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-420,
-60
]
},
{
"parameters": {
"public": true,
"mode": "hostedChat",
"initialMessages": "Who is the quote for, and what do they need?",
"options": {
"responseMode": "lastNode"
}
},
"id": "425c281e-a6bd-4ffe-aab5-92854b17b971",
"name": "Quote chat",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"typeVersion": 1.1,
"position": [
0,
0
],
"webhookId": "425c281e-a6bd-4ffe-aab5-92854b17b971"
},
{
"parameters": {
"options": {
"systemMessage": "=You build price quotes for YOUR_COMPANY's sales team. Currency: YOUR_CURRENCY. VAT: YOUR_VAT_RATE. Today is {{ $now.toFormat('d LLLL yyyy') }}.\n\nTools:\n- \"Price list\": our products and services (code, name, unit, unit price, min quantity, max discount %). Always read it first.\n- \"Save quote\": saves a confirmed quote to the Quotes sheet and returns nothing else.\n- \"Draft quote email\": creates a Gmail draft to the client with the quote (never sends).\n\nProcess:\n1. Ask for the client name, email and what they need, if missing.\n2. Match each item to the price list. Show a table: item, quantity, unit price, line total; then subtotal, discount, VAT and grand total.\n3. Ask the user to confirm, then save the quote with number Q-{{ $now.toFormat('yyMMdd') }}-<2 random digits>.\n4. Offer to draft the email to the client.\n\nRules:\n- Use only prices from the price list. If an item isn't there, say so and leave it out.\n- Never give a discount above an item's max discount %. If asked for more, say a manager must approve.\n- Double-check the arithmetic before showing totals."
}
},
"id": "425c281e-a6bd-4ffe-aab5-92854b17b971",
"name": "Quote agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.9,
"position": [
300,
0
]
},
{
"parameters": {
"model": {
"__rl": true,
"value": "claude-sonnet-5",
"mode": "list"
},
"options": {}
},
"id": "425c281e-a6bd-4ffe-aab5-92854b17b971",
"name": "Claude model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"typeVersion": 1.3,
"position": [
-40,
220
]
},
{
"parameters": {
"contextWindowLength": 10
},
"id": "425c281e-a6bd-4ffe-aab5-92854b17b971",
"name": "Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.3,
"position": [
130,
220
]
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Returns our price list: code, name, unit, unit price, min quantity, max discount %.",
"operation": "read",
"documentId": {
"__rl": true,
"value": "YOUR_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Price list",
"mode": "name"
},
"options": {}
},
"id": "425c281e-a6bd-4ffe-aab5-92854b17b971",
"name": "Price list",
"type": "n8n-nodes-base.googleSheetsTool",
"typeVersion": 4.5,
"position": [
300,
220
]
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Saves a confirmed quote.",
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Quotes",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"date": "={{ $now.toISODate() }}",
"quote_no": "={{ $fromAI('quote_no', \"Quote number\", 'string') }}",
"client": "={{ $fromAI('client', \"Client name\", 'string') }}",
"email": "={{ $fromAI('email', \"Client email\", 'string') }}",
"items": "={{ $fromAI('items', \"Items as 'qty × code name @ price', one per line\", 'string') }}",
"total": "={{ $fromAI('total', \"Grand total including VAT\", 'number') }}",
"valid_until": "={{ $now.plus({ days: 14 }).toISODate() }}",
"status": "sent"
}
},
"options": {}
},
"id": "425c281e-a6bd-4ffe-aab5-92854b17b971",
"name": "Save quote",
"type": "n8n-nodes-base.googleSheetsTool",
"typeVersion": 4.5,
"position": [
470,
220
]
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Creates a Gmail draft to the client with the quote (never sends).",
"resource": "draft",
"operation": "create",
"subject": "={{ $fromAI('subject', \"Email subject\", 'string') }}",
"message": "={{ $fromAI('body', \"Email body with the quote table, total, validity (14 days) and next steps\", 'string') }}",
"options": {
"sendTo": "={{ $fromAI('to', \"The recipient's email address\", 'string') }}"
}
},
"id": "425c281e-a6bd-4ffe-aab5-92854b17b971",
"name": "Draft email",
"type": "n8n-nodes-base.gmailTool",
"typeVersion": 2.1,
"position": [
640,
220
]
}
],
"connections": {
"Quote chat": {
"main": [
[
{
"node": "Quote agent",
"type": "main",
"index": 0
}
]
]
},
"Claude model": {
"ai_languageModel": [
[
{
"node": "Quote agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Memory": {
"ai_memory": [
[
{
"node": "Quote agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Price list": {
"ai_tool": [
[
{
"node": "Quote agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Save quote": {
"ai_tool": [
[
{
"node": "Quote agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Draft email": {
"ai_tool": [
[
{
"node": "Quote agent",
"type": "ai_tool",
"index": 0
}
]
]
}
},
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateCredsSetupCompleted": false
},
"tags": []
}In Make, create a new scenario and add these modules in order:
- Webhooks › Custom webhook — called by your website's chat widget
- Make AI Agents › Run an agent — give it these tools: “Price list” (Google Sheets), “Save quote” (Google Sheets), “Draft email” (Gmail); paste the system prompt as the agent's instructions
- Every module run uses Make operations — the free plan includes a monthly quota.
- Module and step names can differ slightly as Make and Zapier update their apps.
In Zapier, create a new Zap and add these steps in order:
- Zapier Chatbots, or Webhooks by Zapier — Catch Hook from your chat widget
- Zapier Agents — create an agent (or AI by Zapier for a single step) — give it these tools: “Price list” (Google Sheets), “Save quote” (Google Sheets), “Draft email” (Gmail); paste the system prompt as the agent's instructions
- Zaps with more than two steps need a paid Zapier plan.
- Module and step names can differ slightly as Make and Zapier update their apps.
Tips
- Add a max_discount column to the price list, so the agent knows your limits.
Related flows
Customer support AI agent
A chat agent that answers from your FAQ, looks up orders, and hands tricky cases to a human.
Bookkeeping AI agent
Tell it about income and expenses in plain words; ask questions like "how much did we spend on ads this month?"
Unpaid invoices collections AI agent
Every morning, the agent reviews overdue invoices, drafts polite reminders in the right tone, and flags the ones that need a call.