This workflow corresponds to n8n.io template #16181 — we link there as the canonical source.
This workflow follows the Agent → Gmail Tool recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "dPWBxPHEOJxuqhHJ",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "LLM Router",
"tags": [],
"nodes": [
{
"id": "80cee607-170e-431f-8429-90f4172177e8",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-32
],
"parameters": {
"width": 480,
"height": 608,
"content": "## LLM Router\n\n### How it works\n\nThis workflow routes and chains multiple AI prompts around an email-driven document processing flow. It starts with the Gmail node to get the attachment and then analyzes the type of documents. The binary data is passed along the nodes and the switch routes the flow along the document specific path. Document specific analysis and structuring is done for each type. Data can then be sent to the accroding APIs and a dedicated messaging agent handles the conversation about the document. \n\n### Setup steps\n\n- Connect Gmail credentials for the Gmail Trigger and Gmail sending tool, and configure the trigger criteria for the incoming documents to process.\n- Configure Google Gemini credentials for the Gemini analysis node and both AI Agent model subnodes, including any fallback model settings.\n- Add a Merge node with combine setup to presever the binary data along the flow\n- Add a switch that handles the Gemini output and sets the rules for the document paths\n- Add an document specific analysis\n- Structure the output from the analysis with a AI Agent\n- Review the Structured Output Parser schema so it matches the fields expected by the validation code and webhook payload.\n- Update the HTTP Request node with the correct webhook or API endpoint, method, headers, and authentication if needed.\n- Review the Validate Document Data code node to ensure its validation rules match the document types and required fields.\n- Give the AI Messenger Node document specific instructions on how to handle the communication\n\n### Customization\n\nYou can adjust the extraction prompt and parser schema for different document formats, change the validation logic for stricter business rules, replace the webhook URL with a production API, and customize the AI Agent\u2019s Gmail message tone or content."
},
"typeVersion": 1
},
{
"id": "4d4f4823-2cf7-45d0-94cb-201c436cee99",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
448,
-32
],
"parameters": {
"color": 7,
"width": 884,
"height": 528,
"content": "## Ingest and classify document\n\nStarts when a Gmail event occurs, analyzes the incoming document with Gemini. It will only define the class of the document - this is the task of the \"router\" LLM. The routing itself can then be done with a traditional \"Switch\" node. It will address the forward path reliably. Note that you need the merge node to preserve the binary output for the nodes to follow"
},
"typeVersion": 1
},
{
"id": "effc0d62-c731-4375-8573-aa6be835800f",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1552,
-416
],
"parameters": {
"color": 7,
"width": 912,
"height": 1440,
"content": "## Validate and submit data\n\nHere are the specialized agents for each document type with own instructions and structured output. Every document can also be validated with code nodes tailored to the specific document and an HTTP request will be made to the according system, that should get the data of the document. "
},
"typeVersion": 1
},
{
"id": "e9bee643-a21b-4a93-b496-f72fd60a147a",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2480,
-416
],
"parameters": {
"color": 7,
"width": 432,
"height": 1440,
"content": "## Generate Gmail follow-up\n\nUses specific AI Agents to answer the according requests. It is instructed to structure the data as HTML and uses the GMAIL node to send the message. "
},
"typeVersion": 1
},
{
"id": "0c708c0f-a741-4063-bb57-5d8e53eacd6e",
"name": "When Email Received",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
496,
272
],
"parameters": {
"simple": false,
"filters": {
"sender": "john.doe@vylos-ai.com",
"readStatus": "unread"
},
"options": {
"downloadAttachments": true
},
"pollTimes": {
"item": [
{}
]
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 1.4
},
{
"id": "655ab20e-fe8b-4ea4-9126-b147b6f3d37f",
"name": "Analyze Document with Gemini",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
720,
336
],
"parameters": {
"text": "Analyze the document and classify it. Output only the class of the document accoring to the allowed types. Only return the text and of the class and nothing else.\n\nAllowed types: \"lading\" for a bill of lading, \"invoice\" for an invoice, \"warranty\" for a warranty claim and \"other\" for any other document. \n\n",
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-3.1-flash-lite",
"cachedResultName": "models/gemini-3.1-flash-lite"
},
"options": {},
"resource": "document",
"inputType": "binary",
"binaryPropertyName": "attachment_0"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "e137fd9f-ec71-40b1-95fe-4cb8896e99f6",
"name": "Post to Webhook API",
"type": "n8n-nodes-base.httpRequest",
"position": [
2304,
-144
],
"parameters": {
"url": "https://webhook.site/1fdb461e-d9f7-4450-9c74-39c290916bdf",
"method": "POST",
"options": {},
"jsonBody": "={{ $json.output }}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.4
},
{
"id": "2ad57e5e-1444-4db3-b5b6-4d4bdcd723d2",
"name": "Send Gmail Message",
"type": "n8n-nodes-base.gmailTool",
"position": [
2784,
-16
],
"parameters": {
"sendTo": "={{ $('When Email Received').item.json.from.value[0].address }}",
"message": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Message', ``, 'string') }}",
"options": {},
"subject": "=RE: {{ $('When Email Received').item.json.headers.subject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "6f3db04b-5b0c-4098-adb5-df5f33b3dfc1",
"name": "Gemini Main Analysis 1",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1616,
-16
],
"parameters": {
"options": {},
"modelName": "models/gemini-3.1-flash-lite"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "5a745b13-191d-4504-932f-5368672d4819",
"name": "Gemini Fallback Analysis 1",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1744,
-16
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "97b74046-c80e-4caa-89ad-31cff236468c",
"name": "Gemini Main Analysis 2",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
2528,
-16
],
"parameters": {
"options": {},
"modelName": "models/gemini-3.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "86928a60-00eb-41d5-a733-37251b50700b",
"name": "Gemini Fallback Analysis 2",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
2656,
-16
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "bb20ce41-92f6-4821-aaee-f13ca2b1272a",
"name": "Parse Structured Output",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1872,
-16
],
"parameters": {
"jsonSchemaExample": "{\n \"shipper\": {\n \"sid\": \"ACME Corporation\",\n \"name\": \"ACME Corporation\",\n \"address\": \"1234 Industrial Blvd\",\n \"city_state_zip\": \"Springfield, IL 62701\"\n },\n \"consignee\": {\n \"cid\": \"CUST-9988\",\n \"name\": \"John Doe\",\n \"address\": \"42 Elm Street\",\n \"city_state_zip\": \"Shelbyville, IL 62565\"\n },\n \"shipment\": {\n \"bill_of_lading_number\": \"BOL-2026-00847\",\n \"carrier_name\": \"Swift Freight LLC\",\n \"trailer_number\": \"TRL-4821\",\n \"seal_numbers\": [\"SL-002\", \"SL-003\"],\n \"except_as_noted_date\": \"2026-06-01\"\n },\n \"customer_orders\": [\n {\n \"customer_order_number\": \"ORD-8821-A\",\n \"packages\": 4,\n \"weight_lbs\": 320,\n \"additional_shipper_info\": \"Laptop computers \u2013 batch A\"\n },\n {\n \"customer_order_number\": \"ORD-8821-B\",\n \"packages\": 2,\n \"weight_lbs\": 180,\n \"additional_shipper_info\": \"Monitors 27in \u2013 2 units\"\n },\n {\n \"customer_order_number\": \"ORD-8822\",\n \"packages\": 6,\n \"weight_lbs\": 210,\n \"additional_shipper_info\": \"Office chairs \u2013 disassembled\"\n },\n {\n \"customer_order_number\": \"ORD-8823\",\n \"packages\": 1,\n \"weight_lbs\": 45,\n \"additional_shipper_info\": \"Networking switch \u2013 48-port\"\n }\n ],\n \"carrier_line_items\": [\n {\n \"handling_unit\": { \"qty\": 4, \"type\": \"PLT\" },\n \"package\": { \"qty\": 4, \"type\": \"BOX\" },\n \"weight_lbs\": 320,\n \"hazardous_materials\": false,\n \"commodity_description\": \"Laptop Computers Model X-500\",\n \"nmfc_number\": \"61400\",\n \"class\": 85\n },\n {\n \"handling_unit\": { \"qty\": 2, \"type\": \"PLT\" },\n \"package\": { \"qty\": 2, \"type\": \"BOX\" },\n \"weight_lbs\": 180,\n \"hazardous_materials\": false,\n \"commodity_description\": \"27in LCD Monitors\",\n \"nmfc_number\": \"44070\",\n \"class\": 70\n },\n {\n \"handling_unit\": { \"qty\": 6, \"type\": \"PLT\" },\n \"package\": { \"qty\": 6, \"type\": \"CTN\" },\n \"weight_lbs\": 210,\n \"hazardous_materials\": false,\n \"commodity_description\": \"Office Chairs \u2013 KD packed\",\n \"nmfc_number\": \"56100\",\n \"class\": 85\n },\n {\n \"handling_unit\": { \"qty\": 1, \"type\": \"PLT\" },\n \"package\": { \"qty\": 1, \"type\": \"BOX\" },\n \"weight_lbs\": 45,\n \"hazardous_materials\": true,\n \"commodity_description\": \"48-Port Network Switch\",\n \"nmfc_number\": \"63010\",\n \"class\": 70\n }\n ]\n}"
},
"typeVersion": 1.3
},
{
"id": "87730847-18ad-4410-8831-1cba27d44fcd",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
592
],
"parameters": {
"color": "#BAD9FE",
"width": 480,
"height": 192,
"content": "## Get help with the setup and more workflwos\n\n vylos-ai.com/ \n\n## Video on the bill of lading path:\nhttps://www.youtube.com/watch?v=YZDnJ6bYVdA"
},
"typeVersion": 1
},
{
"id": "e523bcd5-2ed1-475c-8750-7d0b1ae87336",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
1168,
256
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "b64cf5ad-5d77-40c9-8e2f-f71e0daba83f",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Analyze Document with Gemini').item.json.content.parts[0].text }}",
"rightValue": "lading"
}
]
}
},
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "74bc6d05-1cce-466e-8430-536ea6bff775",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Analyze Document with Gemini').item.json.content.parts[0].text }}",
"rightValue": "invoice"
}
]
}
},
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "02a1cad5-5c3d-44f2-adf8-fd334a715867",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Analyze Document with Gemini').item.json.content.parts[0].text }}",
"rightValue": "warranty"
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.4
},
{
"id": "00fa0a9e-1e94-4aeb-b959-1552e9e060f9",
"name": "Post to Webhook API1",
"type": "n8n-nodes-base.httpRequest",
"position": [
2304,
272
],
"parameters": {
"url": "https://webhook.site/1fdb461e-d9f7-4450-9c74-39c290916bdf",
"method": "POST",
"options": {},
"jsonBody": "={{ $json.output }}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.4
},
{
"id": "f045e37a-1802-4f2d-a065-527e688f8ae1",
"name": "Gemini Main Analysis ",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1616,
384
],
"parameters": {
"options": {},
"modelName": "models/gemini-3.1-flash-lite"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "64727352-c5ee-43d6-9495-ad8c515df678",
"name": "Gemini Fallback Analysis ",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1744,
384
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "b2a39469-1266-4f53-91e1-480525ae1761",
"name": "Parse Structured Output1",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1872,
384
],
"parameters": {
"jsonSchemaExample": "{\n \"company_name_seller\": \"Acme Corp\",\n \"company_address_seller\": \"742 Evergreen Terrace\",\n \"company_city_state_zip_seller\": \"Springfield, IL 62701\",\n \"company_email_seller\": \"billing@acmecorp.com\",\n \"customer_name_buyer\": \"TechStart Inc.\",\n \"customer_address_buyer\": \"99 Innovation Drive\",\n \"customer_city_state_zip_buyer\": \"Austin, TX 78701\",\n \"customer_email_buyer\": \"ap@techstartinc.com\",\n \"invoice_number\": \"INV-2026-00847\",\n \"invoice_date\": \"2026-06-08\",\n \"due_date\": \"2026-07-08\",\n \"payment_terms\": \"Net 30\",\n \"po_number\": \"PO-TSI-4412\",\n \"line_items\": [\n {\n \"description\": \"Dell OptiPlex 7000 Desktop (i7, 32GB RAM, 1TB SSD)\",\n \"qty\": 5,\n \"unit_price\": 1249.99,\n \"total\": 6249.95\n },\n {\n \"description\": \"LG 27\\\" UltraFine 4K IPS Monitor (27UN850-W)\",\n \"qty\": 10,\n \"unit_price\": 449.95,\n \"total\": 4499.50\n },\n {\n \"description\": \"Logitech MX Keys S Wireless Keyboard + MX Master 3S Mouse Bundle\",\n \"qty\": 8,\n \"unit_price\": 159.00,\n \"total\": 1272.00\n },\n {\n \"description\": \"Cisco Catalyst 9200L 24-Port PoE+ Managed Switch\",\n \"qty\": 2,\n \"unit_price\": 3875.00,\n \"total\": 7750.00\n },\n {\n \"description\": \"Samsung 870 EVO 2TB SATA SSD (MZ-77E2T0B)\",\n \"qty\": 20,\n \"unit_price\": 219.99,\n \"total\": 4399.80\n }\n ],\n \"subtotal\": 24171.25,\n \"tax\": {\n \"rate\": \"8%\",\n \"amount\": 1933.70\n },\n \"total_due\": 26104.95,\n \"payment_instructions\": \"Wire transfer, ACH, or check accepted. Make checks payable to Acme Corp.\",\n \"contact_information\": \"+1 (800) 555-0199\"\n}"
},
"typeVersion": 1.3
},
{
"id": "4326342f-6752-458e-bfc2-508574cdf7f1",
"name": "Post to Webhook API2",
"type": "n8n-nodes-base.httpRequest",
"position": [
2304,
672
],
"parameters": {
"url": "https://webhook.site/1fdb461e-d9f7-4450-9c74-39c290916bdf",
"method": "POST",
"options": {},
"jsonBody": "={{ $json.output }}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.4
},
{
"id": "03b61a16-8e7f-4e89-862f-386d762d11a7",
"name": "Gemini Main Analysis 3",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1616,
896
],
"parameters": {
"options": {},
"modelName": "models/gemini-3.1-flash-lite"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "a6d1e264-3496-44f8-9292-1da870e27b08",
"name": "Gemini Fallback Analysis 3",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1744,
896
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "983bc95e-58da-4dd7-bb02-4975fed2ff6a",
"name": "Parse Structured Output2",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1872,
896
],
"parameters": {
"jsonSchemaExample": "{\n \"claim_number\": \"WC-2026-00312\",\n \"claim_date\": \"2026-06-08\",\n \"claim_status\": \"Pending Review\",\n \"priority\": \"High\",\n \"original_invoice_number\": \"INV-2026-00847\",\n \"po_number\": \"PO-TSI-4412\",\n \"claimant\": {\n \"company_name\": \"TechStart Inc.\",\n \"address\": \"99 Innovation Drive\",\n \"city_state_zip\": \"Austin, TX 78701\",\n \"email\": \"ap@techstartinc.com\"\n },\n \"manufacturer\": {\n \"company_name\": \"Acme Corp\",\n \"address\": \"742 Evergreen Terrace\",\n \"city_state_zip\": \"Springfield, IL 62701\",\n \"email\": \"warranty@acmecorp.com\"\n },\n \"claimed_items\": [\n {\n \"product_description\": \"Dell OptiPlex 7000 Desktop (i7, 32GB RAM, 1TB SSD)\",\n \"serial_sku\": \"OPX7K-SN-00423\",\n \"qty\": 2,\n \"defect_type\": \"DOA \u2013 Unit fails to POST\",\n \"unit_price\": 1249.99,\n \"claim_value\": 2499.98\n },\n {\n \"product_description\": \"LG 27\\\" UltraFine 4K IPS Monitor (27UN850-W)\",\n \"serial_sku\": \"LG4K-SN-88812\",\n \"qty\": 1,\n \"defect_type\": \"Dead pixels (>5 cluster)\",\n \"unit_price\": 449.95,\n \"claim_value\": 449.95\n },\n {\n \"product_description\": \"Cisco Catalyst 9200L 24-Port PoE+ Managed Switch\",\n \"serial_sku\": \"CSC9200-SN-5501\",\n \"qty\": 1,\n \"defect_type\": \"PoE ports non-functional\",\n \"unit_price\": 3875.00,\n \"claim_value\": 3875.00\n }\n ],\n \"total_claim_value\": 6824.93,\n \"defect_description\": \"Units received on June 2, 2026 were inspected upon arrival. Two Dell OptiPlex desktops failed to complete POST and are unresponsive. The LG monitor exhibits a cluster of dead pixels in the upper-left quadrant exceeding the manufacturer threshold. The Cisco switch's PoE ports 1\u20138 do not deliver power despite correct configuration. All defects were identified within 5 business days of receipt.\",\n \"resolution_requested\": \"Full replacement units or a credit note for the total claim value to be applied against future orders.\"\n}"
},
"typeVersion": 1.3
},
{
"id": "47e85fb8-0200-465f-8f35-98f09d745521",
"name": "AI Bill Of Laden Analyzer Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1648,
-240
],
"parameters": {
"text": "={{ $json.content.parts[0].text }}",
"options": {
"systemMessage": "Structure the user message and return valid JSON using the given JSON schema. Make sure to only output the JSON and nothing else. "
},
"promptType": "define",
"needsFallback": true,
"hasOutputParser": true
},
"typeVersion": 3.1
},
{
"id": "cecfac0a-02b9-419a-b1af-e56260efc521",
"name": "AI Warranty Analyzer Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1648,
672
],
"parameters": {
"text": "={{ $json.content.parts[0].text }}",
"options": {
"systemMessage": "Structure the user message and return valid JSON using the given JSON schema. Make sure to only output the JSON and nothing else. "
},
"promptType": "define",
"needsFallback": true,
"hasOutputParser": true
},
"typeVersion": 3.1
},
{
"id": "bce30307-2d52-4bed-8392-1d7ef324ea6b",
"name": "AI Invoice Analyzer Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1648,
160
],
"parameters": {
"text": "={{ $json.content.parts[0].text }}",
"options": {
"systemMessage": "Structure the user message and return valid JSON using the given JSON schema. Make sure to only output the JSON and nothing else. "
},
"promptType": "define",
"needsFallback": true,
"hasOutputParser": true
},
"typeVersion": 3.1
},
{
"id": "80a9a30d-4e21-4d8f-ac79-ae8b34fb0e3c",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
944,
272
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.2
},
{
"id": "1fbfb317-8e9b-4238-b58e-07223f714e65",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1344,
-400
],
"parameters": {
"color": 7,
"width": 196,
"height": 1216,
"content": "## Document specific analysis\nAnalyze document specific structures and data"
},
"typeVersion": 1
},
{
"id": "f3a2442f-81fc-41f5-899a-dc9819b35e5f",
"name": "Validate Bill Of Laden",
"type": "n8n-nodes-base.code",
"position": [
2080,
-144
],
"parameters": {
"language": "pythonNative",
"pythonCode": "# Loop over input items and add a new field called 'my_new_field' to the JSON of each one\nfor item in _items:\n customer_orders = item[\"json\"].get(\"customer_orders\", [])\n carrier_line_items = item[\"json\"].get(\"carrier_line_items\", [])\n\n mismatches = []\n\n for order in customer_orders:\n order_number = order.get(\"customer_order_number\")\n order_pkgs = order.get(\"packages\")\n order_weight = order.get(\"weight_lbs\")\n\n # Find matching carrier line item by commodity description or index\n matched_carrier = next(\n (c for c in carrier_line_items if c.get(\"package\", {}).get(\"qty\") == order_pkgs),\n None\n )\n\n if matched_carrier is None:\n mismatches.append({\n \"order_number\": order_number,\n \"reason\": \"No matching carrier line item found\",\n \"order_packages\": order_pkgs,\n \"order_weight_lbs\": order_weight\n })\n else:\n carrier_pkgs = matched_carrier.get(\"package\", {}).get(\"qty\")\n carrier_weight = matched_carrier.get(\"weight_lbs\")\n\n pkg_match = order_pkgs == carrier_pkgs\n weight_match = order_weight == carrier_weight\n\n if not pkg_match or not weight_match:\n mismatches.append({\n \"order_number\": order_number,\n \"reason\": \"Package count or weight mismatch\",\n \"order_packages\": order_pkgs,\n \"carrier_packages\": carrier_pkgs,\n \"packages_match\": pkg_match,\n \"order_weight_lbs\": order_weight,\n \"carrier_weight_lbs\": carrier_weight,\n \"weight_match\": weight_match\n })\n\n all_match = len(mismatches) == 0\n\n item[\"json\"][\"validation\"] = {\n \"all_match\": all_match,\n \"mismatches\": mismatches if not all_match else []\n }\n\nreturn _items"
},
"typeVersion": 2
},
{
"id": "67310985-d127-4b96-bc6e-ab3a87b4123f",
"name": "AI Bill Of Laden Messaging Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
2592,
-240
],
"parameters": {
"text": "={{ $('Validate Bill Of Laden').item.json.output }}",
"options": {
"systemMessage": "You are an agent that answers emails. You will receive data from a workflow, that checked if an bill of lading has all necessary information in it. You only get messages where all is fine. Be sure to write a nice message of acceptance and list the items. Be sure to structure the message with a nice HTML layout. You will use your GMAIL tool for sending the message, which accpets HTML. "
},
"promptType": "define",
"needsFallback": true
},
"typeVersion": 3.1
},
{
"id": "f9b27564-9049-4b51-a4bb-24631164dcc5",
"name": "Send Gmail Message1",
"type": "n8n-nodes-base.gmailTool",
"position": [
2784,
384
],
"parameters": {
"sendTo": "={{ $('When Email Received').item.json.from.value[0].address }}",
"message": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Message', ``, 'string') }}",
"options": {},
"subject": "=RE: {{ $('When Email Received').item.json.headers.subject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "a8ace220-b2ce-44fe-99fe-e652c4a76f69",
"name": "Gemini Main Analysis 4",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
2528,
384
],
"parameters": {
"options": {},
"modelName": "models/gemini-3.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "e3645289-2d39-4942-b5c2-81845490b7b9",
"name": "Gemini Fallback Analysis 4",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
2656,
384
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "7007450b-0c87-4546-ba5d-16657edbdac7",
"name": "AI Invoice Messaging Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
2592,
160
],
"parameters": {
"text": "={{ $('Validate Invoice').item.json.output }}",
"options": {
"systemMessage": "You are an agent that answers emails. You will receive data from a workflow, that checked if an invoice has all necessary information in it. You only get messages where all is fine. Be sure to write a nice message of acceptance and list the items. Be sure to structure the message with a nice HTML layout. If you have line items createa a HTML table. You will use your GMAIL tool for sending the message, which accpets HTML. "
},
"promptType": "define",
"needsFallback": true
},
"typeVersion": 3.1
},
{
"id": "fda98199-4c63-46e4-9ec1-64054d1f3900",
"name": "Send Gmail Message2",
"type": "n8n-nodes-base.gmailTool",
"position": [
2784,
896
],
"parameters": {
"sendTo": "={{ $('When Email Received').item.json.from.value[0].address }}",
"message": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Message', ``, 'string') }}",
"options": {},
"subject": "=RE: {{ $('When Email Received').item.json.headers.subject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "e902a3e4-4314-4770-8c56-339632ee1206",
"name": "Gemini Main Analysis 5",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
2528,
896
],
"parameters": {
"options": {},
"modelName": "models/gemini-3.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "27aab945-c2a6-458d-98b2-c44b03226767",
"name": "Gemini Fallback Analysis 5",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
2656,
896
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "50cbcd1d-7568-426e-8c4c-7251ba028e34",
"name": "AI Warranty Messaging Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
2592,
672
],
"parameters": {
"text": "={{ $('Validate Warranty Claim').item.json.output }}",
"options": {
"systemMessage": "You are an agent that answers emails. You will receive data from a workflow, that checked if a warranty claim has all necessary information in it. You only get messages where all is fine. Be sure to write a nice message of acceptance and list the items. Be sure to structure the message with a nice HTML layout. You will use your GMAIL tool for sending the message, which accpets HTML. "
},
"promptType": "define",
"needsFallback": true
},
"typeVersion": 3.1
},
{
"id": "fd35f37f-1829-47e1-a5f8-18e8c113a785",
"name": "Validate Invoice",
"type": "n8n-nodes-base.code",
"position": [
2080,
272
],
"parameters": {
"language": "pythonNative",
"pythonCode": "# Loop over input items and validate that line item unit prices match the subtotal\nfor item in _items:\n line_items = item[\"json\"].get(\"line_items\", [])\n subtotal = item[\"json\"].get(\"subtotal\", 0)\n mismatches = []\n\n calculated_subtotal = 0\n for line_item in line_items:\n description = line_item.get(\"description\")\n qty = line_item.get(\"qty\", 0)\n unit_price = line_item.get(\"unit_price\", 0)\n total = line_item.get(\"total\", 0)\n\n expected_total = round(qty * unit_price, 2)\n actual_total = round(total, 2)\n\n calculated_subtotal += actual_total\n\n if expected_total != actual_total:\n mismatches.append({\n \"description\": description,\n \"reason\": \"Line item total does not match qty \u00d7 unit_price\",\n \"qty\": qty,\n \"unit_price\": unit_price,\n \"expected_total\": expected_total,\n \"actual_total\": actual_total\n })\n\n calculated_subtotal = round(calculated_subtotal, 2)\n subtotal = round(subtotal, 2)\n subtotal_match = calculated_subtotal == subtotal\n\n if not subtotal_match:\n mismatches.append({\n \"description\": \"Subtotal\",\n \"reason\": \"Sum of line item totals does not match subtotal\",\n \"calculated_subtotal\": calculated_subtotal,\n \"stated_subtotal\": subtotal\n })\n\n all_match = len(mismatches) == 0\n item[\"json\"][\"validation\"] = {\n \"all_match\": all_match,\n \"mismatches\": mismatches if not all_match else []\n }\n\nreturn _items"
},
"typeVersion": 2
},
{
"id": "77b349c2-ca28-408d-bee4-6602079629a9",
"name": "Validate Warranty Claim",
"type": "n8n-nodes-base.code",
"position": [
2080,
672
],
"parameters": {
"language": "pythonNative",
"pythonCode": "# Loop over input items and validate that claimed item values match the total claim value\nfor item in _items:\n claimed_items = item[\"json\"].get(\"claimed_items\", [])\n total_claim_value = item[\"json\"].get(\"total_claim_value\", 0)\n mismatches = []\n\n calculated_total = 0\n for claimed_item in claimed_items:\n description = claimed_item.get(\"product_description\")\n qty = claimed_item.get(\"qty\", 0)\n unit_price = claimed_item.get(\"unit_price\", 0)\n claim_value = claimed_item.get(\"claim_value\", 0)\n\n expected_claim_value = round(qty * unit_price, 2)\n actual_claim_value = round(claim_value, 2)\n\n calculated_total += actual_claim_value\n\n if expected_claim_value != actual_claim_value:\n mismatches.append({\n \"product_description\": description,\n \"reason\": \"Claim value does not match qty \u00d7 unit_price\",\n \"qty\": qty,\n \"unit_price\": unit_price,\n \"expected_claim_value\": expected_claim_value,\n \"actual_claim_value\": actual_claim_value\n })\n\n calculated_total = round(calculated_total, 2)\n stated_total = round(total_claim_value, 2)\n total_match = calculated_total == stated_total\n\n if not total_match:\n mismatches.append({\n \"product_description\": \"Total Claim Value\",\n \"reason\": \"Sum of claim values does not match total_claim_value\",\n \"calculated_total\": calculated_total,\n \"stated_total\": stated_total\n })\n\n all_match = len(mismatches) == 0\n item[\"json\"][\"validation\"] = {\n \"all_match\": all_match,\n \"mismatches\": mismatches if not all_match else []\n }\n\nreturn _items"
},
"typeVersion": 2
},
{
"id": "3a52928a-2916-42e2-8f48-703195f18598",
"name": "Analyze Bill Of Laden",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
1392,
-144
],
"parameters": {
"text": "Analyze the bill of laden document and structure the content to markdown:\n\n## SID\nCompany Name\n\n## SID City/State/Zip\nSID company City State and zip code\n\n## SID Address\nSID Company address\n\n## SID Name\nSID Company Name\n\n## CID\nCompany Name\n\n## CID City/State/Zip\nCID Customer City State and zip code\n\n## CID Address\nCID Customer address\n\n## CID Name\nCID Customer Name\n\n## Bill of Lading Number\nThe BOL number\n\n## Carrier Name\nName of the freight carrier company\n\n## Trailer number\nnumber of the trailer\n\n## Seal number\nID of the Seal\n\n## Customer Order Information Table\n| CUSTOMER ORDER NUMBER | # PKGS | WEIGHT | PALLET/SLIP (CIRCLE ONE) | ADDITIONAL SHIPPER INFO |\n|----------------------------|--------------------|---------------|--------------------------|----------------------------|\n| order id starting with ORD | number of packages | weight in lbs | Y/N | description of the article |\n\n## Carrier Information Table\n| HANDLING UNIT QTY | HANDLING UNIT TYPE | PACKAGE QTY | PACKAGE TYPE | WEIGHT WEIGHT | H.M.\u25a0(X) | COMMODITY DESCRIPTION COMMODITY DESCRIPTION | LTL ONLY NMFC # | LTL ONLY CLASS |\n|---------------------------|---------------------------|------------------|--------------|--------------------|----------|---------------------------------------------|-----------------|----------------|\n| Quantity of handling unit | Type of the handling unit | Package qunatity | Package type | Weight of the unit | H.M | Description of the Unit | NMFC number | LTL class |\n\n## Except as noted Date\nDate of the Carrier exeptance in the signature area",
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-3.1-flash-lite",
"cachedResultName": "models/gemini-3.1-flash-lite"
},
"options": {},
"resource": "document",
"inputType": "binary",
"binaryPropertyName": "attachment_0"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "98bb2c53-25c0-446f-9b34-dce9aa16c57f",
"name": "Analyze Invoice",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
1392,
272
],
"parameters": {
"text": "Analyze the invoice and structure the content to markdown:\n\n## Company Name (Seller)\nName of the selling company\n\n## Company Address (Seller)\nStreet address of the selling company\n\n## Company City/State/Zip (Seller)\nCity, state, and zip code of the selling company\n\n## Company Email (Seller)\nEmail address of the selling company\n\n## Customer Name (Buyer)\nName of the buying company\n\n## Customer Address (Buyer)\nStreet address of the buying company\n\n## Customer City/State/Zip (Buyer)\nCity, state, and zip code of the buying company\n\n## Customer Email (Buyer)\nEmail address of the buying company\n\n## Invoice Number\nThe invoice number (e.g. INV-2026-00847)\n\n## Invoice Date\nDate the invoice was issued\n\n## Due Date\nDate the payment is due\n\n## Payment Terms\nPayment terms (e.g. Net 30)\n\n## PO Number\nThe purchase order reference number\n\n## Line Items Table\n| DESCRIPTION | QTY | UNIT PRICE | TOTAL |\n|---|---|---|---|\n| Description of the product or service | Quantity ordered | Unit price in USD | Line total in USD |\n\n## Subtotal\nSum of all line items before tax\n\n## Tax\nTax amount applied (include rate if stated)\n\n## Total Due\nFinal amount due including tax\n\n## Payment Instructions\nAny payment method or remittance instructions noted on the invoice\n\n## Contact Information\nPhone number or additional contact details listed",
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-3.1-flash-lite",
"cachedResultName": "models/gemini-3.1-flash-lite"
},
"options": {},
"resource": "document",
"inputType": "binary",
"binaryPropertyName": "attachment_0"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "0fafb497-b179-49cc-a596-d57cc621ff05",
"name": "Analyze Warranty Claim",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
1392,
672
],
"parameters": {
"text": "Analyze the warranty claim and structure the content to markdown:\n\n## Claimant Company Name\nName of the company submitting the warranty claim\n\n## Claimant Address\nStreet address of the claimant\n\n## Claimant City/State/Zip\nCity, state, and zip code of the claimant\n\n## Claimant Email\nEmail address of the claimant\n\n## Manufacturer Company Name\nName of the manufacturer receiving the claim\n\n## Manufacturer Address\nStreet address of the manufacturer\n\n## Manufacturer City/State/Zip\nCity, state, and zip code of the manufacturer\n\n## Manufacturer Email\nWarranty email address of the manufacturer\n\n## Claim Number\nThe warranty claim number (e.g. WC-2026-00312)\n\n## Claim Date\nDate the claim was submitted\n\n## Original Invoice Number\nInvoice number the claimed items were purchased under\n\n## PO Number\nPurchase order reference number\n\n## Claim Status\nCurrent status of the claim (e.g. Pending Review, Approved, Rejected)\n\n## Priority\nPriority level of the claim (e.g. High, Medium, Low)\n\n## Claimed Items Table\n| PRODUCT DESCRIPTION | SERIAL / SKU | QTY | DEFECT TYPE | CLAIM VALUE |\n|---|---|---|---|---|\n| Name and specs of the defective product | Serial number or SKU | Quantity of defective units | Short description of the defect | Total claim value for this line in USD |\n\n## Total Claim Value\nSum of all line item claim values in USD\n\n## Defect Description\nFull narrative description of the defects observed\n\n## Resolution Requested\nWhat the claimant is requesting (replacement, credit note, refund, etc.)",
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-3.1-flash-lite",
"cachedResultName": "models/gemini-3.1-flash-lite"
},
"options": {},
"resource": "document",
"inputType": "binary",
"binaryPropertyName": "attachment_0"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "b54cb0bb-0fc6-4960-a112-fbc17e8490b8",
"connections": {
"Merge": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "Analyze Bill Of Laden",
"type": "main",
"index": 0
}
],
[
{
"node": "Analyze Invoice",
"type": "main",
"index": 0
}
],
[
{
"node": "Analyze Warranty Claim",
"type": "main",
"index": 0
}
]
]
},
"Analyze Invoice": {
"main": [
[
{
"node": "AI Invoice Analyzer Agent",
"type": "main",
"index": 0
}
]
]
},
"Validate Invoice": {
"main": [
[
{
"node": "Post to Webhook API1",
"type": "main",
"index": 0
}
]
]
},
"Send Gmail Message": {
"ai_tool": [
[
{
"node": "AI Bill Of Laden Messaging Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Post to Webhook API": {
"main": [
[
{
"node": "AI Bill Of Laden Messaging Agent",
"type": "main",
"index": 0
}
]
]
},
"Send Gmail Message1": {
"ai_tool": [
[
{
"node": "AI Invoice Messaging Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Send Gmail Message2": {
"ai_tool": [
[
{
"node": "AI Warranty Messaging Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"When Email Received": {
"main": [
[
{
"node": "Analyze Document with Gemini",
"type": "main",
"index": 0
},
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Post to Webhook API1": {
"main": [
[
{
"node": "AI Invoice Messaging Agent",
"type": "main",
"index": 0
}
]
]
},
"Post to Webhook API2": {
"main": [
[
{
"node": "AI Warranty Messaging Agent",
"type": "main",
"index": 0
}
]
]
},
"Analyze Bill Of Laden": {
"main": [
[
{
"node": "AI Bill Of Laden Analyzer Agent",
"type": "main",
"index": 0
}
]
]
},
"Gemini Main Analysis ": {
"ai_languageModel": [
[
{
"node": "AI Invoice Analyzer Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Analyze Warranty Claim": {
"main": [
[
{
"node": "AI Warranty Analyzer Agent",
"type": "main",
"index": 0
}
]
]
},
"Gemini Main Analysis 1": {
"ai_languageModel": [
[
{
"node": "AI Bill Of Laden Analyzer Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Gemini Main Analysis 2": {
"ai_languageModel": [
[
{
"node": "AI Bill Of Laden Messaging Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Gemini Main Analysis 3": {
"ai_languageModel": [
[
{
"node": "AI Warranty Analyzer Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Gemini Main Analysis 4": {
"ai_languageModel": [
[
{
"node": "AI Invoice Messaging Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Gemini Main Analysis 5": {
"ai_languageModel": [
[
{
"node": "AI Warranty Messaging Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Validate Bill Of Laden": {
"main": [
[
{
"node": "Post to Webhook API",
"type": "main",
"index": 0
}
]
]
},
"Parse Structured Output": {
"ai_outputParser": [
[
{
"node": "AI Bill Of Laden Analyzer Agent",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Validate Warranty Claim": {
"main": [
[
{
"node": "Post to Webhook API2",
"type": "main",
"index": 0
}
]
]
},
"Parse Structured Output1": {
"ai_outputParser": [
[
{
"node": "AI Invoice Analyzer Agent",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Parse Structured Output2": {
"ai_outputParser": [
[
{
"node": "AI Warranty Analyzer Agent",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"AI Invoice Analyzer Agent": {
"main": [
[
{
"node": "Validate Invoice",
"type": "main",
"index": 0
}
]
]
},
"Gemini Fallback Analysis ": {
"ai_languageModel": [
[
{
"node": "AI Invoice Analyzer Agent",
"type": "ai_languageModel",
"index": 1
}
]
]
},
"AI Warranty Analyzer Agent": {
"main": [
[
{
"node": "Validate Warranty Claim",
"type": "main",
"index": 0
}
]
]
},
"Gemini Fallback Analysis 1": {
"ai_languageModel": [
[
{
"node": "AI Bill Of Laden Analyzer Agent",
"type": "ai_languageModel",
"index": 1
}
]
]
},
"Gemini Fallback Analysis 2": {
"ai_languageModel": [
[
{
"node": "AI Bill Of Laden Messaging Agent",
"type": "ai_languageModel",
"index": 1
}
]
]
},
"Gemini Fallback Analysis 3": {
"ai_languageModel": [
[
{
"node": "AI Warranty Analyzer Agent",
"type": "ai_languageModel",
"index": 1
}
]
]
},
"Gemini Fallback Analysis 4": {
"ai_languageModel": [
[
{
"node": "AI Invoice Messaging Agent",
"type": "ai_languageModel",
"index": 1
}
]
]
},
"Gemini Fallback Analysis 5": {
"ai_languageModel": [
[
{
"node": "AI Warranty Messaging Agent",
"type": "ai_languageModel",
"index": 1
}
]
]
},
"Analyze Document with Gemini": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"AI Bill Of Laden Analyzer Agent": {
"main": [
[
{
"node": "Validate Bill Of Laden",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googlePalmApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow monitors Gmail for unread emails from a specific sender, classifies attached documents with Google Gemini, then extracts and validates structured data for bills of lading, invoices, and warranty claims, posts the results to an HTTP webhook endpoint, and replies to…
Source: https://n8n.io/workflows/16181/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow triggers on a Gmail message from a specific sender, extracts bill of lading data from an email attachment using Google Gemini, validates the extracted values with Python, posts the struc
This Shopify AI automation is an advanced n8n-powered workflow that transforms Shopify product collections into SEO-optimized blog articles with images, while maintaining full visibility and control t
This workflow is designed for e-commerce, marketing teams, or creators who want to automate the production of high-quality, AI-generated product visuals and ad creatives.
CV → Match → Screen → Decide, all automated
This n8n workflow automates sales processes using AI agents integrated with Airtable as a CRM and Gmail for email handling. It consists of two main workflows: one for handling Airtable status changes