AutomationFlowsAI & RAG › Automated Expense Approval System with Gpt-4, Airtable & Pinecone Vector Db

Automated Expense Approval System with Gpt-4, Airtable & Pinecone Vector Db

ByYaron Been @yaron-nofluff on n8n.io

Automate expense reviews with AI-powered CFO-level analysis. This workflow monitors Airtable expense submissions, uses GPT-4 to analyze expenses like an experienced CFO, flags suspicious expenses with detailed reasoning, and maintains comprehensive audit trails in Pinecone…

Event trigger★★★★☆ complexityAI-powered15 nodesAirtable TriggerAgentOpenAI ChatOutput Parser StructuredPinecone Vector StoreOpenAI EmbeddingsDocument Default Data LoaderText Splitter Recursive Character Text Splitter
AI & RAG Trigger: Event Nodes: 15 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #4576 — we link there as the canonical source.

This workflow follows the Agent → Airtable 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 →

Download .json
{
  "id": "zA3j2ZTGRt82vwa6",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "CFO Expense Reviewer Agent",
  "tags": [],
  "nodes": [
    {
      "id": "7fec5e7c-abea-4caf-b8e2-718e7abc44ef",
      "name": "Watch New Expense Requests",
      "type": "n8n-nodes-base.airtableTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "baseId": {
          "__rl": true,
          "mode": "url",
          "value": "https://airtable.com/appjaqV0O7FkXT2qj/shrst7GnlbzMDz4te"
        },
        "tableId": {
          "__rl": true,
          "mode": "url",
          "value": "https://airtable.com/appjaqV0O7FkXT2qj/tblTAvRqVFOo5AVDF/viwEp0ssaidZOo4nl?blocks=hide"
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyHour"
            }
          ]
        },
        "triggerField": "Amount",
        "authentication": "airtableTokenApi",
        "additionalFields": {}
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8e0fa6f3-df8c-42b6-af2a-f2cfb25f1e6d",
      "name": "CFO Expense Review Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        440,
        0
      ],
      "parameters": {
        "text": "=An employee submitted an expense:\nAmount: ${{ $json.fields.Amount }}\nSubmitted by: {{ $json.fields['Submitted By'] }}\nCategory: {{ $json.fields.Category }}\nDescription: {{ $json.fields.Description }}\nDate Submitted: {{ $json.fields['Date Submitted'] }}\nStatus: {{ $json.fields.Status }}",
        "options": {
          "systemMessage": "You are a CFO expense analysis agent. Flag suspicious expenses with the reason. When you answer try to give answer with all the given details"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "e53c34b4-fe86-4c70-ad90-e61ec4f8c72b",
      "name": "OpenAI GPT-4 Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        360,
        260
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a561418a-2ef0-44bb-9683-ba239d58a3af",
      "name": "Parse CFO Agent Response",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        620,
        220
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"amount\": 4500,\n  \"submitted_by\": \"Alice\",\n  \"category\": \"Travel\",\n  \"description\": \"Business class flight to Tokyo\",\n  \"date_submitted\": \"2025-05-29\",\n  \"status\": \"Pending\",\n  \"decision\": \"Flagged\",\n  \"reason\": \"The amount of $4500 for a business class flight appears unusually high and requires verification against standard travel policies and previous similar expenses. Additionally, the submission date is in the future (2025), which raises concerns about the legitimacy of the expense. It is advisable to confirm the travel plans and the necessity of the business class flight for this trip.\"\n}\n"
      },
      "typeVersion": 1.2
    },
    {
      "id": "1cba2b01-faeb-44ce-97e3-b3ada02ce748",
      "name": "Store Decision in Pinecone",
      "type": "@n8n/n8n-nodes-langchain.vectorStorePinecone",
      "position": [
        1040,
        0
      ],
      "parameters": {
        "mode": "insert",
        "options": {
          "pineconeNamespace": "={{ $json.output.decision }}"
        },
        "pineconeIndex": {
          "__rl": true,
          "mode": "list",
          "value": "new",
          "cachedResultName": "new"
        }
      },
      "credentials": {
        "pineconeApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "5a80d379-907e-43c0-946e-fc82be36c288",
      "name": "Generate Embeddings",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "position": [
        980,
        240
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "50c1a961-cc58-4b6a-bf46-da0925b617e2",
      "name": "Prepare Data for Pinecone",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "position": [
        1180,
        220
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "2484db3c-bef8-4b0e-a324-116dc70644a9",
      "name": "Split Reasoning Text",
      "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
      "position": [
        1120,
        440
      ],
      "parameters": {
        "options": {},
        "chunkSize": 100,
        "chunkOverlap": 20
      },
      "typeVersion": 1
    },
    {
      "id": "cd1a7b50-edd7-400a-8fc8-ff237492749b",
      "name": "Update Airtable Record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1680,
        0
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appjaqV0O7FkXT2qj",
          "cachedResultUrl": "https://airtable.com/appjaqV0O7FkXT2qj",
          "cachedResultName": "Table no.1"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblTAvRqVFOo5AVDF",
          "cachedResultUrl": "https://airtable.com/appjaqV0O7FkXT2qj/tblTAvRqVFOo5AVDF",
          "cachedResultName": "Table 1"
        },
        "columns": {
          "value": {
            "id": "={{ $('Watch New Expense Requests').item.json.id }}",
            "Amount": "={{ $('CFO Expense Review Agent').item.json.output.amount }}",
            "Reason": "={{ $('CFO Expense Review Agent').item.json.output.reason }}",
            "Status": "=completed",
            "Category": "={{ $('CFO Expense Review Agent').item.json.output.category }}",
            "decision": "={{ $('CFO Expense Review Agent').item.json.output.decision }}",
            "Description": "={{ $('CFO Expense Review Agent').item.json.output.description }}",
            "Submitted By": "={{ $('CFO Expense Review Agent').item.json.output.submitted_by }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": true
            },
            {
              "id": "Amount",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Category",
              "type": "options",
              "display": true,
              "options": [
                {
                  "name": "Self-cleaning, keeps drinks cold for 24 hrs, BPA-free",
                  "value": "Self-cleaning, keeps drinks cold for 24 hrs, BPA-free"
                },
                {
                  "name": "Travel",
                  "value": "Travel"
                }
              ],
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Description",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Submitted By",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Submitted By",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date Submitted",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "Date Submitted",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "decision",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "decision",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reason",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Reason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a45e7430-d205-4930-9b15-b52e51139d58",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -100,
        -480
      ],
      "parameters": {
        "color": 2,
        "width": 340,
        "height": 680,
        "content": "## \ud83d\udd01 **Section 1: Intake \u2013 Monitoring Expense Requests**\n\n### 1. **Watch New Expense Requests**\n\n**(Airtable Trigger)**\n\n* **Purpose:** Continuously monitors the Airtable `Expenses` table for new or updated entries with `Status = Pending`.\n* **What it does:** Triggers the entire workflow when a new expense is submitted or an existing one is updated for review.\n\n> \ud83d\udca1 Ensures real-time detection of incoming requests that need analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "6d6229ee-a86b-442f-ab8e-25d44b9bbe24",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -600
      ],
      "parameters": {
        "color": 6,
        "width": 500,
        "height": 1020,
        "content": "\ud83e\udde0 Section 2: AI Analysis \u2013 CFO Reasoning Engine\n2. CFO Expense Review Agent\n(AI Agent - Tools Agent)\n\nPurpose: Acts as a virtual CFO. It receives the expense data and reasons through the submission using a language model.\n\nConnected To: OpenAI GPT-4 Model and Structured Output Parser\n\n3. OpenAI GPT-4 Model\n(OpenAI Chat Model)\n\nPurpose: Powers the logic behind the CFO's decision-making.\n\nPrompt Format: Given structured context about the expense, it determines whether it should be flagged and explains why.\n\n4. Parse CFO Agent Response\n(Structured Output Parser)\n\nPurpose: Transforms the unstructured response from GPT into a clean JSON object.\n\nOutput: Fields like decision, reason, amount, submitted_by, category, etc., which can be used for downstream processing.\n\n\ud83e\udde9 This section gives intelligence to the system, allowing it to make smart and explainable decisions."
      },
      "typeVersion": 1
    },
    {
      "id": "66201323-99aa-4d5e-ab1d-afcc3951e271",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        920,
        -740
      ],
      "parameters": {
        "color": 7,
        "width": 580,
        "height": 1320,
        "content": "\ud83e\uddec Section 3: Audit Trail \u2013 Embedding & Storage\n5. Prepare Data for Pinecone\n(Default Data Loader)\n\nPurpose: Loads the document (usually the reasoning or description) for embedding.\n\nInput: Reasoning text or metadata generated by the AI agent.\n\n6. Split Reasoning Text\n(Recursive Character Text Splitter)\n\nPurpose: Splits long reasoning content into smaller chunks (if needed) to fit OpenAI embedding limits.\n\n7. Generate Embeddings\n(Embeddings OpenAI)\n\nPurpose: Converts the textual reasoning into a vector representation using OpenAI's embedding model.\n\n8. Store Decision in Pinecone\n(Pinecone Vector Store)\n\nPurpose: Saves the embedded vector along with metadata like decision, amount, and reason.\n\nGoal: Creates a searchable, auditable archive of past decisions for future reference and pattern learning.\n\n\ud83e\uddfe This section builds a scalable memory system for compliance and insights over time."
      },
      "typeVersion": 1
    },
    {
      "id": "117ba355-f8cd-465d-bbe6-1b37261f4640",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1600,
        -340
      ],
      "parameters": {
        "color": 3,
        "width": 300,
        "height": 540,
        "content": "\u2705 Section 4: Output \u2013 Updating Records\n9. Update Airtable Record\n(Airtable Update Node)\n\nPurpose: Writes the final decision (Approved or Flagged) and the reasoning back to the original Airtable record.\n\nFields Updated: Status, Reason, and optionally an ReviewedAt timestamp.\n\n\ud83d\udce5 Ensures that Airtable remains the source of truth, visibly updated with the CFO agent\u2019s input."
      },
      "typeVersion": 1
    },
    {
      "id": "e379569e-98b3-47d6-b60d-9faa1babdf1d",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1880,
        -500
      ],
      "parameters": {
        "color": 4,
        "width": 1300,
        "height": 320,
        "content": "=======================================\n            WORKFLOW ASSISTANCE\n=======================================\nFor any questions or support, please contact:\n    Yaron@nofluff.online\n\nExplore more tips and tutorials here:\n   - YouTube: https://www.youtube.com/@YaronBeen/videos\n   - LinkedIn: https://www.linkedin.com/in/yaronbeen/\n=======================================\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ec9af853-11be-4651-9978-c9f2f9a120ae",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1880,
        -160
      ],
      "parameters": {
        "color": 4,
        "width": 1289,
        "height": 2258,
        "content": "## \ud83d\udcca **CFO Expense Approval Workflow Overview**\n\nThis workflow automates the process of monitoring, analyzing, and auditing expense requests using Airtable, OpenAI, and Pinecone. It is organized into the following four sections:\n\n---\n\n## \ud83d\udd01 **Section 1: Intake \u2013 Monitoring Expense Requests**\n\n### 1. **Watch New Expense Requests**\n\n**(Airtable Trigger)**\n\n* **Purpose:** Continuously monitors the Airtable `Expenses` table for new or updated entries with `Status = Pending`.\n* **What it does:** Triggers the entire workflow when a new expense is submitted or an existing one is updated for review.\n\n> \ud83d\udca1 Ensures real-time detection of incoming requests that need analysis.\n\n---\n\n## \ud83e\udde0 **Section 2: AI Analysis \u2013 CFO Reasoning Engine**\n\n### 2. **CFO Expense Review Agent**\n\n**(AI Agent - Tools Agent)**\n\n* **Purpose:** Acts as a virtual CFO. It receives the expense data and reasons through the submission using a language model.\n* **Connected To:** OpenAI GPT-4 Model and Structured Output Parser\n\n### 3. **OpenAI GPT-4 Model**\n\n**(OpenAI Chat Model)**\n\n* **Purpose:** Powers the logic behind the CFO's decision-making.\n* **Prompt Format:** Given structured context about the expense, it determines whether it should be flagged and explains why.\n\n### 4. **Parse CFO Agent Response**\n\n**(Structured Output Parser)**\n\n* **Purpose:** Transforms the unstructured response from GPT into a clean JSON object.\n* **Output:** Fields like `decision`, `reason`, `amount`, `submitted_by`, `category`, etc., which can be used for downstream processing.\n\n> \ud83e\udde9 This section gives intelligence to the system, allowing it to make smart and explainable decisions.\n\n---\n\n## \ud83e\uddec **Section 3: Audit Trail \u2013 Embedding & Storage**\n\n### 5. **Prepare Data for Pinecone**\n\n**(Default Data Loader)**\n\n* **Purpose:** Loads the document (usually the reasoning or description) for embedding.\n* **Input:** Reasoning text or metadata generated by the AI agent.\n\n### 6. **Split Reasoning Text**\n\n**(Recursive Character Text Splitter)**\n\n* **Purpose:** Splits long reasoning content into smaller chunks (if needed) to fit OpenAI embedding limits.\n\n### 7. **Generate Embeddings**\n\n**(Embeddings OpenAI)**\n\n* **Purpose:** Converts the textual reasoning into a vector representation using OpenAI's embedding model.\n\n### 8. **Store Decision in Pinecone**\n\n**(Pinecone Vector Store)**\n\n* **Purpose:** Saves the embedded vector along with metadata like decision, amount, and reason.\n* **Goal:** Creates a searchable, auditable archive of past decisions for future reference and pattern learning.\n\n> \ud83e\uddfe This section builds a scalable **memory system** for compliance and insights over time.\n\n---\n\n## \u2705 **Section 4: Output \u2013 Updating Records**\n\n### 9. **Update Airtable Record**\n\n**(Airtable Update Node)**\n\n* **Purpose:** Writes the final decision (`Approved` or `Flagged`) and the reasoning back to the original Airtable record.\n* **Fields Updated:** `Status`, `Reason`, and optionally an `ReviewedAt` timestamp.\n\n> \ud83d\udce5 Ensures that Airtable remains the **source of truth**, visibly updated with the CFO agent\u2019s input.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "40c83424-4fdd-4bd8-84fc-4418bdbaf450",
  "connections": {
    "OpenAI GPT-4 Model": {
      "ai_languageModel": [
        [
          {
            "node": "CFO Expense Review Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Generate Embeddings": {
      "ai_embedding": [
        [
          {
            "node": "Store Decision in Pinecone",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Split Reasoning Text": {
      "ai_textSplitter": [
        [
          {
            "node": "Prepare Data for Pinecone",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    },
    "CFO Expense Review Agent": {
      "main": [
        [
          {
            "node": "Store Decision in Pinecone",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse CFO Agent Response": {
      "ai_outputParser": [
        [
          {
            "node": "CFO Expense Review Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Data for Pinecone": {
      "ai_document": [
        [
          {
            "node": "Store Decision in Pinecone",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Store Decision in Pinecone": {
      "main": [
        [
          {
            "node": "Update Airtable Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Watch New Expense Requests": {
      "main": [
        [
          {
            "node": "CFO Expense Review Agent",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Automate expense reviews with AI-powered CFO-level analysis. This workflow monitors Airtable expense submissions, uses GPT-4 to analyze expenses like an experienced CFO, flags suspicious expenses with detailed reasoning, and maintains comprehensive audit trails in Pinecone…

Source: https://n8n.io/workflows/4576/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This advanced n8n workflow automates the full lead enrichment, qualification, and personalized outreach process tailored specifically for the B2B real estate sector. Integrating top platforms like Api

N8N Nodes Fillout, OpenAI Chat, Pinecone Vector Store +11
AI & RAG

This n8n template automatically classifies incoming emails (Sales, Support, Internal, Finance, Promotions) and routes them to a dedicated OpenAI LLM Agent for processing. Depending on the category, th

OpenAI, Gmail, Text Classifier +16
AI & RAG

Automate Outreach Prospect automates finding, enriching, and messaging potential partners (like restaurants, malls, and bars) using Apify Google Maps scraping, Perplexity enrichment, OpenAI LLMs, Goog

@Devlikeapro/N8N Nodes Waha, Google Drive Trigger, @Apify/N8N Nodes Apify +14
AI & RAG

Build a powerful, customizable AI chatbot for your WordPress website that intelligently retrieves posts, answers questions, and engages in natural conversations. This complete solution handles content

Qdrant Vector Store, OpenAI Embeddings, Document Default Data Loader +10
AI & RAG

Code Extractfromfile. Uses manualTrigger, sort, httpRequest, compression. Event-driven trigger; 50 nodes.

HTTP Request, Compression, Edit Image +15