{
  "id": "yoejDyiyt2PqSumk",
  "name": "Support student questions via LINE with an AI Agent, Google Drive, and Slack",
  "tags": [],
  "nodes": [
    {
      "id": "ce706c6e-909b-4f87-a88c-6f17d38e00ad",
      "name": "LINE Receiver",
      "type": "n8n-nodes-base.webhook",
      "position": [
        208,
        368
      ],
      "parameters": {
        "path": "line-study-bot",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "756a1f04-9868-4079-88d2-745e54788b36",
      "name": "Acknowledge LINE",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        432,
        272
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\"status\":\"ok\"}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "e60e1ffb-0a15-4f25-99c1-52b0756211c9",
      "name": "Set Config",
      "type": "n8n-nodes-base.set",
      "position": [
        432,
        464
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-1",
              "name": "userId",
              "type": "string",
              "value": "={{ $json.body.events[0].source.userId }}"
            },
            {
              "id": "cfg-2",
              "name": "replyToken",
              "type": "string",
              "value": "={{ $json.body.events[0].replyToken }}"
            },
            {
              "id": "cfg-3",
              "name": "userMessage",
              "type": "string",
              "value": "={{ $json.body.events[0].message.text }}"
            },
            {
              "id": "cfg-4",
              "name": "sheetsId",
              "type": "string",
              "value": "YOUR_GOOGLE_SHEETS_ID"
            },
            {
              "id": "cfg-5",
              "name": "driveFolderId",
              "type": "string",
              "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID"
            },
            {
              "id": "cfg-6",
              "name": "slackWebhookUrl",
              "type": "string",
              "value": "YOUR_SLACK_WEBHOOK_URL"
            },
            {
              "id": "cfg-7",
              "name": "lineChannelToken",
              "type": "string",
              "value": "YOUR_LINE_CHANNEL_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "4199df73-4e88-455e-8e1e-abc361212d95",
      "name": "Load Chat History",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        656,
        464
      ],
      "parameters": {
        "operation": "readRows",
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.sheetsId }}"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "8c13e03f-5b6f-4bba-a593-fb5ac75f4b18",
      "name": "Aggregate History",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        880,
        464
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "28d5c2b6-dd4f-4e0d-8bcb-0e8eb25c7846",
      "name": "Study Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1104,
        464
      ],
      "parameters": {
        "text": "=Student question: {{ $('Set Config').item.json.userMessage }}\n\nPast conversation history (recent 10 exchanges):\n{{ JSON.stringify($json.data.slice(-10)) }}",
        "agent": "conversationalAgent",
        "options": {
          "systemMessage": "You are a helpful study support assistant for students (elementary to high school level). Your job is to answer academic questions clearly and encouragingly.\n\nYou have access to three tools:\n1. search_materials \u2014 Search the school's teaching materials in Google Drive. Always try this first.\n2. save_progress \u2014 Log the question and your answer to Google Sheets after you respond.\n3. escalate_to_teacher \u2014 Use this ONLY when you cannot find a confident answer in the materials. Send the student's question to the teacher via Slack.\n\nRules:\n- Always search materials before answering.\n- Keep explanations simple and age-appropriate.\n- If you escalate, tell the student: 'I've asked your teacher. They'll follow up with you soon!'\n- After every response (escalated or not), call save_progress to log the interaction.\n- Respond in Japanese."
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "4c3e33c9-6141-4db7-af0d-4d0c5eed2151",
      "name": "Gemini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1120,
        688
      ],
      "parameters": {
        "options": {
          "temperature": 0.3
        }
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a4e081ad-e55f-4585-afd4-cabc8b93e24a",
      "name": "Search Materials Tool",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "position": [
        1248,
        688
      ],
      "parameters": {
        "name": "search_materials",
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $workflow.id }}"
        },
        "description": "Search the teaching materials stored in Google Drive. Use this to find explanations, formulas, or examples related to the student's question. Input: a search query string.",
        "workflowInputs": {
          "schema": [
            {
              "id": "q",
              "type": "string",
              "required": true,
              "displayName": "query"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "a95f28e9-53d4-48d0-b49d-40e355eecf0d",
      "name": "Reply via LINE",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1456,
        464
      ],
      "parameters": {
        "url": "https://api.line.me/v2/bot/message/reply",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "replyToken",
              "value": "={{ $('Set Config').item.json.replyToken }}"
            },
            {
              "name": "messages",
              "value": "=[{\"type\":\"text\",\"text\":\"{{ $json.output }}\"}]"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Set Config').item.json.lineChannelToken }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "773d23c3-ce04-4696-91b8-2496d5d14bc7",
      "name": "Sticky Note \u2014 Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -384,
        -64
      ],
      "parameters": {
        "width": 456,
        "height": 620,
        "content": "### How it works\n\nStudents send any study question to your LINE bot. The AI Agent reads their conversation history from Google Sheets, searches your uploaded teaching materials in Google Drive, and replies with a clear explanation directly in LINE.\n\nIf the agent can't find a solid answer in the materials, it flags the question and pings the designated Slack channel so a teacher can step in.\n\nEvery question is logged to Google Sheets with the student's ID, subject, and whether it was resolved \u2014 giving you a clear picture of what topics need more attention.\n\n### Setup steps\n\n1. Add your LINE Messaging API credentials.\n2. Set the Google Sheets ID (conversation log) in the **Set Config** node.\n3. Set the Google Drive folder ID (teaching materials) in the **Set Config** node.\n4. Add your Slack webhook URL in the **Set Config** node.\n5. Activate and share the LINE bot link with students."
      },
      "typeVersion": 1
    },
    {
      "id": "441aa96e-3179-4581-acbf-557b6317d839",
      "name": "Sticky Note \u2014 Input",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        128,
        96
      ],
      "parameters": {
        "color": 7,
        "width": 392,
        "height": 152,
        "content": "## Receive student message\nCaptures incoming LINE messages and extracts the student's user ID and text."
      },
      "typeVersion": 1
    },
    {
      "id": "f8d5c455-f892-4867-97a7-e22c43454539",
      "name": "Sticky Note \u2014 Config",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        576
      ],
      "parameters": {
        "color": 7,
        "width": 312,
        "height": 136,
        "content": "## Set all config here\nUpdate Sheet ID, Drive folder ID, Slack webhook URL, and LINE token in this single node before activating."
      },
      "typeVersion": 1
    },
    {
      "id": "2e1b7b6d-6101-4ec6-8564-d2270cd7c181",
      "name": "Sticky Note \u2014 History",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        592,
        624
      ],
      "parameters": {
        "color": 7,
        "width": 292,
        "height": 184,
        "content": "## Load conversation history\nFetches the student's past Q&A from Google Sheets to give the agent context."
      },
      "typeVersion": 1
    },
    {
      "id": "5cb4a1af-4209-4576-b6b8-3218833a9665",
      "name": "Sticky Note \u2014 Agent",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 388,
        "height": 120,
        "content": "## AI Agent\nJudges intent, searches Drive materials, generates a reply, and decides whether to escalate to a teacher via Slack."
      },
      "typeVersion": 1
    },
    {
      "id": "0435acb6-aa21-4bfa-8819-8ba280e66f79",
      "name": "Sticky Note \u2014 Tools",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        816
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 132,
        "content": "## Agent tools\nDrive: search materials. Sheets: log the result. Slack: alert teacher if unresolved."
      },
      "typeVersion": 1
    },
    {
      "id": "a046b88a-c2d1-4d3e-bfba-5e9d9229dbcb",
      "name": "Sticky Note \u2014 Reply",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        624
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 132,
        "content": "## Reply to student\nSends the agent's answer back via the LINE Reply API."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "a6f72838-dff1-4ce6-a58d-bcd5f55cfde4",
  "connections": {
    "Set Config": {
      "main": [
        [
          {
            "node": "Load Chat History",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Study Agent": {
      "main": [
        [
          {
            "node": "Reply via LINE",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Model": {
      "ai_languageModel": [
        [
          {
            "node": "Study Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "LINE Receiver": {
      "main": [
        [
          {
            "node": "Acknowledge LINE",
            "type": "main",
            "index": 0
          },
          {
            "node": "Set Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate History": {
      "main": [
        [
          {
            "node": "Study Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Chat History": {
      "main": [
        [
          {
            "node": "Aggregate History",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Materials Tool": {
      "ai_tool": [
        [
          {
            "node": "Study Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  }
}