{
  "name": "Export AI agent conversation logs from Postgres to Google Sheets",
  "nodes": [
    {
      "id": "0a03e403-4a72-4382-b648-602f4bd6ef87",
      "name": "When clicking ‘Test workflow’",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1720,
        380
      ]
    },
    {
      "id": "a421a477-bcee-460c-bc6a-8150a924fdd3",
      "name": "add create_at column",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -1640,
        -100
      ]
    },
    {
      "id": "0cb5189e-857d-49a1-a8e9-923d4f955383",
      "name": "Get conversations by sessionId",
      "type": "n8n-nodes-base.postgres",
      "position": [
        380,
        480
      ]
    },
    {
      "id": "72d8c711-a3f9-4f95-b79a-a9190d2b4964",
      "name": "Duplicate template sheet",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -400,
        600
      ]
    },
    {
      "id": "940fae1e-1ab7-4211-8d9f-fe5b9274e5e5",
      "name": "Clear Sheet Content",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -760,
        460
      ]
    },
    {
      "id": "b16e85bc-a84b-4da0-85da-568a1c981e02",
      "name": "Rename Sheet",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -200,
        600
      ]
    },
    {
      "id": "63ac37f4-1f80-4e5a-9af4-ec2e05cbaccb",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1720,
        560
      ]
    },
    {
      "id": "81cfed36-ee79-408f-8bad-0147a8acb0b3",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1740,
        -480
      ],
      "parameters": {
        "width": 320,
        "height": 540,
        "content": "## Add a datetime column\nIf not already done, add a `created_at` column to store the datetime of the message\n\n\n👉 Ideally, do it before your first interaction, otherwise all your previous conversations"
      }
    },
    {
      "id": "cecbaa6a-5d8b-4704-b249-bcd336875773",
      "name": "Set session_id",
      "type": "n8n-nodes-base.set",
      "position": [
        -20,
        600
      ]
    },
    {
      "id": "1f8b387b-52d0-4023-9d4b-4dd61272fe82",
      "name": "Postgres - Get session ids",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -1380,
        420
      ]
    },
    {
      "id": "2ab2fc24-1c19-4c08-b20f-121bf22c6f9c",
      "name": "Loop Over Session IDs",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -1060,
        420
      ]
    },
    {
      "id": "46763fb1-bf18-44a4-82b8-26e09325f159",
      "name": "Add conversations",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        560,
        640
      ]
    },
    {
      "id": "4b711779-938d-4a51-96dc-a3a629cfdcb3",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1400,
        -480
      ],
      "parameters": {
        "width": 360,
        "height": 540,
        "content": "## For Supabase users\nAlthough in theory you could use Supabase native nodes, I found it easier to use PG. It's also more sustainable in the long term.\n\n### Get your Supabase credentials\n1. Go to your"
      }
    },
    {
      "id": "2389393d-3e62-4349-a1cd-819d2b010f29",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1460,
        140
      ],
      "parameters": {
        "width": 280,
        "height": 720,
        "content": "## Get all sessions \nIn this node, we execute a SQL query that collects all sessionIDs.\n\n**Replace** the name of your chat memory before executing the request"
      }
    },
    {
      "id": "eb323ee1-7afb-421d-86f4-02846782fb3e",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -500,
        -620
      ],
      "parameters": {
        "width": 440,
        "height": 700,
        "content": "## Important - How it works\n- Each time this workflow is executed, all conversations are cleared and replaced in order to always have up to date data.\n- The reason is that the sessionID can be overrid"
      }
    },
    {
      "id": "3ca21e1a-1c1c-4064-9e06-540aef692291",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1160,
        140
      ],
      "parameters": {
        "width": 280,
        "height": 720,
        "content": "## Loop over each session\nThis node iterates over each session and add it in a separate sheet"
      }
    },
    {
      "id": "135eb659-31d5-4760-af09-938c3913bb6c",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1000,
        -480
      ],
      "parameters": {
        "width": 360,
        "height": 540,
        "content": "## Google Sheets template\nhttps://docs.google.com/spreadsheets/d/14bKI5J0h18Nv48jbe1IXpZWma6EtqYLFWnpKoCB5Bgc/edit?usp=sharing"
      }
    },
    {
      "id": "6c329217-3f99-40bd-8ff5-57b2266f4012",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1780,
        -620
      ],
      "parameters": {
        "width": 1240,
        "height": 700,
        "content": "# Setup\n### 👉 Make sure to double check these steps before launching this workflow for the first time"
      }
    },
    {
      "id": "b06b11b7-e0c7-491c-b7ce-4e321187663c",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -860,
        140
      ],
      "parameters": {
        "width": 340,
        "height": 720,
        "content": "## Clear Google Sheet content\nThis will clear each Google Sheets data in order to have up to date data.\n\nError path: the error path is actually normal, it happens if the `session_id` doesn't already e"
      }
    },
    {
      "id": "495026a8-4b3a-4ad8-8bf4-120cfa039a63",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -460,
        140
      ],
      "parameters": {
        "width": 640,
        "height": 720,
        "content": "## Create a new Google Sheet based on a template\nThis part of the workflow prepares a fresh sheet for each session by copying a predefined template.\n\n**What it does:**\n**Clear Sheet Content**\nClears t"
      }
    },
    {
      "id": "8eaba5f3-3455-43c0-bffa-6a0bbde39de7",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        220,
        140
      ],
      "parameters": {
        "width": 620,
        "height": 720,
        "content": "## Store transcripts in Google Sheets\nThis section writes each session's messages into its corresponding sheet.\n\n**What it does:**\n* Appends new rows to the sheet named after the `session_id`.\n* Each "
      }
    },
    {
      "id": "6f802f26-e4b2-4787-bc0c-f3f800d79f74",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1800,
        140
      ],
      "parameters": {
        "width": 280,
        "height": 720,
        "content": "## Triggers\nTest it manually, then, once validated, create a scheduler for it to run hourly, daily, weekly... or even create an external trigger. \nYour choice!"
      }
    },
    {
      "id": "145ee4b6-d492-4533-83a0-2096aff97cca",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2740,
        -620
      ],
      "parameters": {
        "width": 860,
        "height": 1480,
        "content": "# Store n8n AI Agent Memory Logs in Google Sheets\n\n## Overview\nThis n8n workflow retrieves AI agent chat memory logs stored in Postgres and pushes them to Google Sheets, creating one sheet per session"
      }
    }
  ],
  "connections": {
    "Rename Sheet": {
      "main": [
        [
          {
            "node": "Set session_id",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set session_id": {
      "main": [
        [
          {
            "node": "Clear Sheet Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Postgres - Get session ids",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add conversations": {
      "main": [
        [
          {
            "node": "Loop Over Session IDs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clear Sheet Content": {
      "main": [
        [
          {
            "node": "Get conversations by sessionId",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Duplicate template sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Session IDs": {
      "main": [
        [],
        [
          {
            "node": "Clear Sheet Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Duplicate template sheet": {
      "main": [
        [
          {
            "node": "Rename Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Postgres - Get session ids": {
      "main": [
        [
          {
            "node": "Loop Over Session IDs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get conversations by sessionId": {
      "main": [
        [
          {
            "node": "Add conversations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Test workflow’": {
      "main": [
        [
          {
            "node": "Postgres - Get session ids",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}