สถาปัตยกรรมหลายโหนด
ภาพรวม
สถาปัตยกรรมหลายโหนดทำให้อุปกรณ์หลายเครื่องทำงานร่วมกัน สร้างประสบการณ์แบบกระจายที่ "อุปกรณ์ A สนทนา อุปกรณ์ B ดำเนินการ" โดย Gateway ทำหน้าที่เป็นศูนย์กลางการจัดตารางเวลา จัดการการลงทะเบียน การค้นพบ และการกำหนดเส้นทางอัจฉริยะของโหนดทั้งหมด
ภาพรวมสถาปัตยกรรม
┌─────────┐ WebSocket ┌─────────────┐ WebSocket ┌──────────┐
│ Web 端 │ ◄────────────► │ Gateway │ ◄────────────► │ APP 节点 A│
│(Browser) │ │ (Node.js) │ │ (macOS) │
└─────────┘ │ │ └──────────┘
│ - 节点注册 │
│ - 智能路由 │ ┌──────────┐
│ - 消息转发 │ ◄────────────► │ APP 节点 B│
│ - 权限验证 │ │(Windows) │
└─────────────┘ └──────────┘

ประเภทของโหนด
| ประเภท | ตัวระบุ | คำอธิบาย | ความสามารถในการดำเนินการ |
|---|---|---|---|
| Human | เว็บเบราว์เซอร์ | โหนดผู้ใช้ฝั่ง Web | ไม่มี Agent Engine |
| Agent | APP เดสก์ท็อป | โหนดดำเนินการ Agent แบบสมบูรณ์ | มี (Sidecar ในเครื่อง) |
| Action | โหนดอัตโนมัติ | ดำเนินการโดยไม่ต้องมีผู้ดูแล | มี |
| Monitor | โหนดตรวจสอบ | ตรวจสอบสถานะ | ไม่มี |
ข้อมูลการลงทะเบียนโหนด
โหนดแต่ละตัวจะลงทะเบียนข้อมูลต่อไปนี้เมื่อเชื่อมต่อกับ Gateway:
| ฟิลด์ | คำอธิบาย |
|---|---|
nodeId |
ตัวระบุโหนดที่ไม่ซ้ำกัน |
displayName |
ชื่อที่แสดง |
platform |
ระบบปฏิบัติการ (macOS / Windows / Linux / Browser) |
version / coreVersion / uiVersion |
ข้อมูลเวอร์ชัน |
deviceFamily / modelIdentifier |
ข้อมูลอุปกรณ์ |
caps |
อาร์เรย์สตริงของความสามารถ |
tools |
รายการคำอธิบายเครื่องมือที่ใช้ได้ |
commands |
รายการคำสั่งที่สามารถดำเนินการได้ |
description |
ข้อความคำอธิบายความสามารถของโหนด |
scope |
ขอบเขตการมองเห็น (account / enterprise) |
ขอบเขตการมองเห็นของโหนด
| ขอบเขต | กฎการมองเห็น | คำอธิบาย |
|---|---|---|
| account | มองเห็นได้เฉพาะ userId เดียวกัน | โหนดส่วนบุคคล ใช้งานข้ามองค์กรได้ |
| enterprise | สมาชิกทั้งหมดที่มี orgId เดียวกันมองเห็นได้ | โหนดองค์กร แชร์ภายในองค์กร |
โหนดระดับ account: ผู้ใช้ที่ล็อกอินบนอุปกรณ์หลายเครื่อง สามารถจัดตารางงานระหว่างอุปกรณ์ใดก็ได้
โหนดระดับ enterprise: ทรัพยากรการดำเนินการที่แชร์ภายในองค์กร สมาชิกทั้งหมดสามารถใช้งานผ่าน Gateway ได้
การกำหนดเส้นทางอัจฉริยะของ Gateway
เมื่อผู้ใช้ฝั่ง Web เริ่มการสนทนา Gateway จะใช้กลยุทธ์ การลดระดับสามชั้น เพื่อเลือกโหนดดำเนินการที่เหมาะสมที่สุด:
ชั้นที่หนึ่ง: การกำหนดเส้นทางเชิงความหมายด้วย LLM
ใช้ OpenAI API วิเคราะห์เจตนาของผู้ใช้ เพื่อจับคู่โหนดที่ดีที่สุด:
| อินพุต | คำอธิบาย |
|---|---|
| ข้อความผู้ใช้ | เนื้อหาการสนทนาที่ผู้ใช้ส่ง |
| รายการโหนด | ชื่อ, คำอธิบาย (สูงสุด 500 ตัวอักษร), รายการเครื่องมือ (สูงสุด 15 รายการ) ของแต่ละโหนด |
LLM ส่งคืน: {nodeId, confidence, reason}
มาตรการด้านความปลอดภัย:
- คำอธิบายโหนดถูกจัดการเป็น DATA ไม่ได้ถูกดำเนินการเป็นคำสั่ง
- ป้องกันการฉีดพรอมต์ (prompt injection) ผ่านคำอธิบายโหนด
หมายเหตุ: การกำหนดเส้นทางด้วย LLM ในปัจจุบันยังไม่ได้กำหนดค่าโมเดล จะลดระดับไปยังชั้นที่สองโดยอัตโนมัติ
ชั้นที่สอง: การจับคู่คำสำคัญด้วย BM25
จับคู่คำสำคัญระหว่างคำค้นหาของผู้ใช้และคำอธิบายโหนดโดยอิงตามอัลกอริทึม BM25:
| พารามิเตอร์ | ค่า |
|---|---|
| k1 | 1.5 |
| b | 0.75 |
| การรองรับภาษาจีน | การแบ่งคำระดับตัวอักษร (一-鿿) |
ส่งคืนโหนดที่มีคะแนนสูงสุด หรือ null (ไม่มีการจับคู่)
ชั้นที่สาม: สำรองด้วยการเชื่อมต่อล่าสุด
เลือกโหนดที่เชื่อมต่อล่าสุดตามไทม์สแตมป์ connectedAtMs เพื่อให้มั่นใจว่ามีผลลัพธ์สำรองเสมอ
การดำเนินการระยะไกล
ขั้นตอนการสนทนา
1. Web 端发送 chat.send 到 Gateway
2. Gateway 执行智能路由,选择目标节点
3. Gateway 转发消息到 APP 节点
4. APP 节点启动 Agent Loop 执行任务
5. 执行过程中的流式事件通过 chat.event 回传
6. Web 端实时渲染执行过程
การเรียกใช้เครื่องมือระยะไกล
1. 主 Agent 通过 dispatch_multi_node_agent 指定远程节点
2. Gateway 发送 node.invoke.request 到目标节点
3. 远程节点启动独立 Agent Loop
4. 完成后通过 node.invoke.result 返回结果
การ Hoisting ไฟล์แนบ (อัปเดต 2026-04) NEW
เมื่อมีการส่งงานข้ามโหนด หากข้อความมี ไฟล์แนบ base64 แบบอินไลน์ (รูปภาพ, เอกสาร ฯลฯ) ระบบจะ อัปโหลดไปยังที่จัดเก็บบนคลาวด์ โดยอัตโนมัติและเปลี่ยนเป็นการอ้างอิงแบบ URL:
- เหตุผล: หลีกเลี่ยงการที่ข้อความ RPC ของ Gateway มีขนาดใหญ่เกินไปจนทำให้การส่งล้มเหลว
- ช่วงเวลา: ดำเนินการโดยอัตโนมัติก่อนการส่งงานระยะไกล ผู้ใช้ไม่รับรู้
- การทำให้เส้นทาง OS เป็นมาตรฐานเดียวกัน: เมื่อส่งงานข้ามระบบปฏิบัติการ (macOS/Windows/Linux) จะแปลงตัวคั่นเส้นทางโดยอัตโนมัติ
กฎการกระจายป๊อปอัปสิทธิ์
เมื่อมีการดำเนินการข้ามโหนด "จะแสดงป๊อปอัปสิทธิ์เครื่องมือที่ฝั่งใด" เป็นการตัดสินใจด้านผลิตภัณฑ์ที่สำคัญ —— ต้องหาสมดุลระหว่าง "ผู้ใช้สามารถตอบสนองได้ทันเวลา" กับ "การป้องกันการทริกเกอร์การดำเนินการที่มีความละเอียดอ่อนโดยเกินสิทธิ์"
สถานการณ์บัญชีเดียวกัน (ฝ่ายที่เรียกและฝ่ายที่ดำเนินการเป็นบัญชีเดียวกัน)
| สถานการณ์ | ตำแหน่งป๊อปอัปและการกระทำที่ใช้ได้ | สถานะ |
|---|---|---|
| node-A APP → node-B APP (บัญชีเดียวกันล็อกอินทั้งสองฝั่ง) | ส่งข้อมูลป๊อปอัปไปยัง node-A ผ่าน Gateway โดย node-A แสดงป๊อปอัปและสามารถคลิก "อนุญาต / อนุญาตเสมอ" ได้ | ⚠️ การกระจายข้ามฝั่งยังไม่ได้ถูกนำมาใช้ |
| node-C Web → node-B APP (บัญชีเดียวกัน Web เรียก APP) | ป๊อปอัปแสดงและตอบสนองที่ฝั่ง node-C Web | ✅ นำมาใช้แล้ว |
| ข้อความช่องทาง IM (โหนดเป้าหมายเริ่มต้นด้วยบัญชีเดียวกัน เช่น DingTalk/Feishu/Telegram เป็นต้น) | หาก channel รองรับการโต้ตอบแบบฟอร์ม/ปุ่ม ป๊อปอัปสิทธิ์จะถูกแปลงเป็นรูปแบบการโต้ตอบของ channel นั้น (นำมาใช้ผ่าน AskUserQuestion) หากไม่รองรับจะ ปฏิเสธโดยค่าเริ่มต้น (ไม่รอ 5 นาที) |
✅ นำมาใช้แล้ว |
สถานการณ์ต่างบัญชี (การเรียก enterprise node ข้ามบัญชี)
- node-D เป็นโหนดประเภท enterprise (สามารถถูกค้นพบโดยผู้ใช้อื่นภายในองค์กรเดียวกัน) ปัจจุบันล็อกอินด้วย user001
- node-E (ล็อกอินด้วย user002 ได้ทั้งฝั่ง APP หรือ Web) ส่งข้อความไปยัง node-D ผ่าน Gateway
- หาก node-D ต้องการสิทธิ์เครื่องมือระหว่างการดำเนินการ:
- ป๊อปอัปจะแสดงเฉพาะบนอินเทอร์เฟซของ node-D ในเครื่อง ไม่กระจายข้ามฝั่งไปยัง node-E
- หากไม่มีผู้ตอบสนองเกิน 5 นาที จะปฏิเสธโดยค่าเริ่มต้น
แรงจูงใจในการออกแบบ
| กฎ | แรงจูงใจ |
|---|---|
| บัญชีเดียวกันหลายฝั่งสามารถให้สิทธิ์ข้ามฝั่งได้ | ผู้ใช้สามารถจัดการคำขอให้สิทธิ์ได้จากฝั่งใดก็ได้ หลีกเลี่ยงการที่งานถูกบล็อกเพราะฝั่งใดฝั่งหนึ่งไม่อยู่ใกล้ตัว |
| ต่างบัญชี enterprise ไม่กระจายข้ามฝั่ง | จำกัดอย่างเข้มงวดไว้ที่เครื่องของฝ่ายที่ถูกเรียก ป้องกันไม่ให้บัญชีภายนอกทริกเกอร์การดำเนินการที่มีความละเอียดอ่อน (เช่น การอ่าน/เขียนไฟล์ในเครื่อง, การรัน Bash) ผ่านข้อความระยะไกล |
| ช่องทาง IM ที่ไม่รองรับการโต้ตอบจะปฏิเสธโดยค่าเริ่มต้น | เมื่อฝั่ง IM ไม่สามารถแสดงป๊อปอัปได้ หลีกเลี่ยงการที่คำขอค้างอยู่จนบล็อกกระบวนการ Agent |
| หมดเวลา 5 นาทีสำหรับต่างบัญชี | หาสมดุลระหว่าง "ผู้ใช้อาจออกไปชั่วคราว" กับ "หลีกเลี่ยงการที่งานค้างอยู่เป็นเวลานาน" |
การเตือนความจำในการนำไปใช้: ลิงก์การกระจายข้ามฝั่งบัญชีเดียวกันของ node-A APP → node-B APP ปัจจุบัน ยังไม่มีอยู่ ความต้องการที่เกี่ยวข้องกับเส้นทางนี้ต้องเพิ่มการกำหนดเส้นทาง Gateway + ตรรกะการรับ/แสดงผลฝั่ง APP อย่าถือว่ามันใช้งานได้แล้วโดยค่าเริ่มต้น
การแยก Gateway ข้ามบัญชี NEW
นอกเหนือจากกฎตำแหน่งของป๊อปอัปสิทธิ์แล้ว การเข้าถึงข้อมูลเอง ก็มีการแยกเช่นกัน:
การแยกความจำส่วนบุคคล
เมื่อโหนดถูกเรียกใช้ ข้ามบัญชี ในขอบเขต enterprise:
- ความจำระดับบัญชี (ผูกกับ userId): ❌ ไม่สามารถเข้าถึงได้
- ความจำระดับองค์กร (ผูกกับ orgId): ✅ เข้าถึงได้
- ความจำระดับเซสชัน (เซสชันปัจจุบัน): ✅ เข้าถึงได้
บังคับกรองในขณะสอบถามความจำผ่านแฟล็ก isRemoteSession —— ผู้เรียกข้ามบัญชี ไม่สามารถอ่านความจำส่วนบุคคลของเจ้าของโหนดเป้าหมายผ่าน memory_query ได้
เหตุใดจึงออกแบบเช่นนี้
- การปกป้องความเป็นส่วนตัว: ความชอบส่วนบุคคล นิสัยการทำงาน ข้อมูลบัญชีของคุณ ไม่สามารถถูกเพื่อนร่วมงานอ่านได้ผ่านการเรียกโหนดของคุณ
- การแชร์ภายในองค์กร: ความรู้ขององค์กร เช่น เทคโนโลยีสแตก มาตรฐาน ฯลฯ ยังคงถูกแชร์ตามปกติ ไม่กระทบต่อการทำงานร่วมกัน
- ความต้องการด้านการปฏิบัติตามข้อกำหนด: ตอบสนองต่อข้อกำหนด "สิทธิ์ขั้นต่ำ" ของกฎหมายความเป็นส่วนตัว เช่น GDPR
การแยกไอคอนของการสนทนา
การสนทนาจากแหล่งที่มาต่างกันในรายการเซสชันจะแสดงไอคอนต่างกัน:
| ไอคอน | ความหมาย |
|---|---|
| ไอคอนคอมพิวเตอร์ (LocalComputerIcon) | เริ่มต้นหรือดำเนินการโดยโหนด APP ในเครื่อง |
| ไอคอนเซิร์ฟเวอร์ (NodeIcon) | ดำเนินการโดยโหนดระยะไกล |
| ไอคอนแพลตฟอร์ม (Telegram/WeChat เป็นต้น) | มาจากช่องทาง IM |
พิจารณาจากฟิลด์ isLocalInitiated, targetNodeId และ sourceChannel
โปรโตคอล WebSocket
การจับมือเชื่อมต่อ (Handshake)
1. Client → Gateway: connect.challenge
2. Gateway → Client: challenge(含 nonce)
3. Client → Gateway: connect(含签名的 JWT)
4. Gateway → Client: hello-ok(确认连接)
การรักษาการเชื่อมต่อด้วย Heartbeat
- กลไก tick: heartbeat เป็นระยะเพื่อรักษาการเชื่อมต่อ
- การเชื่อมต่อใหม่เมื่อสายหลุด: ลองใหม่แบบ exponential backoff
- การล้างข้อมูลหมดอายุ: Gateway ล้างเซสชันโหนดที่หมดอายุเป็นระยะ
การควบคุมทราฟฟิก
- การจำกัด Delta: รวมเหตุการณ์สตรีม SSE ทุก 150ms เพื่อลดจำนวนเฟรม WebSocket
- Run TTL: หมดเวลา 10 นาที ล้าง Run ที่หมดอายุทุกชั่วโมง
สิ่งนี้มีความหมายอย่างไรต่อผู้ใช้
สถาปัตยกรรมหลายโหนดทำให้คุณสามารถเริ่มงานได้จากที่ใดก็ได้ และให้อุปกรณ์ที่เหมาะสมที่สุดเป็นผู้ดำเนินการ
สถานการณ์ทั่วไป:
- เริ่มงานที่ต้องเข้าถึงไฟล์บนคอมพิวเตอร์ที่ออฟฟิศจากเบราว์เซอร์บนมือถือ (ฝั่ง Web) ในร้านกาแฟ → Gateway จะกำหนดเส้นทางงานไปยังโหนด APP ที่ออฟฟิศเพื่อดำเนินการโดยอัตโนมัติ
- เซิร์ฟเวอร์ประสิทธิภาพสูงในทีม (macOS Pro) เปิด APP ไว้ตลอดและตั้งเป็น enterprise → สมาชิกในทีมทุกคนสามารถส่งงานหนักไปยังเครื่องนั้นจากเบราว์เซอร์ของตนเองได้
ประสบการณ์ที่คุณจะสัมผัสได้:
- เมื่อเริ่มการสนทนาที่ฝั่ง Web ระบบจะเลือกโหนด APP ที่ออนไลน์อยู่มาดำเนินการโดยอัตโนมัติ
- รายการเซสชันจะแสดงไอคอนต่างกัน เพื่อให้คุณรู้ว่าการสนทนานั้นดำเนินการในเครื่องหรือดำเนินการระยะไกล
- หากไม่มีโหนด APP ออนไลน์ ฝั่ง Web จะแจ้งว่าไม่สามารถดำเนินการงานที่ต้องใช้ความสามารถของ Agent ได้
- เมื่อคอมพิวเตอร์หลายเครื่องติดตั้ง APP ไว้ คุณสามารถเลือกด้วยตนเองว่าจะดำเนินการบนเครื่องใด
สิ่งที่คุณต้องระวัง:
- ฝั่ง Web ไม่สามารถดำเนินการงาน Agent ได้ด้วยตนเอง ต้องมีโหนด APP ออนไลน์อย่างน้อยหนึ่งตัว
- การสนทนาที่ดำเนินการระยะไกลจะมีความล่าช้าของเครือข่าย (ขึ้นอยู่กับคุณภาพเครือข่ายระหว่าง Gateway และโหนด)
- เมื่อตั้งค่าโหนดเป็นขอบเขต enterprise สมาชิกในทีมสามารถส่งงานไปยังอุปกรณ์ของคุณได้ —— แต่ ความจำส่วนบุคคลของคุณจะไม่ถูกเข้าถึง
เอกสารที่เกี่ยวข้อง
- การจัดการโหนด Work — ดูโหนดที่ออนไลน์ในอินเทอร์เฟซการจัดการ
- ความปลอดภัยขณะรันไทม์ — โหนด — การกำหนดค่าความปลอดภัยของโหนด
- ตัวแทนย่อย — การส่งงานข้ามโหนด — dispatch_multi_node_agent
- ระบบความจำสามมิติ — การแยกความจำข้ามบัญชี
