{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "da09cc5d-4b12-4a17-8916-ed24446e041f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2400,
        -48
      ],
      "parameters": {
        "width": 480,
        "height": 656,
        "content": "## Chat with databricks\n\n### How it works\n\n1. A Slack trigger initiates the workflow upon receiving a message. 2. The workflow fetches the Databricks table schema and parses it for the AI model. 3. An AI agent processes the data using a chat model and SQL tools to generate a response. 4. The workflow evaluates the AI output and sends a message back via Slack.\n\n### Setup steps\n\n- Configure the Slack Trigger node with your Slack app credentials.\n- Update the Databricks Configuration node with your target table and warehouse IDs.\n- Ensure the AI Agent has valid Google Gemini and Redis credentials.\n- Connect the Slack nodes to your workspace's notification channel.\n\n### Customization\n\nAdjust the system prompt in the AI agent to tailor the SQL generation style for your specific database schema."
      },
      "typeVersion": 1
    },
    {
      "id": "4df1fe14-99b9-4c68-bf3d-c13f827decf2",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2944,
        128
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 272,
        "content": "## Initialize trigger and connection\n\nTriggering the process and preparing Databricks connection details."
      },
      "typeVersion": 1
    },
    {
      "id": "4f0836ac-a5b8-4749-97d4-4c50c163d66f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3584,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 544,
        "content": "## Process schema and AI agent\n\nParsing table schema and processing AI logic using Gemini and tools to execute generated sql query."
      },
      "typeVersion": 1
    },
    {
      "id": "334d777e-dfa3-4df4-9d2a-eca0f2a3a7cc",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4272,
        -48
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 560,
        "content": "## Evaluate conditions and report\n\nHandling conditional responses and final Slack notifications."
      },
      "typeVersion": 1
    },
    {
      "id": "a9f9654f-f76a-4646-b2eb-28adbe041d3b",
      "name": "When Slack Message Received",
      "type": "n8n-nodes-base.slackTrigger",
      "position": [
        2992,
        240
      ],
      "parameters": {
        "options": {},
        "trigger": [
          "app_mention"
        ],
        "watchWorkspace": true
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "80f0882d-dd25-4e3b-b5c4-2b605359f3ff",
      "name": "Parse Table Schema",
      "type": "n8n-nodes-base.code",
      "position": [
        3648,
        240
      ],
      "parameters": {
        "jsCode": "// Get the rows from the Databricks result\nconst rows = $json.result.data_array;\n\n// Map the rows into a structured object\nconst structuredSchema = rows.map(row => {\n  return {\n    column: row[0],\n    type: row[1],\n    description: row[2] || \"No description provided\"\n  };\n});\n\n// Create a simplified string version for the AI Prompt\nconst simpleText = rows.map(row => `- ${row[0]} (${row[1]})`).join('\\n');\n\nreturn [{\n  json: {\n    table_name: \"franchises\", // You can pass this dynamically if needed\n    columns_count: structuredSchema.length,\n    schema_details: structuredSchema,\n    ai_friendly_schema: simpleText\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "69c720ed-86e4-4edf-bbf8-79c01fb40c90",
      "name": "Post to Slack Channel",
      "type": "n8n-nodes-base.slack",
      "position": [
        4560,
        80
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('When Slack Message Received').item.json.channel }}"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "7d5794c0-19a4-4f31-b9bd-a86fb7eb4b4b",
      "name": "Fetch Databricks Schema",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3408,
        240
      ],
      "parameters": {
        "url": "https://enter-your-databricks-url.cloud.databricks.com/api/2.0/sql/statements",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "warehouse_id",
              "value": "={{ $json.warehouse_id }}"
            },
            {
              "name": "statement",
              "value": "=DESCRIBE {{ $json.target_table }}"
            },
            {
              "name": "wait_timeout",
              "value": "50s"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "0faf472b-c048-4879-b0b1-147a81392aba",
      "name": "Set Databricks Config",
      "type": "n8n-nodes-base.set",
      "position": [
        3200,
        240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e4bb3b8f-f081-4c1e-a548-7156daed098b",
              "name": "target_table",
              "type": "string",
              "value": "enter_your_databricks_table_id"
            },
            {
              "id": "ffb52ca6-fbab-45ad-82cb-bb6872462ba4",
              "name": "warehouse_id",
              "type": "string",
              "value": "enter_your_databricks_warehouse_id"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "29de86cd-0e50-4976-93a6-c3812a911dfc",
      "name": "SQL Data Analyst Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        3872,
        240
      ],
      "parameters": {
        "text": "=You are an expert Databricks SQL analyst.\n\nYour goal is to answer the user's question by:\n1. Generating ONE SQL query\n2. Executing it using the SQL execution tool\n3. Interpreting the results and providing a clear, conversational answer\n\nSchema:\n{{ $json.ai_friendly_schema }}\n\nUser question:\n{{ $('When Slack Message Received').item.json.text }}\\\n\nTable ID:\n{{ $('Set Databricks Config').item.json.target_table }}\n\nRULES:\n- Use the SQL execution tool ONLY ONCE\n- After getting results, provide a clear answer in natural language\n- Format numbers and data in a readable way\n- If the question doesn't need database data, answer directly without using the tool",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "a91bbc88-0063-4a23-ba0f-2770e61070c1",
      "name": "Gemini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        3744,
        448
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-3.1-flash-lite-preview"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8b21f5c3-0ec3-4cf6-9b36-362ce2c162ac",
      "name": "Redis Chat Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryRedisChat",
      "position": [
        3936,
        448
      ],
      "parameters": {
        "sessionKey": "={{ $('When Slack Message Received').item.json.thread_ts || $('When Slack Message Received').item.json.ts }}",
        "sessionTTL": 60,
        "sessionIdType": "customKey"
      },
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.5
    },
    {
      "id": "c6e06aa2-79fe-472c-8ceb-353843e12ee2",
      "name": "Run Primary SQL Query",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        4112,
        448
      ],
      "parameters": {
        "url": "https://enter-your-databricks-url-here.cloud.databricks.com/api/2.0/sql/statements",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "warehouse_id",
              "value": "={{ $('Set Databricks Config').item.json.warehouse_id }}"
            },
            {
              "name": "statement",
              "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('parameters1_Value', ``, 'string') }}"
            },
            {
              "name": "wait_timeout",
              "value": "50s"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth",
        "toolDescription": "Executes a single SQL query on Databricks.\n\nIMPORTANT:\n- This tool can be used ONLY ONCE per request.\n- The AI must provide a complete SQL query in the \"statement\" field.\n- After execution, the AI must produce a final answer and MUST NOT call this tool again.\n\nReturns query results in JSON format."
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "490fac20-41ef-465f-81ec-b0efed3ffcab",
      "name": "If Output Valid",
      "type": "n8n-nodes-base.if",
      "position": [
        4320,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "fe5bbd74-d036-4c5b-a6e5-090ef9dcf515",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $('When Slack Message Received').item.json.thread_ts \n   ? 'thread[' + $('When Slack Message Received').item.json.thread_ts + ']' \n   : 'message_ts[' + $('When Slack Message Received').item.json.ts + ']' \n}}",
              "rightValue": "message"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3
    },
    {
      "id": "24e93021-0a48-4f42-a61f-c176cfdd7571",
      "name": "Post Error to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        4576,
        336
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('When Slack Message Received').item.json.channel }}"
        },
        "otherOptions": {
          "thread_ts": {
            "replyValues": {
              "thread_ts": "={{ $('When Slack Message Received').item.json.thread_ts }}"
            }
          },
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    }
  ],
  "connections": {
    "Gemini Model": {
      "ai_languageModel": [
        [
          {
            "node": "SQL Data Analyst Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "If Output Valid": {
      "main": [
        [
          {
            "node": "Post to Slack Channel",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Post Error to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Redis Chat Memory": {
      "ai_memory": [
        [
          {
            "node": "SQL Data Analyst Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Parse Table Schema": {
      "main": [
        [
          {
            "node": "SQL Data Analyst Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Primary SQL Query": {
      "ai_tool": [
        [
          {
            "node": "SQL Data Analyst Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Set Databricks Config": {
      "main": [
        [
          {
            "node": "Fetch Databricks Schema",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SQL Data Analyst Agent": {
      "main": [
        [
          {
            "node": "If Output Valid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Databricks Schema": {
      "main": [
        [
          {
            "node": "Parse Table Schema",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Slack Message Received": {
      "main": [
        [
          {
            "node": "Set Databricks Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}