{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "a4329c24-ccf8-4bcf-abab-a4a639a43f5f",
      "name": "Workflow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        1024
      ],
      "parameters": {
        "width": 420,
        "height": 752,
        "content": "## Extract order details from LINE messages and photos to Google Sheets with OpenAI\n\nAutomatically extract order information from text messages or handwritten memo photos sent via LINE, confirm with the user, and append to a Google Sheets tracking sheet.\n\n## How it works\n\n1. Receives text or image messages from LINE Messaging API\n2. Routes messages by type \u2014 text goes directly to the AI Agent, images are first downloaded via LINE API\n3. The AI Agent (GPT-4o) analyzes the input, extracts order details, and asks the user for confirmation\n4. Once approved, the order is appended as a new row in Google Sheets\n\n## Setup steps\n\n1. **LINE Messaging API**: Create a LINE channel and set the webhook URL to this workflow's trigger endpoint\n2. **OpenAI Credentials**: Set up your OpenAI API key in n8n Credentials\n3. **Google Sheets Credentials**: Set up Google Sheets OAuth2 in n8n Credentials\n4. **Configure Spreadsheet**: Open the \"Append Row to Google Sheets\" node and set your Spreadsheet ID and sheet name\n5. **Activate the workflow**"
      },
      "typeVersion": 1
    },
    {
      "id": "96f3e14a-a0c6-4b1c-9ba6-dca78f563ee3",
      "name": "Routing Section",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        1280
      ],
      "parameters": {
        "color": 7,
        "width": 628,
        "height": 328,
        "content": "### Message Routing\nReceives LINE messages and routes them by type: text messages go directly to the AI Agent, image messages are downloaded first."
      },
      "typeVersion": 1
    },
    {
      "id": "970e06ee-9789-4b66-85a1-e7ae755c03f9",
      "name": "Append Row to Google Sheets",
      "type": "n8n-nodes-base.googleSheetsTool",
      "position": [
        1616,
        1696
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "363db00b-9206-4c4d-a9dd-d30c9e4fec03",
      "name": "Reply via LINE",
      "type": "@aotoki/n8n-nodes-line-messaging.lineMessaging",
      "position": [
        1920,
        1472
      ],
      "parameters": {
        "messages": {
          "values": [
            {
              "text": "={{ $json.output }}"
            }
          ]
        },
        "replyToken": "={{ $('Line Messaging Trigger1').item.json.replyToken }}"
      },
      "typeVersion": 1
    },
    {
      "id": "01f5bc0d-8fc6-46f8-bba0-81d82db016b3",
      "name": "Download LINE Image",
      "type": "@aotoki/n8n-nodes-line-messaging.lineMessagingData",
      "position": [
        1056,
        1632
      ],
      "parameters": {
        "messageId": "={{ $json.message.id }}",
        "additionalOptions": {}
      },
      "typeVersion": 1
    },
    {
      "id": "e1e2030a-d11d-47a4-a94e-7ee0b015def2",
      "name": "Route by Message Type",
      "type": "n8n-nodes-base.switch",
      "position": [
        768,
        1408
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "text",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "a44d35d1-11c0-48b0-b311-f61331828552",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.message.type }}",
                    "rightValue": "text"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "image",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "6b241213-75b7-41d9-b936-6735d0cc4c91",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.message.type }}",
                    "rightValue": "image"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "43fec621-283d-4217-aead-96393036959c",
      "name": "AI Processing Section1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1200,
        1312
      ],
      "parameters": {
        "color": 7,
        "width": 646,
        "height": 524,
        "content": "### AI Processing & Data Entry\nGPT-4o analyzes text or images, extracts order details, confirms with the user via LINE, and appends approved orders to Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "0a48a493-a3c7-498b-aaef-9b373547869e",
      "name": "AI Agent - Order Extractor1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1424,
        1472
      ],
      "parameters": {
        "text": "={{ $json.message?.text ?? 'Please read the order information from the attached image' }}",
        "options": {
          "systemMessage": "You are a DVD order assistant. You extract order information from text messages or handwritten memo photos sent by users via chat.\n\n## Your Role\n\n1. Analyze text or images (photos of handwritten memos) sent by the user\n2. Extract the following fields:\n   - Game name (game_name) \u2014 name of the game to purchase\n   - Game date (game_date) \u2014 in YYYY-MM-DD format\n   - Customer name (customer_name)\n   - Contact (contact) \u2014 phone number or email address\n   - Delivery address (delivery_address)\n   - DVD quantity (dvd_quantity) \u2014 numeric value\n3. Present the extracted result to the user in this format:\n   \ud83d\udccb Extracted Details:\n   - Game: \u2026\n   - Date: \u2026\n   - Customer: \u2026\n   - Contact: \u2026\n   - Address: \u2026\n   - Quantity: \u2026\n4. Ask the user: \"Shall I register this order?\"\n5. If the user requests corrections, apply them and re-display\n6. Only when the user explicitly approves (e.g., \"Register\", \"OK\", \"Yes\"), pass the data to the Google Sheets tool in the following JSON format\n\n## Google Sheets Output Format (Strict)\n\nWhen calling the Google Sheets tool, pass only the following JSON. Do not include any text, explanations, or code block markers (```) outside the JSON.\n\n{\"game_name\": \"Game Name\", \"game_date\": \"YYYY-MM-DD\", \"customer_name\": \"Customer Name\", \"contact\": \"Contact\", \"delivery_address\": \"Address\", \"dvd_quantity\": \"Quantity\"}\n\n## Important Rules\n\n- Never call the Google Sheets tool without explicit user approval\n- If required fields (game name, customer name) are missing, ask the user before registering\n- If the image is unreadable, reply: \"The image is unclear. Could you resend it?\"\n- If the user says \"Cancel\" or \"Stop\", abort the registration\n- Respond in the same language as the user's message",
          "passthroughBinaryImages": true,
          "returnIntermediateSteps": false
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "009cab26-2625-473d-86a5-2d6a595a31ac",
      "name": "OpenAI GPT-4o1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1360,
        1696
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini",
          "cachedResultName": "gpt-4.1-mini"
        },
        "options": {
          "maxTokens": 4096,
          "temperature": 0.3
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e264f81c-352e-4440-8014-714e01e7a011",
      "name": "Simple Memory - Chat History1",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        1488,
        1696
      ],
      "parameters": {
        "sessionKey": "={{ $('Line Messaging Trigger1').item.json.source.userId }}",
        "sessionIdType": "customKey",
        "contextWindowLength": 10
      },
      "typeVersion": 1.3
    },
    {
      "id": "c4c3a990-5d0d-41ee-8b3c-3e01f3003394",
      "name": "Line Messaging Trigger1",
      "type": "@aotoki/n8n-nodes-line-messaging.lineMessagingTrigger",
      "position": [
        544,
        1408
      ],
      "parameters": {
        "events": [
          "message"
        ]
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "OpenAI GPT-4o1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent - Order Extractor1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Download LINE Image": {
      "main": [
        [
          {
            "node": "AI Agent - Order Extractor1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Message Type": {
      "main": [
        [
          {
            "node": "AI Agent - Order Extractor1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Download LINE Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Line Messaging Trigger1": {
      "main": [
        [
          {
            "node": "Route by Message Type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent - Order Extractor1": {
      "main": [
        [
          {
            "node": "Reply via LINE",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Row to Google Sheets": {
      "ai_tool": [
        [
          {
            "node": "AI Agent - Order Extractor1",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory - Chat History1": {
      "ai_memory": [
        [
          {
            "node": "AI Agent - Order Extractor1",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    }
  }
}