🔗 n8n: joining things together, without writing a program · n8n: เอาของมาต่อกัน โดยไม่ต้องเขียนโปรแกรม · n8n:不写程序,把东西接起来

Six steps and five workflows you can import. Fetch a live price. Decide whether it matters. Ask your own AI. Then let your laptop answer a web address. It all runs on your machine. · หกขั้น กับห้าเวิร์กโฟลว์ที่ import ได้เลย ดึงราคาสด ตัดสินว่ามันสำคัญไหม ถาม AI ของคุณเอง และจบด้วยแล็ปท็อปที่ตอบที่อยู่เว็บได้ ทุกอย่างรันบนเครื่องของคุณ · 六步,五个可以直接导入的工作流。抓实时价格、判断值不值得、问你自己的 AI,最后让你的笔记本去回答一个网址。全部跑在你自己机器上。

🇬🇧 English

n8n joins things together. Fetch a price, ask your AI, send an email, wait for a web address to be called.

You draw it instead of typing it. Boxes for the steps, lines for the order. The drawing is a file, and the file is on this page.

So each step here gives you a workflow to import, and shows what came out when we ran it. Six steps, on your own machine.

It is free, it runs on your laptop, and nothing leaves the room.

🇹🇭 ไทย

n8n เอาของมาต่อกัน ดึงราคา ถาม AI ของคุณ ส่งอีเมล หรือรอให้มีคนเรียกที่อยู่เว็บสักอัน

คุณวาดมันแทนที่จะพิมพ์ กล่องคือขั้นตอน เส้นคือลำดับ ภาพที่วาดคือไฟล์หนึ่งไฟล์ และไฟล์นั้นอยู่บนหน้านี้แล้ว

แต่ละขั้นจึงให้เวิร์กโฟลว์มา import และแสดงสิ่งที่ออกมาจริงตอนเรารัน หกขั้น บนเครื่องของคุณเอง

มันฟรี รันบนแล็ปท็อปของคุณ และไม่มีอะไรออกไปนอกห้อง

🇨🇳 中文

n8n 把东西接起来:抓一个价格、问你自己的 AI、发一封邮件,或者等着某个网址被人调用。

你是画出来的,不是打出来的。方块是步骤,线是顺序。这幅画就是一个文件,而那个文件就在这一页上。

所以每一步都给你一个可以导入的工作流,并且给你看我们跑它时真正出来的东西。六步,全在你自己机器上。

它免费,跑在你的笔记本上,什么都不出这个房间。

THE OFFICIAL WAY IS DOCKER NOW n8n prints this itself on startup. Running it outside a container is deprecated. Future versions will need the Docker image. The npm way below still works today. It is the quickest way to try it. If you decide to keep it, move to Docker. n8n พิมพ์เรื่องนี้ออกมาเองตอนเริ่มทำงาน การรันนอกคอนเทนเนอร์ถือว่าเลิกสนับสนุนแล้ว และเวอร์ชันต่อ ๆ ไปจะต้องใช้อิมเมจ Docker วิธี npm ข้างล่างยังใช้ได้อยู่ตอนนี้ และเป็นวิธีที่ลองได้เร็วที่สุด ถ้าคุณตัดสินใจจะใช้มันจริงจัง ให้ย้ายไป Docker 这是 n8n 自己启动时打印出来的:在容器外面运行已经不推荐了,以后的版本会要求用 Docker 镜像。下面的 npm 方式今天还能用,也是最快能试一试的方式。如果你决定留着它,就搬到 Docker 上去。

🔧 Tutorial 1 — Run it, and read one · บทที่ 1 — รันมัน แล้วอ่านสักอัน · 教程 1 —— 跑起来,再读一个

🇬🇧 English

Start it once, then open the editor in a browser. After that, a workflow is just a file you can import.

🇹🇭 ไทย

เริ่มมันครั้งหนึ่ง แล้วเปิดหน้าแก้ไขในเบราว์เซอร์ หลังจากนั้น เวิร์กโฟลว์ก็เป็นแค่ไฟล์ที่คุณ import เข้าไปได้

🇨🇳 中文

启动一次,然后在浏览器里打开编辑器。之后,工作流就只是一个你可以导入的文件。

1 Start it · เริ่มมันขึ้นมา · 把它启动起来

🇬🇧 English

Two ways. Docker is the one n8n wants you to use. npm is quicker if you only want to look.

Either way it opens at localhost:5678. The first screen asks you to make an account. It stays on your machine.

🇹🇭 ไทย

มีสองทาง Docker คือทางที่ n8n อยากให้ใช้ ส่วน npm เร็วกว่า ถ้าคุณแค่อยากลองดูเฉย ๆ

ไม่ว่าทางไหน มันจะเปิดที่ localhost:5678 หน้าจอแรกจะให้สร้างบัญชี ซึ่งอยู่บนเครื่องคุณเท่านั้น

🇨🇳 中文

两种方式。Docker 是 n8n 希望你用的那种,npm 更快,适合只想看看的人。

不管哪种,它都开在 localhost:5678。第一屏让你建一个账号,那个账号只留在你自己机器上。

⌨️ TERMINAL · the way n8n recommends

docker run -it --rm -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  docker.n8n.io/n8nio/n8n

⌨️ TERMINAL · the quick way, deprecated but working

npm install n8n
npx n8n start
GIVE IT A SHORT FOLDER ON WINDOWS n8n installs 2,279 packages, and they nest deeply. Windows still stops at 260 characters for a path. Unless you turned that off. Install it at something like C:\n8nlab. Not inside a long folder. The install fails part way through. n8n ติดตั้งแพ็กเกจ 2,279 ตัว และซ้อนกันลึกมาก Windows ยังจำกัดเส้นทางไฟล์ไว้ที่ 260 ตัวอักษร ถ้าคุณไม่ได้ปิดข้อจำกัดนั้น ให้ติดตั้งไว้ที่สั้น ๆ อย่าง C:\n8nlab ไม่ใช่ในโฟลเดอร์ชื่อยาว ๆ ไม่อย่างนั้นการติดตั้งจะล้มกลางคัน n8n 会装 2,279 个包,而且嵌套很深。除非你关掉了那个限制,Windows 的路径上限仍然是 260 个字符。把它装在像 C:\n8nlab 这样短的地方,别放在名字很长的文件夹里,否则装到一半就会失败。
YOUR TURN
  1. Pick one of the two commands and run it.
  2. Open http://localhost:5678 and make the account.
  3. Check: you see an empty canvas with a plus button.
  4. Click about. Nothing you do here can break anything yet.
  1. เลือกหนึ่งในสองคำสั่งแล้วรัน
  2. เปิด http://localhost:5678 แล้วสร้างบัญชี
  3. ตรวจ: ต้องเห็นผืนผ้าใบว่าง ๆ กับปุ่มเครื่องหมายบวก
  4. ลองคลิกไปทั่ว ๆ ตอนนี้ยังทำอะไรพังไม่ได้
  1. 从两条命令里挑一条跑。
  2. 打开 http://localhost:5678,把账号建好。
  3. 检查:你看到一块空白画布和一个加号按钮。
  4. 随便点点。现在你还弄不坏任何东西。

2 A workflow is boxes and lines · เวิร์กโฟลว์คือกล่องกับเส้น · 工作流就是方块和线

🇬🇧 English

Here is the smallest one. Two boxes: something starts it, and something makes a message.

Read the file and you can see the whole idea. nodes is the boxes. connections is the lines. That is all a workflow is.

Import it from the editor, or from the terminal.

🇹🇭 ไทย

นี่คืออันที่เล็กที่สุด สองกล่อง อันหนึ่งเริ่มงาน อีกอันสร้างข้อความ

อ่านไฟล์แล้วจะเห็นแนวคิดทั้งหมด nodes คือกล่อง connections คือเส้น เวิร์กโฟลว์มีแค่นี้เอง

import มันจากหน้าแก้ไข หรือจากเทอร์มินัลก็ได้

🇨🇳 中文

这是最小的一个。两个方块:一个负责启动,一个负责做出一条消息。

把文件读一遍,整个想法就都在那儿了。nodes 是方块,connections 是线。工作流就只是这样。

可以在编辑器里导入,也可以在终端里导入。

📄 NEW FILE · hello.json

{
  "name": "Hello",
  "nodes": [
    {
      "parameters": {},
      "id": "11111111-1111-4111-8111-111111111111",
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "greeting",
              "value": "Hello from Chiang Mai",
              "type": "string"
            },
            {
              "id": "a2",
              "name": "bags",
              "value": 3,
              "type": "number"
            }
          ]
        },
        "options": {}
      },
      "id": "22222222-2222-4222-8222-222222222222",
      "name": "Make a message",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        0
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Make a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "id": "hello001",
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}
LineWhat it does · ทำอะไร · 做什么
"type": "n8n-nodes-base.manualTrigger",Every workflow needs a start. This one starts when you press the button.ทุกเวิร์กโฟลว์ต้องมีจุดเริ่ม อันนี้เริ่มเมื่อคุณกดปุ่ม每个工作流都要有个开头。这个是你按按钮时开始。
"type": "n8n-nodes-base.set",The Edit Fields box. It makes data out of nothing, which is handy for trying things.กล่อง Edit Fields มันสร้างข้อมูลขึ้นมาจากอากาศ ซึ่งสะดวกเวลาอยากลองอะไรEdit Fields 方块。它凭空造出数据,试东西的时候很好用。
"connections": {The lines. Start points at Make a message. That is the order they run.ส่วนของเส้น Start ชี้ไปที่ Make a message นั่นคือลำดับการทำงาน线在这里。Start 指向 Make a message,运行顺序就是这么定的。

⌨️ TERMINAL · import it, then run it

npx n8n import:workflow --input=hello.json
npx n8n execute --id=hello001

🖥️ WHAT CAME OUT · a real run

status   : success

--- node: Start   (1 item(s), 1 ms)
{}

--- node: Make a message   (1 item(s), 3 ms)
{
  "greeting": "Hello from Chiang Mai",
  "bags": 3
}
THE WORKFLOW NEEDS AN id OF ITS OWN Import a file with no "id" at the top and it fails. The error is NOT NULL constraint failed: workflow_entity.id. Every file on this page has one. Also, execute --file was removed. You import first, then run it by its id. ถ้า import ไฟล์ที่ไม่มี "id" อยู่ข้างบน มันจะล้มด้วยข้อความ NOT NULL constraint failed: workflow_entity.id ทุกไฟล์บนหน้านี้มี id แล้ว และสังเกตว่า execute --file ถูกถอดออกไปแล้ว ต้อง import ก่อน แล้วค่อยรันด้วย id ของมัน 导入一个顶上没有 "id" 的文件,它会以 NOT NULL constraint failed: workflow_entity.id 失败。这一页上每个文件都有 id。另外注意 execute --file 已经被拿掉了:先导入,再用它的 id 去运行。
YOUR TURN
  1. Save the file, then import and run it.
  2. Check: status : success, and your greeting.
  3. Open it in the editor. The same file, drawn as two boxes.
  4. Change bags to 10 in the editor. Look at the file again.
  1. เซฟไฟล์ แล้ว import และรัน
  2. ตรวจ: ต้องขึ้น status : success และคำทักทายของคุณ
  3. เปิดมันในหน้าแก้ไข ไฟล์เดียวกัน แต่วาดออกมาเป็นสองกล่อง
  4. แก้ bags เป็น 10 ในหน้าแก้ไข แล้วกลับไปดูไฟล์อีกที
  1. 保存文件,然后导入并运行。
  2. 检查:status : success,还有你那句问候。
  3. 在编辑器里打开它。同一个文件,画成了两个方块。
  4. 在编辑器里把 bags 改成 10,再回去看那个文件。

🌐 Tutorial 2 — Fetch something real · บทที่ 2 — ไปเอาของจริงมา · 教程 2 —— 去拿点真东西回来

🇬🇧 English

Two boxes are enough to reach the whole internet. One asks, one tidies up what came back.

Then a third decides whether any of it was worth telling you about.

🇹🇭 ไทย

สองกล่องก็พอจะเอื้อมไปถึงทั้งอินเทอร์เน็ตแล้ว อันหนึ่งไปถาม อีกอันจัดระเบียบสิ่งที่ได้กลับมา

แล้วกล่องที่สามจะตัดสินว่ามันคุ้มจะบอกคุณหรือเปล่า

🇨🇳 中文

两个方块就够够到整个互联网了:一个去问,一个把拿回来的东西收拾干净。

然后第三个来决定,这些值不值得告诉你。

3 Ask the internet, then tidy the answer · ถามอินเทอร์เน็ต แล้วจัดระเบียบคำตอบ · 问一下互联网,再把答案收拾干净

🇬🇧 English

The HTTP Request box fetches an address. Here it is the bitcoin price from Bitkub, the same one used on the bitcoin page.

What comes back has nine fields and every number is text. The Code box keeps four of them and makes them numbers.

🇹🇭 ไทย

กล่อง HTTP Request ไปดึงที่อยู่เว็บมา ตรงนี้คือราคาบิตคอยน์จาก Bitkub อันเดียวกับที่ใช้ในหน้าบิตคอยน์

ของที่ได้กลับมามีเก้าฟิลด์ และตัวเลขทุกตัวเป็นข้อความ กล่อง Code เก็บไว้สี่อัน แล้วเปลี่ยนให้เป็นตัวเลขจริง

🇨🇳 中文

HTTP Request 方块去抓一个网址。这里抓的是 Bitkub 的比特币价格,和比特币那一页用的是同一个。

回来的东西有九个字段,而且每个数字都是文字。Code 方块留下四个,并把它们变成真正的数字。

📄 NEW FILE · price.json

{
  "name": "Bitcoin price",
  "nodes": [
    {
      "parameters": {},
      "id": "11111111-1111-4111-8111-111111111111",
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "url": "https://api.bitkub.com/api/v3/market/ticker?sym=BTC_THB",
        "options": {}
      },
      "id": "22222222-2222-4222-8222-222222222222",
      "name": "Ask Bitkub",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Bitkub sends every number as text, so turn them into numbers.\nconst coin = items[0].json;\nconst buy = Number(coin.lowest_ask);\nconst sell = Number(coin.highest_bid);\n\nreturn [{ json: {\n  symbol: coin.symbol,\n  buy,\n  sell,\n  gap: Math.round((buy - sell) * 100) / 100,\n  moved: Number(coin.percent_change),\n} }];"
      },
      "id": "33333333-3333-4333-8333-333333333333",
      "name": "Tidy the numbers",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        0
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Ask Bitkub",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ask Bitkub": {
      "main": [
        [
          {
            "node": "Tidy the numbers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "id": "price001",
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}
LineWhat it does · ทำอะไร · 做什么
"type": "n8n-nodes-base.httpRequest",The box that fetches an address. No key here, because Bitkub prices are public.กล่องที่ไปดึงที่อยู่เว็บ ตรงนี้ไม่ต้องใช้คีย์ เพราะราคาของ Bitkub เปิดสาธารณะ去抓网址的那个方块。这里不用密钥,因为 Bitkub 的价格是公开的。
const coin = items[0].json;items is what the box before handed over. Always a list.items คือของที่กล่องก่อนหน้าส่งมา เป็นลิสต์เสมอitems 是上一个方块递过来的东西,永远是个列表。
return [{ json: {Hand on a list too. That shape is the rule between every pair of boxes.ส่งต่อเป็นลิสต์เหมือนกัน รูปแบบนี้คือกติการะหว่างทุกคู่กล่อง交出去的也要是列表。这个形状是每两个方块之间的规矩。

🖥️ WHAT CAME OUT · a real run, live prices

--- node: Ask Bitkub   (1 item(s), 251 ms)
{ "symbol": "BTC_THB", "highest_bid": "2841678.89",
  "lowest_ask": "2843241.72", "percent_change": "1.6", ... }

--- node: Tidy the numbers   (1 item(s), 599 ms)
{
  "symbol": "BTC_THB",
  "buy": 2843241.72,
  "sell": 2841678.89,
  "gap": 1562.83,
  "moved": 1.6
}
YOUR TURN
  1. Import and run it. The numbers will differ from ours.
  2. Check: buy is a number, with no quote marks.
  3. Change the address to ETH_THB and run it again.
  4. Take out the Number() calls. What do the values look like?
  1. import แล้วรัน ตัวเลขจะไม่เหมือนของเรา
  2. ตรวจ: buy ต้องเป็นตัวเลข ไม่มีเครื่องหมายคำพูด
  3. เปลี่ยนที่อยู่เป็น ETH_THB แล้วรันใหม่
  4. ลองเอา Number() ออก ค่าที่ได้หน้าตาเป็นอย่างไร
  1. 导入并运行。数字会和我们的不一样。
  2. 检查:buy 是数字,没有引号。
  3. 把网址改成 ETH_THB,再跑一次。
  4. 把 Number() 去掉,看看值变成什么样。

4 Only tell me when it matters · บอกฉันเฉพาะตอนที่มันสำคัญ · 只在值得的时候告诉我

🇬🇧 English

An IF box has two ways out. True leaves the top, false leaves the bottom, and you draw a different line from each.

This is what turns a fetch into an alert. Without it you get told everything, which is the same as being told nothing.

🇹🇭 ไทย

กล่อง IF มีทางออกสองทาง ถ้าจริงออกทางบน ถ้าเท็จออกทางล่าง แล้วคุณลากเส้นคนละเส้นจากแต่ละทาง

นี่คือสิ่งที่เปลี่ยนการไปดึงข้อมูล ให้กลายเป็นการแจ้งเตือน ถ้าไม่มีมัน คุณจะถูกบอกทุกเรื่อง ซึ่งก็เท่ากับไม่ถูกบอกอะไรเลย

🇨🇳 中文

IF 方块有两个出口。真从上面走,假从下面走,你从每个出口拉一条不同的线。

就是它把"抓一下数据"变成"提醒"。没有它,你什么都会被告知,那等于什么都没被告知。

📄 NEW FILE · alert.json

{
  "name": "Only tell me when it matters",
  "nodes": [
    {
      "parameters": {},
      "id": "11111111-1111-4111-8111-111111111111",
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "url": "https://api.bitkub.com/api/v3/market/ticker?sym=BTC_THB",
        "options": {}
      },
      "id": "22222222-2222-4222-8222-222222222222",
      "name": "Ask Bitkub",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const coin = items[0].json;\nreturn [{ json: { buy: Number(coin.lowest_ask) } }];"
      },
      "id": "33333333-3333-4333-8333-333333333333",
      "name": "Take the price",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $json.buy }}",
              "rightValue": 2000000,
              "operator": {
                "type": "number",
                "operation": "gt"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "44444444-4444-4444-8444-444444444444",
      "name": "Above my line?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "y1",
              "name": "say",
              "value": "=Bitcoin is {{ $json.buy }} baht. Above the line.",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "55555555-5555-4555-8555-555555555555",
      "name": "Tell me",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        880,
        -100
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "n1",
              "name": "say",
              "value": "Nothing worth waking you for.",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "66666666-6666-4666-8666-666666666666",
      "name": "Stay quiet",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        880,
        100
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Ask Bitkub",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ask Bitkub": {
      "main": [
        [
          {
            "node": "Take the price",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Take the price": {
      "main": [
        [
          {
            "node": "Above my line?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Above my line?": {
      "main": [
        [
          {
            "node": "Tell me",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Stay quiet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "id": "alert001",
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}
LineWhat it does · ทำอะไร · 做什么
"operator": { "type": "number", "operation": "gt" }Greater than, and it means the number kind of greater than.มากกว่า และเป็นการมากกว่าแบบตัวเลข大于,而且是数字意义上的大于。
"leftValue": "={{ $json.buy }}",The = at the front makes it an expression, not the text itself.เครื่องหมาย = ข้างหน้าทำให้มันเป็นนิพจน์ ไม่ใช่ข้อความตรง ๆ前面那个 = 让它变成表达式,而不是这串字本身。
"main": [ [{ "node": "Tell me", ... }], [{ "node": "Stay quiet", ... }]Two lists. The first is the true way out. The second is the false one.สองลิสต์ อันแรกคือทางออกเมื่อจริง อันที่สองคือเมื่อเท็จ两个列表。第一个是真的出口,第二个是假的。

🖥️ WHAT CAME OUT · the price really was above the line

--- node: Above my line?   (1 item(s), 20 ms)
{ "buy": 2843241.72 }

--- node: Tell me   (1 item(s), 6 ms)
{ "say": "Bitcoin is 2843241.72 baht. Above the line." }
NOTHING CAME OUT OF THE OTHER SIDE Look again at the run. Stay quiet is not there at all. An IF does not run both ways and pick one. It sends the item down one line. The boxes on the other line never run. That is why an empty branch costs you nothing. ลองดูผลการรันอีกครั้ง Stay quiet ไม่โผล่มาเลย IF ไม่ได้รันทั้งสองทางแล้วค่อยเลือก มันส่งข้อมูลไปทางเดียว และกล่องบนอีกทางก็ไม่ได้ทำงานเลย นั่นคือเหตุผลที่กิ่งที่ว่างอยู่ไม่กินอะไรของคุณเลย 再看一眼那次运行,Stay quiet 根本没出现。IF 不是两边都跑一遍再挑一个。它把数据送进其中一条线,另一条线上的方块压根不会运行。所以空着的那一支不花你任何东西。
YOUR TURN
  1. Import and run it. Which way did yours go?
  2. Change rightValue to a number above today's price.
  3. Check: now Stay quiet runs, and the other does not.
  4. Add a third condition. Watch combinator in the file.
  1. import แล้วรัน ของคุณไปทางไหน
  2. เปลี่ยน rightValue เป็นตัวเลขที่สูงกว่าราคาวันนี้
  3. ตรวจ: คราวนี้ Stay quiet จะทำงาน ส่วนอีกอันไม่ทำ
  4. ลองเพิ่มเงื่อนไขที่สาม แล้วสังเกตคำว่า combinator ในไฟล์
  1. 导入并运行。你的走了哪一边?
  2. 把 rightValue 改成比今天价格还高的数。
  3. 检查:这次轮到 Stay quiet 运行,另一个不跑。
  4. 加第三个条件,注意文件里的 combinator。

🤖 Tutorial 3 — Your own AI, in a workflow · บทที่ 3 — AI ของคุณเอง ในเวิร์กโฟลว์ · 教程 3 —— 把你自己的 AI 放进工作流

🇬🇧 English

Ollama answers on an address, and n8n can call an address. That is the whole connection.

No key, no account, no bill. The question and the answer stay on your laptop.

🇹🇭 ไทย

Ollama ตอบผ่านที่อยู่เว็บ และ n8n เรียกที่อยู่เว็บได้ การเชื่อมต่อมีแค่นี้

ไม่มีคีย์ ไม่มีบัญชี ไม่มีบิล คำถามและคำตอบอยู่บนแล็ปท็อปของคุณ

🇨🇳 中文

Ollama 在一个网址上回答,而 n8n 会调用网址。连接就这么简单。

不用密钥,不用账户,不用付钱。问题和答案都留在你的笔记本上。

5 Ask Ollama from a box · ถาม Ollama จากในกล่อง · 从一个方块里问 Ollama

🇬🇧 English

The same HTTP Request box as before, pointed at your own machine and sending a POST instead of a GET.

Ollama answers with a lot you did not ask for. The Code box takes the one line that matters.

🇹🇭 ไทย

กล่อง HTTP Request อันเดิม แต่ชี้มาที่เครื่องของคุณเอง และส่งแบบ POST แทน GET

Ollama ตอบกลับมาพร้อมของที่คุณไม่ได้ขอเยอะแยะ กล่อง Code หยิบเอาบรรทัดเดียวที่สำคัญ

🇨🇳 中文

还是之前那个 HTTP Request 方块,只是指向你自己的机器,而且发的是 POST,不是 GET。

Ollama 会回来一堆你没要的东西。Code 方块只把那一行有用的拿走。

📄 NEW FILE · ask.json

{
  "name": "Ask your own AI",
  "nodes": [
    {
      "parameters": {},
      "id": "11111111-1111-4111-8111-111111111111",
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://localhost:11434/api/chat",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "{\n  \"model\": \"llama3.2\",\n  \"stream\": false,\n  \"messages\": [\n    { \"role\": \"user\", \"content\": \"Name one street food in Chiang Mai. Six words or fewer.\" }\n  ]\n}",
        "options": {}
      },
      "id": "22222222-2222-4222-8222-222222222222",
      "name": "Ask Ollama",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Ollama buries the answer. Dig it out and throw the rest away.\nconst reply = items[0].json;\nreturn [{ json: {\n  answer: reply.message.content.trim(),\n  model: reply.model,\n} }];"
      },
      "id": "33333333-3333-4333-8333-333333333333",
      "name": "Take the answer",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        0
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Ask Ollama",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ask Ollama": {
      "main": [
        [
          {
            "node": "Take the answer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "id": "ask001",
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}
LineWhat it does · ทำอะไร · 做什么
"method": "POST",A question has a body, so it cannot be a GET.คำถามมีเนื้อหาส่งไปด้วย จึงเป็น GET ไม่ได้提问是带正文的,所以不能用 GET。
"url": "http://localhost:11434/api/chat",Your own machine. Change it to a friend's address to borrow their model.เครื่องของคุณเอง เปลี่ยนเป็นที่อยู่ของเพื่อนก็ยืมโมเดลเขาใช้ได้你自己的机器。改成朋友的地址,就能借用他的模型。
"stream": falseAsk for the whole answer at once. A workflow has nothing to stream into.ขอคำตอบทั้งก้อนทีเดียว เพราะเวิร์กโฟลว์ไม่มีที่ให้ทยอยส่งเข้าไป一次要完整答案。工作流没有地方可以一点一点接。
reply.message.content.trim()The answer is buried this deep. Everything else is timings.คำตอบฝังอยู่ลึกขนาดนี้ ส่วนที่เหลือคือตัวเลขเวลา答案埋在这么深的地方。其余的都是耗时数据。

🖥️ WHAT CAME OUT · a real run, on llama3.2

--- node: Ask Ollama   (1 item(s), 7552 ms)
{ "model": "llama3.2",
  "message": { "role": "assistant", "content": "Sai Oua (Chiang Mai sausage)" },
  "done": true, "eval_count": 11, ... }

--- node: Take the answer   (1 item(s), 83 ms)
{
  "answer": "Sai Oua (Chiang Mai sausage)",
  "model": "llama3.2"
}
SEVEN SECONDS IS NORMAL, AND THAT IS FINE HERE Most of those 7,552 ms was loading the model into memory. That was the first time. Run it again and it is much quicker. A workflow is not a chat window. Nobody sits there watching it wait. เวลา 7,552 มิลลิวินาทีนั้น ส่วนใหญ่หมดไปกับการโหลดโมเดลเข้าหน่วยความจำครั้งแรก รันอีกครั้งจะเร็วขึ้นมาก เวิร์กโฟลว์ไม่ใช่หน้าต่างแชต จึงไม่มีใครนั่งจ้องรออยู่ 那 7,552 毫秒里,大部分花在第一次把模型装进内存。再跑一次就快多了。工作流不是聊天窗口,没有人坐在那里盯着它等。
YOUR TURN
  1. Make sure Ollama is running, then import and run it.
  2. Check: answer is one short sentence.
  3. Run it a second time. Look at how much faster it is.
  4. Join this to step 3: ask the model about the price it fetched.
  1. ตรวจว่า Ollama รันอยู่ แล้ว import และรัน
  2. ตรวจ: answer ต้องเป็นประโยคสั้น ๆ หนึ่งประโยค
  3. รันอีกครั้ง แล้วดูว่าเร็วขึ้นแค่ไหน
  4. ลองต่ออันนี้เข้ากับขั้นที่ 3 ให้โมเดลพูดถึงราคาที่เพิ่งดึงมา
  1. 确认 Ollama 在跑,然后导入并运行。
  2. 检查:answer 是一句短句。
  3. 再跑第二次,看看快了多少。
  4. 把它和第 3 步接起来:让模型聊聊它刚抓到的价格。

📡 Tutorial 4 — Let it answer the world · บทที่ 4 — ให้มันตอบโลกภายนอก · 教程 4 —— 让它去回答外面的世界

🇬🇧 English

So far you pressed a button. Now something else presses it.

A webhook gives the workflow an address. Anything that can open a web address can now set your workflow running.

🇹🇭 ไทย

ที่ผ่านมาคุณเป็นคนกดปุ่ม คราวนี้ให้สิ่งอื่นเป็นคนกด

เว็บฮุกให้ที่อยู่เว็บกับเวิร์กโฟลว์ อะไรก็ตามที่เปิดที่อยู่เว็บได้ ก็สั่งให้เวิร์กโฟลว์ของคุณทำงานได้แล้ว

🇨🇳 中文

到现在都是你按按钮。现在让别的东西来按。

Webhook 给工作流一个网址。任何能打开网址的东西,现在都能让你的工作流跑起来。

6 Your laptop answers a web address · แล็ปท็อปของคุณตอบที่อยู่เว็บ · 你的笔记本开始回答一个网址

🇬🇧 English

Swap the manual trigger for a webhook and the workflow stops waiting for you. It waits for a request instead.

This one prices a bag of coffee in satoshis, using today's rate. The caller gets the answer back, there and then.

A webhook only listens while n8n is running and the workflow is active. That is two different switches.

🇹🇭 ไทย

เปลี่ยนตัวเริ่มแบบกดปุ่มเป็นเว็บฮุก แล้วเวิร์กโฟลว์ก็เลิกรอคุณ มันไปรอคำขอแทน

อันนี้คิดราคากาแฟหนึ่งถุงเป็นซาโตชิ โดยใช้อัตราของวันนี้ คนที่เรียกมาจะได้คำตอบกลับไปทันทีตรงนั้น

เว็บฮุกจะฟังก็ต่อเมื่อ n8n รันอยู่ และเวิร์กโฟลว์ถูกเปิดใช้งาน นั่นคือสวิตช์สองตัวคนละตัวกัน

🇨🇳 中文

把手动触发换成 webhook,工作流就不再等你了,它改成等一个请求。

这个工作流用今天的汇率,把一包咖啡算成多少聪。调用它的人当场就拿到答案。

只有在 n8n 运行着、而且工作流被启用时,webhook 才在听。那是两个不同的开关。

📄 NEW FILE · hook.json

{
  "id": "hook001",
  "name": "Answer a web address",
  "active": false,
  "settings": { "executionOrder": "v1" },
  "nodes": [
    {
      "parameters": {
        "path": "coffee",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "11111111-1111-4111-8111-111111111111",
      "name": "When a request arrives",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [0, 0],
      "webhookId": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee"
    },
    {
      "parameters": {
        "url": "https://api.bitkub.com/api/v3/market/ticker?sym=BTC_THB",
        "options": {}
      },
      "id": "22222222-2222-4222-8222-222222222222",
      "name": "Ask Bitkub",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [220, 0]
    },
    {
      "parameters": {
        "jsCode": "// Whoever called the address gets exactly this back.\nconst coin = items[0].json;\nconst baht = Number(coin.last);\nreturn [{ json: {\n  shop: 'Doi Suthep Coffee',\n  bag_price_thb: 180,\n  bitcoin_thb: baht,\n  bag_in_satoshis: Math.round(180 / baht * 100000000),\n} }];"
      },
      "id": "33333333-3333-4333-8333-333333333333",
      "name": "Work out the price",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [440, 0]
    }
  ],
  "connections": {
    "When a request arrives": {
      "main": [[{ "node": "Ask Bitkub", "type": "main", "index": 0 }]]
    },
    "Ask Bitkub": {
      "main": [[{ "node": "Work out the price", "type": "main", "index": 0 }]]
    }
  }
}
LineWhat it does · ทำอะไร · 做什么
"type": "n8n-nodes-base.webhook",The start box is a listener now. Nobody presses anything.กล่องเริ่มกลายเป็นตัวคอยฟัง ไม่มีใครต้องกดอะไร起点方块现在是个监听器。没有人需要按什么。
"path": "coffee",This word becomes the address: /webhook/coffee.คำนี้จะกลายเป็นที่อยู่ /webhook/coffee这个词就变成网址:/webhook/coffee。
"responseMode": "lastNode",Send whatever the last box made back to whoever called.ส่งสิ่งที่กล่องสุดท้ายสร้างไว้ กลับไปให้คนที่เรียกมา把最后一个方块做出来的东西,回给调用的人。

⌨️ TERMINAL · switch it on, then call it

npx n8n import:workflow --input=hook.json
npx n8n update:workflow --id=hook001 --active=true
npx n8n start

curl http://localhost:5678/webhook/coffee

🖥️ WHAT CAME BACK · a real call

{"shop":"Doi Suthep Coffee","bag_price_thb":180,"bitcoin_thb":2843241.72,"bag_in_satoshis":6331}
ACTIVATE IT BEFORE YOU START n8n n8n reads which workflows are active when it starts. Switch one on while it is running and it tells you so. It says: changes will not take effect if n8n is running. Activate first, then start. Or activate in the editor, which handles it for you. n8n อ่านว่าเวิร์กโฟลว์ไหนเปิดใช้งานอยู่ตอนที่มันเริ่มทำงาน ถ้าไปเปิดสวิตช์ระหว่างที่มันรันอยู่ มันจะบอกคุณเองว่า changes will not take effect if n8n is running ให้เปิดใช้งานก่อน แล้วค่อยสตาร์ต หรือจะเปิดในหน้าแก้ไขก็ได้ มันจัดการให้เอง n8n 是在启动的时候读取哪些工作流是启用的。在它运行中去打开开关,它会自己告诉你:changes will not take effect if n8n is running。先启用,再启动。或者在编辑器里启用,它会替你处理好。
AN ADDRESS WITH NO LOCK ON IT This webhook asks nobody who they are. On your own laptop that is fine. The moment you put it on the internet, that changes. Anyone who learns the address can run your workflow. n8n has header auth for that, and you should use it. เว็บฮุกนี้ไม่ถามว่าใครเป็นใครเลย บนแล็ปท็อปของคุณเองก็ไม่เป็นไร แต่วินาทีที่คุณเอามันขึ้นอินเทอร์เน็ต ใครก็ตามที่รู้ที่อยู่ จะสั่งให้เวิร์กโฟลว์ของคุณทำงานกี่ครั้งก็ได้ n8n มีการยืนยันตัวตนผ่านเฮดเดอร์ไว้ให้ และคุณควรใช้มัน 这个 webhook 完全不问你是谁。在自己笔记本上没关系。但只要你把它放上互联网,任何知道地址的人都能随便让你的工作流跑。n8n 有基于请求头的验证,你应该用上。
YOUR TURN
  1. Import it, activate it, then start n8n.
  2. Open http://localhost:5678/webhook/coffee in a browser.
  3. Check: you get JSON back, with today's rate in it.
  4. Change the bag price to 250 and call it again.
  1. import แล้วเปิดใช้งาน จากนั้นค่อยสตาร์ต n8n
  2. เปิด http://localhost:5678/webhook/coffee ในเบราว์เซอร์
  3. ตรวจ: ต้องได้ JSON กลับมา พร้อมอัตราของวันนี้
  4. เปลี่ยนราคาถุงเป็น 250 แล้วเรียกอีกครั้ง
  1. 导入它,启用它,然后启动 n8n。
  2. 在浏览器里打开 http://localhost:5678/webhook/coffee。
  3. 检查:你拿到一段 JSON,里面是今天的汇率。
  4. 把每包价格改成 250,再调用一次。

🇬🇧 English

Six steps, and five files you can import into any n8n.

What to take away is the shape. Boxes hand a list of items to the next box, and that is the only rule there is.

Everything else is which box, and n8n ships hundreds of them. You have used four: a trigger, a fetch, a decision, and some code.

🇹🇭 ไทย

หกขั้น และห้าไฟล์ที่ import เข้า n8n ตัวไหนก็ได้

สิ่งที่ควรจำคือรูปร่างของมัน กล่องส่งลิสต์ของรายการไปให้กล่องถัดไป และนั่นคือกฎข้อเดียวที่มี

ที่เหลือคือจะใช้กล่องไหน ซึ่ง n8n มีมาให้เป็นร้อย คุณเพิ่งใช้ไปสี่แบบ ตัวเริ่มงาน ตัวไปดึงข้อมูล ตัวตัดสินใจ และโค้ด

🇨🇳 中文

六步,五个可以导入任何一个 n8n 的文件。

该记住的是那个形状:方块把一个项目列表交给下一个方块,全部规矩就这一条。

剩下的只是用哪个方块,而 n8n 自带几百个。你已经用过四种:触发、抓取、判断,和一点代码。

('You want', 'คุณอยากได้', '你想要')('Look up', 'ไปหาคำว่า', '去查')
It to run every morningให้มันทำงานทุกเช้า让它每天早上跑Schedule Trigger
Send the result as emailส่งผลลัพธ์เป็นอีเมล把结果用邮件发出去Send Email / Gmail
Do it once per rowทำทีละแถว每一行做一次Split In Batches
Keep a password safelyเก็บรหัสผ่านให้ปลอดภัย安全地存一个密码Credentials, not a Code boxCredentials ไม่ใช่กล่อง Code用 Credentials,不要写在 Code 方块里
An agent that picks toolsเอเจนต์ที่เลือกเครื่องมือเอง会自己挑工具的智能体AI Agent + Ollama Chat Model

Fifteen lines, your own address, and an app password. That is the whole trick. · สิบห้าบรรทัด อีเมลของคุณเอง และ app password หนึ่งอัน เคล็ดลับมีแค่นี้ · 十五行代码、你自己的邮箱地址,加一个应用专用密码。诀窍就这些。

All five workflows on this page were imported and run on 22 September 2026, on n8n 2.40.5 and Node 24.15.0. Every output shown is copied from those runs: the Bitkub prices were live, llama3.2 really answered Sai Oua, and the webhook really returned 6,331 satoshis for a 180 baht bag. The install needed a short folder to finish at all, and the two removed CLI behaviours in the warnings - a workflow needing its own id, and execute --file being gone - are both errors we hit before they were written down.