ข้ามไปยังเนื้อหาหลัก

Work: พื้นที่ทำงานแบบแยก

Work คือ UI agent เขียนโปรแกรมในตัวของ Libre WebUI แต่ละ task รวม conversation แบบคงอยู่ route ของ provider ที่ชัดเจน และ filesystem /workspace แยก โมเดลดูและแก้ file รัน command ใน Docker container หรือ Kubernetes Pod ของ task และเริ่ม preview ได้

Work ทำงานแบบ native โดยไม่ใช้ Libre Claw หรือ daemon แยก

เฉพาะผู้ใช้ที่เชื่อถือได้

API ทั้งหมดต้องใช้ account ที่ยืนยันตัวตนและมีสิทธิ์ ค่าเริ่มต้นเฉพาะ administrator แต่เปิดให้ user ที่ active ทั้งหมดได้ Folder ของ host จำกัดเฉพาะ administrator เพราะ mount path ของ server Work ตั้งใจให้รัน shell command ใดก็ได้ใน sandbox Task ใช้ egress เว้นแต่ policy ที่เลือกปิด network ให้ถือ user ทุกคนที่ได้รับอนุญาตเป็น operator runtime ที่เชื่อถือได้ ไม่ใช่เพียง user chat

ความสามารถหลักของรุ่น

  • Mode Work และ Chat แยก พร้อม selector ที่มองเห็น
  • Task ในรายการข้างหลัก ตำแหน่งคงที่ และลบโดยตรง
  • Identity sandbox แยก พร้อม Docker volume แบบคงอยู่หรือ Kubernetes PVC ต่อ task; หยุด/สร้าง environment ใหม่ได้โดยไม่เสีย file
  • เก็บ conversation, state ของ run, activity ของ tool, การเลือกโมเดล และ owner ของ task ในฐานข้อมูล Libre WebUI
  • Stream ที่ยืนยันตัวตนสำหรับข้อความ assistant, reasoning ที่ provider เปิดเผย, tool call/result, usage, skill และการเปลี่ยน state
  • Workflow skill ของ server สอนโมเดลให้ inspect, edit, test และเริ่ม preview โดยไม่สร้าง file ควบคุมใน project
  • โมเดล Ollama local ที่มี tool, Ollama Cloud และ plugin provider ที่ตั้งค่าแล้ว
  • แบ่ง Conversation/Workspace แบบปรับได้ resize ด้วย mouse/keyboard บน desktop และ switch บนหน้าจอเล็ก
  • View Files, Activity, Git, Terminal, Preview, Screen ในตัว; Screen แสดง desktop Work Computer
  • Syntax highlighting โหมดสว่าง/มืด formatting ใน browser ตรวจ save conflict และ draft ชั่วคราว
  • Data disclosure ต่อ user ที่ปิดได้เมื่อเลือก provider remote
  • แปล Work ครบ 25 ภาษา รวม layout RTL ภาษาอาหรับแบบ native โดยรักษา LTR สำหรับ code, path, model ID และ output

หน่วยที่คงอยู่คือ workspace ของ task ไม่ใช่ container ที่รันตลอด Libre เริ่ม หยุด และสร้าง container ใหม่เมื่อจำเป็นโดยเก็บ named volume

สถาปัตยกรรม

Libre WebUI ไม่ใช่โมเดลหรือ browser เป็นผู้เลือกชื่อ sandbox/workspace, image, volume mount, user, ขีดจำกัด, network mode และ preview port โมเดลได้รับเฉพาะ tool ต่อไปนี้:

  • list_files
  • read_file
  • write_file
  • delete_file
  • move_file
  • search_files
  • run_command
  • start_preview
  • stop_preview

delete_file และ move_file ออกจาก workspace ไม่ได้ ไม่ตาม symlink ต้องมี recursive flag ชัดเจนสำหรับ directory และไม่เขียนทับ destination เพราะใช้ file helper tool จึงทำงานใน preview ได้แม้ run_command ถูกบล็อก

Request ของโมเดลทำโดย server ไม่ใช่ container Work จึงไม่ขึ้นกับ network policy ของ container

ข้อกำหนด

  • Docker: daemon ติดตั้งและเข้าถึงได้ process ของ server มีสิทธิ์เรียก docker หรือ program ใน WORK_DOCKER_COMMAND
  • Kubernetes: API credential Role/RoleBinding จำกัด namespace, namespace sandbox และ NetworkPolicies ที่ Helm สร้างเมื่อ work.enabled=true

นอกจากนี้:

  • โมเดลที่มี tool ผ่าน Ollama/Ollama Cloud ที่พร้อมใช้งาน หรือ plugin completion/chat active พร้อมโมเดลที่ตรงและ credential administrator
  • Memory เพียงพอสำหรับ image environment, project และ dependency local
  • Account ที่ยืนยันตัวตนและมีสิทธิ์ Work; ค่าเริ่มต้นเฉพาะ administrator แต่เปิดให้ user active ทั้งหมดได้

Libre ตรวจ capability ของ Ollama และปฏิเสธโมเดลที่ไม่มี tools โมเดล plugin ต้องรองรับ protocol tool-calling ของ provider ความล้มเหลวจะจบ run โดยไม่ fallback แบบเงียบ

รันในเครื่อง

วิธีง่ายที่สุดบนเครื่องเดียว:

docker info
npx libre-webui@latest

เปิด http://localhost:8080 login เป็น administrator เลือก Work และโมเดลที่เข้ากัน แล้วอธิบาย task

หากไม่มี Docker หรือเข้าถึงไม่ได้ Work แสดง Runtime unavailable พร้อมเหตุผลและปิดการเริ่ม Command จะไม่รันโดยตรงบน host

ครั้งแรกจะตรวจ image environment และ download อัตโนมัติหากไม่มี จึงอาจใช้เวลานานขึ้น

UI ของ Work

สร้างและเปิดอีกครั้ง

เลือก Work ป้อนคำสั่ง เลือกโมเดล แล้วกด Run message แรกสร้าง task, run แรก, route ของ provider และ workspace คงอยู่

Task อยู่ใน sidebar หลัก เปิดอีกครั้งจะคืน conversation ล่าสุด tab Files, provider/model ปัจจุบัน และ workspace Message เก่า load เป็นหน้า เปลี่ยนชื่อจาก title และลบผ่าน menu/sidebar ได้

มี run active ได้เพียงหนึ่งรายการต่อ task คำสั่งถัดไปใช้ conversation และ filesystem เดิม

Composer รองรับการบอกข้อความ ปุ่ม microphone ใช้ speech API ของ browser หรือโมเดลรู้จำเสียงที่ตั้งค่า และเพิ่ม transcript ลงใน text File ที่สร้าง/ย้ายแสดงเป็น badge ที่คลิกได้ใต้ action ของ tool คลิกเปิด editor และสลับไป workspace บนหน้าจอแคบ มีเพียง tool ที่แก้ไขเท่านั้นสร้าง badge ดังนั้น read 20 ครั้งและ write 1 ครั้งจะแสดง artifact หนึ่งรายการ

จ้างเป็น Agent

หากมี persona คำสั่ง Hire as agent เปลี่ยน task เป็น agent ที่มีชื่อและคงอยู่ Persona อยู่ระหว่าง run ชื่อและ system prompt มาก่อน prompt Work แต่ contract ของ sandbox มีลำดับสูงสุด Sidebar วาง agent ในกลุ่ม Agents เหนือ task ครั้งเดียว พร้อม avatar, activity และ state เมื่อย่อ sidebar จะเหลือเฉพาะ avatar ของ agent ที่ปักหมุดไว้ในแถบ rail ส่วน task Work แบบครั้งเดียวจะกลับมาเมื่อขยาย sidebar อีกครั้ง

บรรทัด state มีสองระดับ หลัง run ของ agent จะมี request โมเดลราคาต่ำแบบไม่มี tool เพื่อขอ status ราว 8 คำ (“กล่องข้อความว่าง มี 2 คำตอบพร้อมแล้ว”) response จำกัดหนึ่งบรรทัด 90 ตัว หาก error/timeout ใช้บรรทัดแรกของคำตอบสุดท้าย Task ครั้งเดียวและ run ที่ล้มเหลวใช้ fallback แบบ deterministic นี้ WORK_STATUS_BLURB_MODEL=0 ปิด request การเปิด task จะเลื่อน marker viewed แบบ monotonic ที่ sync ระหว่างอุปกรณ์ จุดหมายถึง terminal run ที่ใหม่กว่า

Agent รายงานงานผ่าน notification: work-run-finished, work-run-attention, work-takeover Banner ของ Screen เห็นเฉพาะ tab ที่เปิด push notification ไปถึง user ที่อื่น ลิงก์แต่ละรายการไปยัง agent โดยตรง

ใช้ persona ของตนหรือ shared ได้ view แบบ shared ไม่เปิด memory ของ owner หากลบ persona agent จะทำงานต่อโดยไม่มีและบันทึก warning API รับ personaId, isAgent task ที่มี persona จะเป็น agent อัตโนมัติ

Tab Agent

Tab เพิ่มแรกคือ Agent:

  • Identity: avatar, ชื่อ, indicator activity และบรรทัด state ล่าสุด
  • Screen: หากมี Work Computer จะแสดง thumbnail live แบบ read-only นี่คือ connection เต็มที่นับใน limit คลิกเปิด full screen พร้อม takeover, teaching และ audio
  • Routines: automation ที่ผูกกับ task แต่ละ trigger รันใน workspace/conversation เดิมด้วย model/environment ของ agent ไม่ใช่ task ใหม่ จึงสะสม morning report ที่เดียว บรรทัดแสดง schedule และ pause toggle form + Routine ผูกกับ agent แล้ว Trigger ขณะ agent ยุ่งจะจบด้วย work-task-busy โดยไม่เข้าคิว
  • Auto Review: สวิตช์ approval ของ agent และ rule Always-allow ที่ agent สะสมไว้ (ลบ rule เพื่อปิดขอบเขตนั้นอีกครั้ง) เมื่อ policy ของ task บังคับให้ review สวิตช์จะถูกล็อกเป็นเปิด
  • Taught skills: routine ที่สาธิตแล้วพร้อม enable toggle

เครื่องมือที่เชื่อมต่อ (เซิร์ฟเวอร์ MCP และ OpenAPI)

Agent ของ Work เรียกใช้ เซิร์ฟเวอร์เครื่องมือ ชุดเดียวกับที่ตั้งค่าไว้สำหรับแชตได้ ทั้ง MCP และ OpenAPI ซึ่ง administrator ลงทะเบียนไว้ที่ การตั้งค่า → เครื่องมือ เครื่องมือจะปรากฏต่อ agent ด้วยชื่อที่มี namespace (server__tool) และการเรียกจะรันจาก backend ของ Libre WebUI ผ่าน gateway เครื่องมือที่เสริมความแข็งแรงแล้ว (egress กัน SSRF, credential ต่อ user, จำกัดขนาดและเวลา) ไม่เคยรันจากในกล่อง sandbox

รายการที่เสนอตรงไปตรงมาว่ารันแบบอัตโนมัติใช้อะไรได้จริง:

  • Task ที่ออฟไลน์จะไม่ได้เครื่องมือใดเลย: แม้ egress จะออกจาก backend แต่ task ที่ไม่มี network ก็ยังออฟไลน์ ด้วยเหตุผลเดียวกับ web_search
  • เซิร์ฟเวอร์ที่ต้องใช้ credential ส่วนตัวซึ่งผู้ใช้ยังไม่ได้บันทึกจะ ถูกกรองออกตั้งแต่ตอนเสนอเครื่องมือ เพราะการรันแบบอัตโนมัติหยุดเพื่อถามไม่ได้ เพิ่ม credential ที่ การตั้งค่า → เครื่องมือ แล้วการรันครั้งถัดไปจะเสนอเซิร์ฟเวอร์นั้น
  • โหมดการเข้าถึงเครื่องมือ (เฉพาะ administrator หรือผู้ใช้ทุกคน) และการมองเห็นรายเซิร์ฟเวอร์ใช้เหมือนในแชตทุกประการ และการผูกเซิร์ฟเวอร์เครื่องมือของเพอร์โซนาจะจำกัดว่า agent ที่จ้างจากเพอร์โซนานั้นเห็นเซิร์ฟเวอร์ใดบ้าง
  • เมื่อ การอนุมัติ ทำงานอยู่ เครื่องมือที่เชื่อมต่อซึ่งเซิร์ฟเวอร์จัดว่า มีผลข้างเคียง จะหยุดรอการตัดสินใจของคุณเหมือนการกระทำที่ถูกกำกับอื่น ๆ ส่วนเครื่องมือที่อ่านอย่างเดียวจะรันโดยไม่ถาม

การมอบหมายระหว่าง agent (@-mention)

Agent ที่จ้างไว้ส่งงานให้กันได้ พิมพ์ @ ในช่องเขียนของ Work เพื่อกล่าวถึง agent ตัวอื่นของคุณ agent ปัจจุบันจะเห็นรายชื่อเพื่อนร่วมงาน (ชื่อและบรรทัด state) ในคำสั่งของตน แล้วมอบหมายคำขอที่ตรงกันด้วยเครื่องมือ message_agent การมอบหมายคือการประสานงานด้วยข้อความ ไม่ใช่การใช้เครื่องร่วมกันโดยตั้งใจ: agent แต่ละตัวมี workspace และ sandbox ของตัวเอง และปลายทางมองไม่เห็นบทสนทนาที่มอบหมาย คำขอจึงต้องพก context ของตัวเองมาด้วย

การมอบหมายเป็นแบบอะซิงโครนัส เครื่องมือคืนค่าทันที agent ปลายทางรันใน task ของตัวเอง (บทสนทนาของมันแสดงคำขอที่ติดป้าย Delegated by ผู้ส่ง) และเมื่อทำเสร็จ ไม่ว่าจะสำเร็จ ต้องการ input ผิดพลาด หรือถูกยกเลิก คำตอบสุดท้ายจะถูกส่งกลับเข้าบทสนทนาของ agent ผู้มอบหมายเป็นข้อความที่ติดป้าย Report from agent นั้น หากผู้มอบหมายยังรันอยู่ รายงานจะถึงโมเดลใน round ถัดไป หากว่างอยู่ รายงานก็จะรออยู่ในบทสนทนาเฉย ๆ รายงานจะไม่เริ่มรันเองโดยอัตโนมัติ agent สองตัวจึงโยนงานไปมาไม่ได้ รอบที่ถูกมอบหมายจะมอบหมายต่อไม่ได้ ปลายทางที่ยุ่งอยู่จะล้มเหลวอย่างตรงไปตรงมาแทนการเข้าคิว และเมื่อการอนุมัติทำงานอยู่ message_agent จะหยุดรอการตรวจเหมือนการกระทำที่มีผลข้างเคียงอื่น (rule Always-allow ผูกกับ agent ปลายทางตัวนั้นตัวเดียว)

การอนุมัติการกระทำ (Auto Review)

การกระทำที่มีผลข้างเคียงสามารถหยุดรอการตัดสินใจของคุณก่อนรันได้ เมื่อการอนุมัติทำงานอยู่กับ task — policy ของ Work ตั้ง Require approval for side-effecting actions หรือสวิตช์ Auto Review ของ agent เปิดอยู่ — รอบจะหยุดก่อนสั่ง run_command, computer_act, delete_file, move_file หรือ message_agent และแสดงการ์ดตัดสินใจในบทสนทนา: Allow once, Always allow หรือ Deny

  • Allow once รันเฉพาะการเรียกครั้งนี้และถามใหม่ในครั้งถัดไป
  • Always allow รันการเรียกและบันทึก rule ไว้กับ task: ครอบทั้งเครื่องมือสำหรับการกระทำกับไฟล์และคอมพิวเตอร์ จำกัดเฉพาะโปรแกรมของคำสั่ง (token แรก) สำหรับ run_command — อนุมัติ npm run build คืออนุมัติล่วงหน้าให้คำสั่ง npm ในอนาคต ไม่ใช่ทั้ง shell — และจำกัดเฉพาะ agent ปลายทางตัวเดียวสำหรับ message_agent rule จะแสดงในส่วน Auto Review ของแท็บ Agent และลบได้ที่นั่น
  • Deny ปฏิเสธการเรียก โมเดลจะได้รับแจ้งว่าผู้ใช้ปฏิเสธการกระทำนั้นและต้องไม่ลองใหม่แบบเดิม รอบจะทำงานต่อด้วยคำตอบนั้น

การอนุมัติที่รออยู่จะสร้างการแจ้งเตือนด้วย (ในแอป และ web push เมื่อเปิดใช้) เพราะรอบอาจทำงานโดยไม่มีคนดูมาหลายนาทีแล้วเมื่อไปถึงจุดกำกับ หากไม่มีใครตัดสินใจภายในห้านาที คำขอจะหมดอายุ การกระทำจะไม่ถูกสั่ง และรอบจะจบเป็น ต้องการ input พร้อม handoff ตามปกติแทนการรอจนหมดงบ

การอนุมัติกำกับการกระทำ ไม่ได้กำกับการมองเห็น: write_file และเครื่องมือที่อ่านอย่างเดียวยังไม่ถูกกำกับ และทุกการตัดสินใจจะถูกบันทึกใน log ตรวจสอบความปลอดภัย

State ของ Task

UIState ของ Serverสี
Idleidlergb(255, 255, 255)
กำลังประมวลผลpreparing หรือ runningrgb(48, 121, 255)
พร้อมcompletedrgb(76, 212, 117)
ต้องการ inputneeds_input หรือ cancelledrgb(255, 204, 0)
ผิดพลาดfailedrgb(255, 61, 129)

หยุด run active จะเปลี่ยนเป็น ต้องการ input และเก็บ file งบ round/tool หมดก็จบแบบเดียวกันหลัง handoff สุดท้ายที่ไม่มี tool งานที่ยังไม่เสร็จจะไม่ถูกทำเครื่องหมาย พร้อม

Run active ไม่บล็อก conversation: message จะรวมทันทีและถึงโมเดลใน round ถัดไป ทำให้ชี้นำ แก้ไข และเพิ่ม context โดยไม่ stop

ปรับขนาด

ที่ความกว้าง desktop xl conversation/workspace แบ่งด้วย divider ที่ลากได้:

  • ความกว้าง conversation ค่าเริ่มต้น 45%
  • ช่วงแนะนำ 30%–70% โดยคำนึง minimum content width
  • Ratio ที่เก็บเป็นของ user ที่ login ใน browser นี้
  • ปุ่มลูกศรขยับ 2% และ Shift 10%
  • Home/End เลือก minimum/maximum
  • Enter หรือ double-click reset split

Control ตามทิศทางการเขียน ภาษาอาหรับ conversation อยู่ขวา workspace อยู่ซ้าย pointer/arrow ตามทิศทาง visual

หน้าจอเล็กใช้ switch ใน header ของ task

Files

Tab Files แสดง /workspace โดยตรง เปิดเฉพาะ file text UTF-8 ที่ถูกต้องและ save การเปลี่ยนแปลงลง volume ของ task ลำดับ byte ที่ไม่ถูกต้องถูกปฏิเสธ ไม่แทนที่จนเสีย data

Editor มี:

  • syntax highlighting สว่าง/มืดสำหรับภาษาทั่วไป
  • save ด้วย Cmd/Ctrl+S
  • format ด้วย Shift+Alt+F
  • ตรวจ save conflict แบบ optimistic
  • draft ตาม task/path ใน session memory
  • warning เมื่อออกพร้อมการเปลี่ยนแปลงที่ยังไม่ save

Live highlighting หยุดเหนือ 8,000 ตัวอักษร/400 บรรทัด Formatting ถึง 100,000 ตัวอักษร/4,000 บรรทัดสำหรับ JavaScript/JSX, TypeScript/TSX, JSON variant, CSS/SCSS/Less, HTML, Markdown/MDX และ YAML

เมื่อโมเดลแก้ file ที่เปิด tab แสดง diff แดง/เขียวตั้งแต่ต้น round และย่อส่วนยาวที่ไม่เปลี่ยน Toggle สลับ diff/editor counter +added −removed สรุป Baseline คือ content ที่ browser เห็นก่อน round file ที่เปิดครั้งแรกภายหลังจะไม่แสดง diff

Draft มีไว้สะดวก ไม่ใช่ backup และล้างหลัง save, delete task หรือจบ session

Activity

Tab แสดง tool call/result, การทำงาน file, command output และ error ขยาย metadata ได้ Output ยังคง LTR ใน UI RTL

Run active เปิด stream SSE ที่ยืนยันตัวตนพร้อม event:

  • snapshot, run_state;
  • reasoning_delta หาก provider เปิด reasoning
  • assistant_delta;
  • tool_call, tool_result;
  • usage;
  • skill_loaded; และ
  • error, done.

Reasoning ขึ้นกับ model/provider Libre แสดงเฉพาะ content ที่ API คืนและสร้าง chain-of-thought ที่ซ่อนไม่ได้ บางโมเดลไม่ส่ง Text และ action ของ tool stream แยกได้

Output จำกัดโดยตั้งใจ ผลที่ถูกตัดไม่พิสูจน์ว่าไม่มีต่อ ขอให้โมเดลตรวจผลลัพธ์ที่แคบกว่า

Git

Tab Git ทำงาน local ใน /workspace:

  • init repository ด้วย branch main
  • แสดง status porcelain, ahead/behind และ commit สูงสุด 20
  • แสดง diff จำกัด
  • stage path สูงสุด 200
  • สร้าง commit ด้วยชื่อ/email administrator หรือ no-reply local
  • สร้าง branch หลัง commit แรก
  • switch ไป branch ที่มีหาก working tree สะอาด

พื้นผิว local เท่านั้น: ไม่มี clone, fetch, pull, push, จัดการ repository remote, command ใดก็ได้, token, SSH key หรือ pull request ใช้ broker credential ที่เชื่อถือได้แยก โดยควรเป็น GitHub App หรือ installation token ที่จำกัด repository/action เดียว อย่าเก็บ credential อายุยาวใน workspace, environment ของ container หรือ config repository

Git read ใช้ได้เมื่อ task idle/active Write ถูกปฏิเสธเมื่อ run ของโมเดล terminal หรือ preview ครอบครอง container การ switch branch ต้องใช้ tree สะอาด ซึ่งป้องกัน race

Command UI ใช้ array argument คงที่และรันเป็น 1000:1000 input ไม่ถูก shell evaluate Environment ปิด config system/global, prompt, hook, credential helper, signing, submodule, external diff, textconv และ network protocol Repository ถูกปฏิเสธหาก work tree ไม่ใช่ /workspace หรือ Git dir ออกนอก Write ถูกบล็อกหากมี filter clean/smudge/process executable

สิ่งนี้ปกป้อง Git API ของ Libre WebUI Administrator ผ่าน terminal และโมเดลผ่าน run_command ยังรัน Git command ปกติได้ command ใดก็ได้ถูกจำกัดด้วย sandbox และ boundary deployment

Workflow Skill ในตัว

แต่ละ run ได้ reference ของ server เกี่ยวกับ boundary /workspace แบบคงอยู่ root read-only, process ชั่วคราวและ /tmp, network, limit, lifecycle preview Skill กำหนดให้:

  • ตรวจ instruction, manifest, lockfile, script และ state repository ก่อน edit
  • เก็บงานไม่เกี่ยวข้องและ batch read อิสระ
  • ทำ implementation ต่อ ไม่หยุดที่ plan
  • ตรวจ targeted ก่อนตรวจวงกว้าง
  • diagnosis error ไม่ retry แบบสุ่ม
  • verify แอปก่อน start preview เป็น process ยาวสุดท้าย

Reference อยู่เฉพาะใน context โมเดล Libre ไม่สร้าง AGENTS.md, directory skill หรือ file control อื่น Instruction project override security boundary ไม่ได้

Terminal

Shell แบบโต้ตอบเชื่อม sandbox เดียวกัน เพื่อให้ administrator ตรวจ state, build และ debug project

ใช้ policy เดียวกัน: 1000:1000 แบบไม่มี privilege, directory /workspace และ container hardened ที่ไม่มี capability Terminal ไม่ให้ privilege มากกว่า run_command เพียงมี UI สำหรับมนุษย์ไปยัง boundary เดิม

  • การยืนยันตัวตน — header Authorization แลกผ่าน HTTP เป็น ticket ใช้ครั้งเดียวอายุสั้นที่ผูกกับ protocol และ task ที่ตรง มีเพียง ticket และ task ID ใน /ws/work-terminal ตรวจ account, access, task และ owner ใหม่ก่อนทุก input การ revoke ปิด session และปล่อย lease
  • ตรวจ Origin — หากตั้ง CORS_ORIGIN หรือ BASE_URL origin ของ browser ต้องตรง ตั้งอย่างน้อยหนึ่งค่าสำหรับ deployment remote Client Electron/non-browser อาจไม่ส่ง Origin แต่ยังต้องใช้ ticket และ check จัดการด้วย TLS, firewall และ proxy
  • Admission — terminal ใช้ runtime lease และนับใน WORK_MAX_ACTIVE_RUNTIMES_*
  • อายุ Container — terminal ที่เชื่อมจะยึด container ไม่ให้ idle stop
  • ConcurrencyWORK_TERMINAL_MAX_SESSIONS_PER_TASK ค่าเริ่มต้น 2
  • Idle timeoutWORK_TERMINAL_IDLE_TIMEOUT_MS ค่าเริ่มต้น 15 นาที
  • Run active — terminal รอ model turn จบ

TTY ต้องใช้ stream สองทิศทางที่ capture ดังนั้น terminal เข้าถึง Docker Engine API โดยตรง ลำดับคือ WORK_DOCKER_SOCKET, DOCKER_HOST—socket unix:// หรือ HTTP ธรรมดา tcp:// ผ่าน proxy พร้อม tunnel Connection: Upgrade—แล้ว /var/run/docker.sock ไม่รองรับ ssh:// หรือ tcp:// ที่มี DOCKER_TLS_VERIFY และทำให้ terminal unavailable พร้อมคำอธิบาย โดยไม่กระทบ Work ส่วนอื่น Kubernetes ใช้ TTY WebSocket ของ exec API subresource รวม resize โดยไม่ใช้ Docker

Session แบบโต้ตอบไม่ถูกบันทึก และ command ไม่แสดงใน Activity

Preview

Preview start, stop, embed และเปิดแอป Field command ว่างตรวจพบ:

  • script dev ใน root package.json พร้อม host/port ที่ต้องการ
  • root index.html ที่ static server ในตัวให้บริการ
  • แอปหนึ่งรายการใน directory nested

ให้ app root มีลำดับก่อน แอป nested หลายรายการที่เท่ากันหรือไม่มี entry point ทำให้เกิด error ชัดเจน ไม่ใช่ npm command แบบสุ่ม สำหรับ project อื่นให้ป้อน command ก่อน Start preview โดยเริ่มที่ /workspace เช่น cd apps/web && npm run dev -- --host 0.0.0.0 --port 4173 Process ต้อง listen บน 0.0.0.0 และ WORK_PREVIEW_PORT และพร้อมภายใน 15 วินาที

โมเดลใช้ start_preview ได้ ซึ่งเป็นวิธีเดียวที่รองรับเพื่อคง process ยาว run_command ล้าง child process background เมื่อเสร็จ

Screen (Work Computer)

ดู agent Libre WebUI Work ค้นหารูปและสร้างแกลเลอรีอวกาศแบบโต้ตอบ

Demo เต็ม: run จริงที่ไม่ edit (30x แล้ว real time) ซึ่ง agent browse NASA เลือกรูป build และ test gallery Three.js จากพรอมต์เดียว

Policy Work Computer เพิ่ม tab Screen: หน้าต่าง live ของ desktop เสมือนใน sandbox เดียว พร้อม window manager, panel และ Chromium 1280×800 คุณดู agent, takeover mouse/keyboard, ฟัง audio คอมพิวเตอร์ และสอน action ด้วย demo ได้ การเปิด tab เริ่ม session กราฟิก on-demand (ไม่มีสิ่งใดรันก่อน observer) และเชื่อม view VNC ผ่าน WebSocket

Administrator ใช้ Enable คลิกเดียว Libre สร้าง image กราฟิกในตัวบน Docker daemon ของ deployment (ครั้งแรกหลายนาที) และ policy พร้อมโดยไม่ต้อง docker build ด้วยมือ หลัง proxy กรอง build endpoint ถูกปิดโดยตั้งใจ ให้ pull image ghcr.io/libre-webui/libre-work-computer tag libre-work-computer:latest บน host หรือ build จาก deploy/work-computer/ แล้วปุ่มจะสร้างเฉพาะ policy Task ต้องมี network เพราะ Screen เข้าถึงผ่าน loopback port เช่น preview

VNC server ใน container listen ที่ localhost และใช้ password สองค่าต่อ session: observer ที่อนุญาตได้ password view-only ส่วน control-lease owner เท่านั้นได้ password เต็ม Server ทิ้ง input อื่น WebSocket bridge เป็น surface เดียวที่เข้าถึงได้และ publish เฉพาะ loopback host Observer แต่ละราย authenticate ด้วย ticket session/task ใช้ครั้งเดียวเช่น terminal ตรวจ Work access ทุก connection และ revocation ตัด Screen ทันที สูงสุดสี่ observer และ viewing นับเป็น activity ของ task

Viewing ไม่แข่งกับ execution การเปิดระหว่าง run เชื่อม sandbox เดียว Screen ที่สังเกตไม่ block run ถัดไป และ session อยู่หลัง completion แม้ deployment team มี worker ภายนอก Browser profile เก็บที่ /workspace/.browser-profile ทำให้ login อยู่ข้าม container restart

การควบคุม agent ใช้ tool สองรายการ computer_observe คืน full screenshot, pointer position, active window, current browser URL, focus ของหน้า/UI browser, สรุป element ที่ focused และ hash screenshot สัญญาณ semantic มาจาก DevTools บน loopback container และไม่มีใน image เก่า computer_act รัน batch สูงสุด 24 action—move, click, double/right click, type, key combo, scroll, wait—แล้วคืน screenshot หลังนิ่ง

Guard ทำงานสามจุด: action type/key ประกาศ focus ที่คาดได้และ fail safe หาก field ไม่ focused เพื่อไม่ให้ text เข้า address bar; batch หยุดเมื่อ window, title หรือ focus เปลี่ยนเพราะ coordinate ที่เหลือ stale; batch ประกาศ title, URL หรือ region change ที่คาดได้ และ environment verify ด้วย deadline adaptive—waiting ไม่ใช่ success

หลัง batch จะ poll Screen จนนิ่งแทน delay คงที่ ผลมี evidence: click รายงาน pixel ใกล้เปลี่ยน scroll_until scroll ถึง text/edge และรายงาน visibility แต่ละ observation เทียบก่อนหน้าและบอก no-change ชัด subgoal หนึ่งบรรทัดเก็บเป็น checkpoint และทำซ้ำเมื่อ recovery action เดิมสามครั้งบน Screen ไม่เปลี่ยนทำให้ warning การทำซ้ำหยุด run พร้อมขอ input Wait ที่ไม่ confirm ต่อเนื่องต้อง observation ใหม่ Telemetry round, delay, screenshot, guard และ verdict ถูก log พร้อม tool/outcome

Screenshot ส่งเป็น image จริงทุก route—Ollama, Anthropic, Gemini และ Chat/Responses ที่เข้ากันกับ OpenAI—จึงควรใช้โมเดล vision สำหรับ control หาก provider ปฏิเสธ image run จะไม่ fail: ตัด screenshot ออกจาก run ที่เหลือ โมเดลเปลี่ยนเป็น observation text และ log อธิบาย Verification นี้อ่อนกว่า Context มีเพียง screenshot ล่าสุด log คงอยู่เก็บเฉพาะ text ไม่เก็บ byte image

Content blocking ใน browser มี uBlock Origin Lite สำหรับโฆษณา/tracker (pin version และ verify checksum ตอน build; filter mode จัดการด้วย policy) และปิด cookie-consent banner อัตโนมัติ โฆษณาไม่ใช้ screenshot, token หรือ click Script โฆษณาที่รู้จักถูกแทนด้วย stub local ที่ปลอดภัย Agent ห้ามใส่ credential หรือผ่าน CAPTCHA/2FA และรายงาน blocker สำหรับ task ไม่น่าเชื่อถือให้รวม policy กราฟิกกับ DNS filtering

Audio ค่าเริ่มต้นปิดเพราะ browser ต้อง click ปุ่ม speaker stream audio คอมพิวเตอร์ real time PulseAudio เล่นไป null sink ส่วน monitor ส่ง PCM raw ผ่าน WebSocket ยืนยันตัวตนตัวที่สองบน loopback ด้วย ticket, access recheck และ observer limit เดิม ต้องใช้ image ใหม่จาก deploy/work-computer/

Take over control ให้ mouse/keyboard สำหรับ login, CAPTCHA หรือขั้นตอนมนุษย์ Done คืน Screen Session VNC ใช้ password full/view ที่สร้างและไม่ log password full ให้เฉพาะ lease owner Lease หมดในสองนาที ต่ออายุด้วย UI ที่เปิด และ user อื่นแย่งไม่ได้

Policy Allow screen takeover ห้าม control ทั้งหมดได้: ซ่อนปุ่ม takeover/teaching, endpoint ปฏิเสธ, request_takeover รายงาน unavailable; viewing ยังอยู่ เมื่อมนุษย์ control computer_observe/computer_act ถูก block เพื่อไม่ให้ agent แทรกหรือ capture input request_takeover แสดง banner เหตุผลและรอคืน Credential ไปจาก keyboard ถึงหน้าโดยตรง ไม่ผ่าน model/log Image เก่ารองรับ viewing เท่านั้น

Mode Teach task บันทึก demo: มนุษย์ control Screen พร้อม indicator ที่เห็น และเก็บ action เป็น coordinate แต่ละ click bind กับ tag read-only, ID, label ที่เห็น และ current URL ทำให้ step ตั้งชื่อ target เช่น “Click button#submit (Place order)”; coordinate เป็น hint

Save สร้าง script deterministic ไม่มีโมเดล: รวม keystroke เป็น string แยก click จาก drag ด้วย threshold 8 pixel pause เป็น wait; text ที่ตรง secret lexicon หรือ credential pattern (8+ ตัวจากสาม class) ถูก redact และแทนด้วย request_takeover Routine ภาษาธรรมชาติใช้ target ที่ bind แล้ว coordinate และ reinterpret ผ่าน computer_observe Routine มี condition, input, step, verification, scope ที่อนุญาต จาก host ที่เข้าจริง (ต้อง stop และถามก่อนออก), approval boundary และ stop เมื่อ fail

Script เก็บเป็น skill ปกติ prefix taught- พร้อม versioning, edit, sharing Run Work Computer load/list taught skill active ของ owner; replay เป็น run ปกติด้วย routine ที่ตรง หลัง run badge เพิ่มการประเมิน success/error พร้อมวันที่ใน Track record ด้วย click เดียว (ใหม่สุดด้านบน จำนวน bounded แต่ละ record เป็น version ปกติ) อย่าใส่ password จริงตอนบันทึก ให้ demo flow ถึง login, save แล้วใช้ request_takeover ตอน replay

Provider, Routing และ Data Disclosure

Route ที่รองรับ

Routeการตรวจและพฤติกรรม
Ollama localOllama พร้อม โมเดลที่ตรงประกาศ tool support
Ollama CloudRoute ชัดผ่าน Ollama; cloud suffix แสดง disclosure
Plugin completion/chatActive พร้อมโมเดลที่ตรงและ credential administrator ปัจจุบัน
Plugin Anthropicใช้ adapter message/tool Anthropic สำหรับ Work
Plugin Geminiใช้ adapter content/function-call Gemini สำหรับ Work
อื่นที่เข้ากันใช้รูปแบบ OpenAI สำหรับ message, tool และ tool choice

เก็บประเภท provider และ plugin ID บน task และทุก run ชื่อโมเดลอย่างเดียวไม่เลือก route plugin ชื่อเดียวกันไม่ยึด task ที่มี

ข้อมูลที่ Provider ได้รับ

  • system prompt ของ Work
  • workflow skill และ limit environment ปัจจุบัน
  • message ล่าสุด 30 รายการของ user/assistant สูงสุด 256 KB
  • tool definition
  • ประวัติ tool-call
  • result รวม list, file content, search, output และ error

Volume ไม่ถูก upload ทั้งหมด แต่ content ที่ tool คืนจะเป็นส่วน conversation และส่ง provider ตรวจ retention, training, pricing และเงื่อนไขก่อนงานละเอียดอ่อน

Credential อยู่ server-side และไม่ mount ใน container Work

แอปเข้ารหัส credential ไม่ได้หมายถึงเข้ารหัส task ทั้งหมด Conversation, result, output และ metadata คือ content ฐานข้อมูลปกติ file คือ file volume/PVC ปกติ ใช้ host control และ disk encryption ตาม threat model

Disclosure ของ Provider Remote

โมเดล plugin และชื่อ Ollama ที่มี :cloud หรือ -cloud ถือเป็น remote เมื่อเลือก notification ที่ปิดได้จะอธิบาย data flow และ paid call หลายครั้ง เก็บ preference ต่อ user

ทุก route ใช้ WORK_MAX_AGENT_ROUNDS ค่าเริ่มต้น 48 round ไม่มี limit 12 เฉพาะ plugin Tool budget คือ max(128, configured rounds × 8) call เมื่อหมด Libre ขอ handoff สุดท้ายที่ไม่มี tool เกี่ยวกับงาน check blocker และส่วนที่เหลือ แล้วเขียน ต้องการ input ไม่ใช่ exception หรือ completion ปลอม การทำต่อใช้ workspace เดิม หนึ่ง run ยังสร้าง request แบบเสียเงินได้หลายครั้ง

Folder ของ Host (ไม่บังคับ)

Docker ปกติใช้ named volume ทำให้โมเดลไม่เห็น file จริง Task bind กับ directory ของ host จริงได้ Kubernetes ปฏิเสธ directory นี้และใช้ PVC

WORK_HOST_WORKSPACES_ENABLED=true
WORK_HOST_WORKSPACE_ROOTS=/Users/you/Projects

WORK_HOST_WORKSPACE_ROOTS คือรายการ root คั่นด้วย : ค่าเริ่มต้นคือ home ของ user server Folder workspace ไม่บังคับ ค่าว่างรักษา isolation

Path ต้องเป็น directory สัมบูรณ์ที่มีและยังอยู่ใน root หลัง resolve symlink .ssh, .gnupg, .aws, .config, .kube, .docker, .claude, .libre-webui และ node_modules ถูกปฏิเสธเสมอ Path ที่อนุญาตถูกเก็บและแสดง

Boundary ของ Sandbox แคบลง

โมเดลอ่านและแก้ file จริง user ที่ไม่มี privilege, capability ที่ drop และ limit ไม่แยกโมเดลจาก directory อีก ปิด feature เว้นแต่จำเป็น ตั้ง root แคบ และเลือก directory ที่มี version control

Persistence และ Lifecycle

Stateการจัดเก็บอายุ
Owner, title, provider, stateฐานข้อมูล Libreจนลบ task/user
Run, error, message, activityฐานข้อมูล Libreจนลบ task
FileDocker volume หรือ K8s PVCอยู่ข้าม cancel, stop preview, restart
ระบบ root และ file ชั่วคราวContainer หรือ PodEphemeral; stop/recreate ได้
Process previewSandbox ที่รันชั่วคราว เก็บเมื่อ verify health
Draft ยังไม่ saveSession browserความสะดวกชั่วคราว

Server สร้าง task UUID และมีเพียง server กำหนด resource name ตรวจ label management/owner ก่อน reuse/delete และปฏิเสธ resource ของ task อื่น

Sandbox เตรียม on-demand File helper หยุด environment idle, command ปล่อยเมื่อเสร็จ และ preview ที่ verify แล้วอาจยึดไว้ Workspace แบบคงอยู่ mount ใหม่

Administrator กำหนด runtime policy ที่มีชื่อ: image, limit memory/CPU/PID, ขนาด Kubernetes, idle timeout, network และ toggle Work Computer (GUI + browser) กับ Allow screen takeover (กำหนด teaching ด้วย) Task ใช้ policy ที่เลือก field ว่าง inherit ค่า global และการลบ policy คืนค่าใน recreate ถัดไป Policy เปลี่ยนเฉพาะ resource/feature และลดความเข้ม mode ไม่มี privilege, root read-only, capability ที่ drop หรือ network isolation ไม่ได้

WORK_RUNTIME_IDLE_TIMEOUT_MS หยุด sandbox และปล่อย slot หากไม่มี command, terminal หรือ request preview ที่ลงลายเซ็น Workspace ถูกเก็บและ preview start ใหม่ ค่าเริ่มต้น 0 เก็บ environment จน stop ชัด

เมื่อ server startup run active ถูกทำเครื่องหมาย failed และ clear state preview Driver ดึง container/Pod managed ใน query เดียว Environment ของ task ที่รู้จักและกำลังรันถูก stop ที่ stop แล้วไม่เปลี่ยน orphan ถูกลบ Owner กำหนดด้วย label ไม่ใช่ชื่อ มี Libre instance เดียวต่อ namespace/daemon หากพิสูจน์ cleanup ไม่ได้ Work fail closed, retry ทุก 10 วินาที และ block operation mutation

เครือข่าย

ตรวจ Policy

หากไม่มี policy มีชื่อ network จะ active Administrator สร้าง policy เครือข่ายที่ปิดเป็นค่าเริ่มต้นและ author เลือกตอนสร้าง task ได้ ไม่มี toggle ต่อ task การเปลี่ยน policy ต้อง recreate environment

Docker เชื่อม task ที่มีเครือข่ายกับ bridge managed (libre-webui-work, WORK_NETWORK_NAME) ด้วย com.docker.network.bridge.enable_icc=false:

  • sandbox เชื่อมกันไม่ได้
  • ค่าเริ่มต้นเข้าถึง container deployment บน bridge ร่วมไม่ได้ รวมฐานข้อมูลหรือ Ollama ที่ยังไม่ publish

Network ชื่อเดียวกันที่ไม่มี label management ถูกปฏิเสธ

บน Kubernetes Pod ได้ network label Helm สร้าง default-deny, ingress เฉพาะ preview และ internet egress สำหรับ Pod ที่อนุญาต ยกเว้น work.networkPolicy.blockedEgressCidrs มีผลเมื่อ CNI รองรับ ดู Kubernetes

อนุญาต egress สำหรับ package, Git และ API นี่ไม่ใช่ egress firewall Code เข้าถึง:

  • service ของ host Docker
  • LAN ของ host
  • internet
  • endpoint metadata infrastructure

เครื่องมือ Policy Egress

  • WORK_RUNTIME_DNS (Docker) — ที่อยู่ IPv4/IPv6 คั่น comma และบังคับด้วย --dns; resolver filter ให้ list ชื่อ ที่อยู่ invalid ถูกปฏิเสธ/log จึง inject flag ไม่ได้
  • Firewall host หรือ upstream บน subnet คงที่ของ bridge managed
  • WORK_NETWORK_NAME สำหรับ network precreated ที่มี option เอง management label และปิด ICC

DNS ไม่จำกัด IP โดยตรง ต้องใช้ firewall เพื่อรับประกัน

อย่าถือ Work เป็นการป้องกัน exfiltration ให้ access เฉพาะ user ที่เชื่อถือได้ สำหรับ task อัตโนมัติเลือก policy offline มีชื่อ ไม่มีตัวแปร environment global เปลี่ยนค่าเริ่มต้น

Network ไม่เพิ่ม credential: SSH key, cloud credential, browser profile, home ของ host หรือ Docker socket ไม่ mount ใน task Code ยังส่ง secret ที่เขียนใน /workspace ได้

Traffic sandbox แยกจาก request โมเดล Ollama และ plugin ถูกเรียกโดย server ผ่าน route ชัดเสมอ

Boundary ความปลอดภัยของ Sandbox

Docker Container:

  • รัน non-root เป็น 1000:1000
  • ใช้ /workspace เป็น working directory
  • mount เฉพาะ volume ของ task ที่เลือก
  • ใช้ root read-only และ /tmp จำกัด
  • drop Linux capability ทั้งหมด
  • no-new-privileges;
  • ไม่ privileged และใช้ init process
  • ใช้ limit CPU, memory, process, เวลา และ output
  • ล็อก swap (--memory-swap = --memory)
  • เชื่อม network managed ไม่มี ICC หรือไม่มี network
  • publish เฉพาะ preview port บน loopback ที่กำหนด

ตรวจ property ทั้งหมดซ้ำด้วย docker inspect และ hash ใน ai.libre-webui.policy Container ที่มี policy เก่าถูกทำลายและ recreate หลัง update

Kubernetes ใช้เทียบเท่า: user ไม่มี privilege, root read-only, seccomp RuntimeDefault, ไม่มี privilege escalation, capability ที่ drop, resource ชั่วคราวจำกัด, ไม่มี ServiceAccount token และ PVC ที่ /workspace ตรวจ label และ fingerprint

Path validation ปฏิเสธ path สัมบูรณ์ traversal, backslash, NUL และความยาวเกิน Helper resolve real path และปฏิเสธ escape ผ่าน symlink Write ใช้ file ชั่วคราวและ atomic rename

มาตรการลด host exposure โดยไม่ตั้งใจ แต่ไม่ทำให้ Work เป็น VM หรือ environment วิเคราะห์ malware ที่ปลอดภัย Container ใช้ kernel host ร่วม vulnerability ของ Docker, Kubernetes, runtime, image, dependency หรือ kernel อาจข้าม boundary

Docker volume ไม่มี quota อิสระ Project อาจใช้ storage หมด ให้ติดตามการเติบโตและใช้ host limit การ enforce ขนาด PVC Kubernetes ขึ้นกับ storage provider

Checklist การ Hardening Docker

บน Kubernetes ตรวจ RBAC namespace, ความปลอดภัย Pod, storage class และ CNI NetworkPolicy enforcement ตาม คู่มือ

แอปตั้ง flag container, validate path และปกป้อง API แต่ให้ host firewall, storage quota หรือระดับ privilege daemon ไม่ได้ เป็นหน้าที่ operator

1. แยกการควบคุม Docker

Container หลักต้อง control daemon; socket คือ credential ของ control plane การ compromise แอปอาจทำให้ host compromise

docker-compose.socket-proxy.yml ไม่ให้ socket กับแอป Proxy ให้เฉพาะ containers, images, volumes, networks, exec และ info; block swarm, secrets, configs, build, commit และ system Libre ใช้ DOCKER_HOST=tcp://docker-socket-proxy:2375 โดยไม่ mount socket/group; CLI, terminal และ diagnostics ตามที่อยู่นี้ API surface เล็กลงแต่ blast radius ยังอยู่ การสร้าง container ทำให้ mount host path ได้

Boundary ที่แข็งแรงกว่าคือ VM แยกที่ไม่มี workload ไม่เกี่ยวข้อง ยิ่งแข็งแรงคือ daemon rootless แยกหรือ runtime host แยก ก่อน rollout ให้ verify file ownership, routing, cleanup และ terminal การ mount socket ปกติแบบ read-only ไม่ทำให้ API read-only

2. บล็อกการควบคุม Host จาก Sandbox

การปิด ICC ไม่ block service ของ host ตรวจ bridge และ subnet จริง:

docker network inspect libre-webui-work \
--format 'id={{.Id}} subnets={{range .IPAM.Config}}{{.Subnet}} {{end}}'
ss -lntup

Firewall คงอยู่ต้องปฏิเสธ traffic bridge ไป SSH, Docker API, ฐานข้อมูล และ admin port ทดสอบ rule ด้วย container ครั้งเดียวและ download ที่อนุญาตแล้ว persist DOCKER-USER control traffic forwarded การ access host อาจต้องใช้ rule INPUT

3. จำกัด Target Egress

Block cloud metadata, infrastructure private และ LAN client หากไม่จำเป็น รวม DNS/firewall IP โดยตรง bypass DNS; HTTP proxy ไม่พอสำหรับ connection โดยตรง ใช้ policy นอก container

สร้าง policy แยกแบบไม่มี network, registry-only และ egress เปิด Policy กำหนด network attachment ส่วน rule ภายนอกกำหนด target ที่อนุญาต

4. Storage Quota จริง

Limit CPU, memory และ PID ไม่จำกัด volume ใช้ XFS project quota, logical volume มี quota หรือ volume/PVC driver ที่ enforce ขนาด Docker local บน ext4 ไม่มี quota ที่น่าเชื่อถือจากขนาดที่ประกาศเท่านั้น

ติดตามทุก volume ai.libre-webui.managed=true และ Docker data root เตือนก่อนเต็มและ test พฤติกรรม failure UI หรือ du แค่ warning ไม่ enforce limit ระหว่าง check

5. ตรวจสอบ Policy

หลังเปลี่ยน สร้าง task ครั้งเดียวและตรวจผ่าน docker inspect: UID, root read-only, capability, no-new-privileges, memory, swap, CPU, PID, volume task เดียว และ network Container หลักควรมีเฉพาะ mount ที่คาด public ingress ต้องผ่าน proxy/tunnel ที่ยืนยันตัวตน ไม่ใช่ port Docker หรือ preview

ความปลอดภัยและการเข้าถึง Preview

Docker publish preview แบบ dynamic บน loopback ของ server; Kubernetes ใช้ IP Pod โมเดล/browser ไม่เลือก origin ใดก็ได้ Libre sign URL สำหรับ task/endpoint ที่ตรง verify process ทุก request และ proxy HTTP/WebSocket ผ่าน /api/work/previews Stop/restart revoke URL

Response ลบ credential Libre และ cookie upstream HTML จำกัดด้วย iframe sandbox/CSP ที่ให้ script, form, modal และ download แบบไม่มี same-origin การป้องกันใช้กับ tab แยกด้วย Generated code ยังไม่น่าเชื่อถือและอาจส่ง data workspace/browser URL คือ secret อายุสั้น

Browser load public origin เดียวกัน ทำให้ HTTPS remote ทำงานโดยไม่เปิด port/IP Pod และไม่ mixed content Reverse proxy ต้องรักษา WebSocket สำหรับ /api/work/previews/; Nginx ในตัวทำ

แอปหลักให้เฉพาะ origin ของตนและ Turnstile ใน frame Preview bypass Helmet policy global เพื่อส่ง body และใช้ sandbox แคบลง ปิด cross-origin embedder policy เพราะ development server แทบไม่มี header ที่ต้องการ

ตาราง Deployment

DeploymentRun/filePreview
npx libre-webui localรองรับเมื่อ Docker ติดตั้ง/เข้าถึงได้Proxy ลงลายเซ็นบน origin ของแอป
Run จาก source localข้อกำหนดเหมือนกันOrigin API development ที่ port 3001
Electronมีเงื่อนไข ใช้ backend ภายนอกโดยไม่มี runtime Work แยกProxy ลงลายเซ็นของ backend นั้น
Bare metal/VM remoteรันเมื่อ host มี DockerReverse proxy HTTP/WebSocket
Compose มาตรฐานรองรับโดยค่าเริ่มต้นบน Docker Desktop: image มี CLI, Compose mount socket และพอร์ต Work วิ่งผ่าน host.docker.internal ส่วน Docker Engine แบบเนทีฟต้องมี WORK_PREVIEW_BIND ที่ไม่เปิดสาธารณะแต่เข้าถึงได้เพิ่มด้วยpublic origin เดียวกัน
Kubernetes/Helm--set work.enabled=true: Pod/PVC ผ่าน IP Pod สำหรับ run, file, command, Git, terminal, Screen/audio Work Computer, Role namespace และ default-deny NetworkPolicies; ไม่มี socket ดู KubernetesProxy ใน cluster ไป IP Pod

Work เมื่อ Libre WebUI อยู่ใน Docker

File Compose ทั้งหมดใน repository รวม Work: image มี CLI และ mount /var/run/docker.sock Docker Desktop ใช้งานได้ด้วยค่าเริ่มต้นของการกำหนดเส้นทางที่มาพร้อมกัน ส่วน Docker Engine แบบเนทีฟต้องตั้ง WORK_PREVIEW_BIND เป็นอินเทอร์เฟซโฮสต์ที่ไม่เปิดสาธารณะแต่คอนเทนเนอร์พี่น้องเข้าถึงได้เพิ่มด้วย ตามที่อธิบายด้านล่าง

Container ของ task เป็น sibling ของ container Libre WebUI มองเห็นใน docker ps และจัดการด้วย lifecycle เดียวกัน

Socket ให้ control host เทียบเท่า root Work ไม่รันหากไม่มี ผลชัดเจน: administrator Libre WebUI ทุกคนเทียบเท่า administrator ของ Docker host ความปลอดภัย network, lifecycle, backup และ access เป็นหน้าที่ operator ลบบรรทัด socket เพื่อปิด Work feature อื่นไม่ขึ้นกับ socket

ทางเลือกคือ docker-compose.socket-proxy.yml ผ่าน DOCKER_HOST ดู การแยก control

ต้องครบสามเงื่อนไข:

  1. มี Docker CLI Image ทางการมี ส่วน image custom ต้องใช้ docker-cli หรือ WORK_DOCKER_COMMAND มิฉะนั้น: The "docker" CLI is not installed…
  2. Mount socket แล้ว มิฉะนั้น: No Docker daemon is reachable…
  3. User อยู่ group ของ socket Image รันเป็น nodejs uid 1001; socket มักเป็นของ root หรือ docker จึงใช้ Compose group_add: ['${DOCKER_GID:-0}'] ค่าเริ่มต้นเหมาะกับ Docker Desktop ส่วน Linux ต้องใช้ ID ของตน มิฉะนั้น: The Docker socket is mounted but the Libre WebUI user cannot open it…
# Read the socket's group as seen INSIDE a container. A macOS host reports a
# different value, because Docker Desktop proxies the socket through a VM.
echo "DOCKER_GID=$(docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
alpine stat -c '%g' /var/run/docker.sock)" >> .env
docker compose up -d --force-recreate

Preview port อยู่บน loopback host และเข้าผ่าน proxy ลงลายเซ็น origin เดียวสำหรับ HTTP/WebSocket ทำงานกับ HTTPS/tunnel ใช้ sandbox และ revoke URL เก่า

บน Docker ที่อยู่ publish/connect อาจต่างกัน เก็บ WORK_PREVIEW_BIND=127.0.0.1 และตั้ง WORK_DOCKER_PUBLISHED_HOST เป็นที่อยู่ host ที่เข้าถึงได้ (host.docker.internal บน Docker Desktop) โปรไฟล์ Compose ที่มาพร้อมกันตั้งทั้งสองค่าและแมปชื่อโฮสต์นี้ให้แล้ว การติดตั้งบน Linux แบบเนทีฟต้อง override WORK_PREVIEW_BIND ด้วยเกตเวย์ของ Docker bridge (หรืออินเทอร์เฟซโฮสต์อื่นที่ไม่เปิดสาธารณะแต่เข้าถึงได้ชัดเจน) mapping อย่างเดียวไม่ทำให้ loopback reachable และอย่า bind พอร์ตชั่วคราวดิบเหล่านี้กับ 0.0.0.0 เด็ดขาด

Concurrency จำกัด: WORK_MAX_ACTIVE_RUNTIMES_PER_USER 2 และ WORK_MAX_ACTIVE_RUNTIMES_GLOBAL 3 Response capability บอก busy state เพิ่มเมื่อทรัพยากรพอเท่านั้น

สำหรับ Kubernetes ใช้ work.enabled=true; chart สร้าง RBAC, namespace, policy และ Pod/PVC ตาม คู่มือ

การตั้งค่า Runtime

ตัวแปรค่าเริ่มต้นวัตถุประสงค์
WORK_RUNTIME_BACKENDdockerBackend sandbox: docker หรือ kubernetes
WORK_RUNTIME_IMAGEnode:22.22-bookworm@sha256:2d178f2785b96dfbf62a416ca2e40f50e30150b4ff3320d706f0d96e90600eb3Image sandbox ของ task
WORK_DOCKER_COMMANDdockerไฟล์ executable ของ Docker CLI
WORK_COMMAND_TIMEOUT_MS120000Command timeout ค่าเริ่มต้น
WORK_MAX_OUTPUT_CHARS50000Output ที่ capture สูงสุด
WORK_MAX_AGENT_ROUNDS48Round model/tool ต่อ run
WORK_MEMORY_LIMIT2gLimit memory ของ container
WORK_CPU_LIMIT2Limit CPU ของ container
WORK_PIDS_LIMIT256Limit process ของ container
WORK_PREVIEW_PORT4173Port แอปใน container
WORK_PREVIEW_BIND127.0.0.1Interface publish ของ host
WORK_DOCKER_PUBLISHED_HOSTเหมือน WORK_PREVIEW_BINDHost/IP สำหรับ port Work ที่ publish
WORK_COMPUTER_SCREEN_PORT6080Port WebSocket bridge ของ Screen
WORK_COMPUTER_AUDIO_PORT6081Port WebSocket bridge ของ audio
WORK_RUN_LEASE_WAIT_MS60000รอ owner ของ runtime lease ชั่วคราว
WORK_MAX_ACTIVE_RUNTIMES_GLOBAL3Task container concurrent ทั้ง instance
WORK_MAX_ACTIVE_RUNTIMES_PER_USER2Task concurrent ต่อ administrator
WORK_MAX_TASKS_GLOBAL500จำนวน task คงอยู่สูงสุดทั้ง instance
WORK_MAX_TASKS_PER_USER100จำนวน task คงอยู่สูงสุดต่อ administrator
WORK_NETWORK_NAMElibre-webui-workBridge managed สำหรับ sandbox มีเครือข่าย
WORK_RUNTIME_DNSไม่ตั้งIP resolver คั่น comma
WORK_DOCKER_SOCKETDOCKER_HOST หากเป็น unix:///tcp:// มิฉะนั้น /var/run/docker.sockDocker Engine endpoint สำหรับ terminal/diagnostics
WORK_TERMINAL_MAX_SESSIONS_PER_TASK2Terminal browser concurrent ต่อ task
WORK_TERMINAL_IDLE_TIMEOUT_MS900000Terminal idle timeout
WORK_RUNTIME_IDLE_TIMEOUT_MS0 (ปิด)หยุด sandbox idle รวม preview
WORK_K8S_NAMESPACElibre-webui-workNamespace Pod/PVC sandbox Kubernetes
WORK_K8S_STORAGE_CLASSค่าเริ่มต้น clusterStorageClass สำหรับ workspace PVC
WORK_K8S_WORKSPACE_SIZE5Giขนาด PVC workspace ต่อ task
WORK_K8S_POD_READY_TIMEOUT_MS900000รอ Pod sandbox เป็น Running
WORK_K8S_POD_GONE_TIMEOUT_MS60000รอ Pod ที่ลบหายไป

ใน production ใช้ version image หรือ digest คงที่ที่ verify แล้ว Tag mutable อาจเปลี่ยน CLI tool และ security boundary โดย Libre WebUI ไม่เปลี่ยน

Run, preview, file helper, command และ recreate sandbox ใช้ capacity accounting ร่วม Operation nested ของ task ที่นับแล้วไม่ถูกนับซ้ำ เกิน limit คืน HTTP 429

ขีดจำกัด Protocol และ UI คงที่

รายการขีดจำกัด
Message task/run ใหม่65,536 ตัวอักษรและ byte UTF-8
Model ID ตอน create/change500 ตัวอักษรและ byte UTF-8
ID provider plugin200 ตัวอักษร
Run active ต่อ task1
Text command20,000 ตัวอักษร
Timeout command ของ tool1–600 วินาที
Preview readiness15 วินาที
Read/write file2,000,000 byte text UTF-8
List directory โดยตรง1,000 รายการแรก
หน้า message200 message, 1,000,000 byte
Message เดี่ยวที่เก็บ100 KB
Context conversation ของโมเดล30 message ล่าสุด, 256 KB
Output tool ที่เก็บราว 20,000 source character และ truncation marker
Live editor highlight8,000 ตัวอักษร/400 บรรทัด
Browser formatting100,000 ตัวอักษร/4,000 บรรทัด
Output state Git2,000,000 ตัวอักษร
Output diff Git600,000 ตัวอักษร
ประวัติ Git20 commit local
Path ใน request stage หนึ่งครั้ง200
Commit message4,000 ตัวอักษร
Agent loop48 round ค่าเริ่มต้นผ่าน WORK_MAX_AGENT_ROUNDS
Tool-call budgetmax(128, configured rounds × 8) call

File API ใช้ text UTF-8 Editor ในตัวไม่ edit file binary file ใหญ่กว่า 2 MB เปิดผ่าน Work API ไม่ได้

ภาพรวม API

Endpoint ทั้งหมดอยู่ใต้ /api/work และต้องยืนยันตัวตนพร้อมสิทธิ์ Work ปัจจุบันจากฐานข้อมูล Work ค่าเริ่มต้นเฉพาะ administrator operation ปกติเปิดให้ user active ได้ การเลือก folder host และ admin endpoint สำหรับ policy/access ยังเฉพาะ administrator

MethodPathวัตถุประสงค์
GET/capabilitiesAvailability และ limit ของ environment/provider
GET/tasksList task ของ administrator ปัจจุบัน
POST/tasksสร้าง task และ run async แรก
GET/tasks/:idLoad state และ message ล่าสุด
GET/tasks/:id/messagesLoad message เก่า
PATCH/tasks/:idRename หรือเปลี่ยน route โมเดลที่ตรง
DELETE/tasks/:idลบ task และ workspace คงอยู่
POST/tasks/:id/runsStart run ถัดไป
POST/tasks/:id/messagesส่ง message ให้ agent ระหว่าง run
GET/tasks/:taskId/runs/:runId/eventsStream event SSE ที่ยืนยันตัวตน
POST/tasks/:id/cancelยกเลิก run active
GET/tasks/:id/approvalsApproval ที่รออยู่และ state Auto Review ของ task
PUT/tasks/:id/approvalsเปิด/ปิด approval ต่อ task
POST/tasks/:id/approvals/:approvalIdตัดสิน approval ที่รออยู่ (อนุญาตครั้งเดียว/เสมอ, ปฏิเสธ)
DELETE/tasks/:id/approval-rules/:ruleIdลบ rule Always-allow
GET/computer/setupState setup Work Computer สำหรับ administrator
POST/computer/setupสร้าง image GUI และ policy
POST/tasks/:id/computer/startStart session Work Computer
GET/tasks/:id/computer/controlController ปัจจุบันและ request takeover
POST/tasks/:id/computer/controlTakeover หรือต่ออายุ control
DELETE/tasks/:id/computer/controlคืน control ให้ agent
POST/tasks/:id/computer/teachเก็บ demo เป็น skill
POST/tasks/:id/computer/anchorResolve element ใต้ click
POST/computer/skills/:slug/traceเพิ่ม outcome ให้ skill
GET/tasks/:id/filesList directory workspace
GET/tasks/:id/fileRead file text
PUT/tasks/:id/fileSave file text
GET/tasks/:id/gitRead state/history Git hardened
GET/tasks/:id/git/diffRead diff local จำกัด
POST/tasks/:id/git/initInit Git local
POST/tasks/:id/git/stageStage path ชัด
POST/tasks/:id/git/commitCommit การเปลี่ยนแปลง staged
POST/tasks/:id/git/branchesสร้าง branch local
POST/tasks/:id/git/switchSwitch ไป branch สะอาด
POST/tasks/:id/preview/startStart preview managed
POST/tasks/:id/preview/stopหยุด preview managed

ตรวจ Task ID กับ owner ที่ยืนยันตัวตนเสมอ อ่าน state ของ account, role และ access policy จากฐานข้อมูลทุก request ทำให้ revocation ยังใช้แม้ JWT มี role claim เก่า

Schema update ของ task เก็บ field server networkEnabled เพื่อ compatibility ภายใน Field ไม่แสดงเป็น control Work แยก ตอน create เลือก policy มีชื่อพร้อม network state ค่าเริ่มต้นที่ต้องการ อย่าใช้ field ดิบเป็น API config แบบคงอยู่

การลบ การเปลี่ยน Account และ Backup

ลบ Task

การลบเป็น destructive โดยตั้งใจ:

  1. Server ทำเครื่องหมาย task ว่ากำลัง decommission และ block mutation ใหม่
  2. ยกเลิก run active และหยุด sandbox
  3. Libre WebUI verify label ownership ของ resource runtime
  4. ลบ Container หรือ Pod พร้อม named volume/PVC
  5. Cascade-delete task จากฐานข้อมูลพร้อม run/message
  6. Clear draft ใน browser เมื่อสำเร็จ

หาก cleanup runtime ล้มเหลว Libre WebUI เก็บ record และคืน error ให้ operator แก้ Docker/Kubernetes แล้ว retry Metadata ไม่ถูกลบเงียบจนเหลือ resource ที่ไม่ติดตาม

การหยุด run/preview ต่างจาก delete: execution หยุดแต่เก็บ volume และ conversation

ลดสิทธิ์ Administrator และลบ User

เมื่อ downgrade Libre WebUI เก็บ role revocation ก่อน ทุก request ถัดไปตรวจสิทธิ์ปัจจุบัน Server suspend task และลอง stop run/sandbox Cleanup error ไม่คืน access และรายงาน operator ให้ retry

เมื่อลบ user อื่น จะลบ resource managed ก่อน หาก cleanup ล้มเหลวเก็บ record ของ user เพื่อไม่เสีย metadata ownership

Backup Task แบบครบ

Backup Work แบบครบต้องมี:

  • ฐานข้อมูล Libre WebUI พร้อม ownership, ชื่อ resource Docker/Kubernetes, routing, run, message และ activity
  • Docker volume/Kubernetes PVC ทั้งหมดที่มี label ai.libre-webui.managed=true และมี file Work

ไม่ต้อง copy Container ephemeral และ process preview สำหรับ copy ที่สอดคล้องให้หยุด activity Work ใหม่และ server แล้วใช้ procedure snapshot storage

Restore ฐานข้อมูลและ workspace ที่ตรงกันพร้อมกัน สร้าง volume/PVC แต่ละรายการด้วยชื่อที่บันทึกตรง และ restore label ai.libre-webui.task=<task UUID> กับ ai.libre-webui.managed=true มีเพียง file จะขาด label มีเพียงฐานข้อมูลจะขาด file มีเพียง storage จะขาด ownership และชื่อ resource

หาก installation มี credential provider เข้ารหัส ให้ทำตาม procedure backup หลักสำหรับ data directory และ key

Localization และ RTL ภาษาอาหรับ

Work แปลครบ 25 ภาษา: อังกฤษ อาหรับ เบงกาลี เช็ก เดนมาร์ก เยอรมัน สเปน ฝรั่งเศส ฮินดี อินโดนีเซีย ไอซ์แลนด์ อิตาลี ญี่ปุ่น เกาหลี มาเลย์ ดัตช์ โปแลนด์ โปรตุเกส รัสเซีย สวีเดน ไทย ตุรกี ยูเครน เวียดนาม และจีน

ภาษาอาหรับตั้ง lang="ar" และ dir="rtl" ก่อน React render: sidebar/conversation ไปขวา workspace ไปซ้าย icon ทิศทาง mirror และ tab/resize ตาม RTL

Content เทคนิคที่มีผลต่อความถูกต้องยังเป็น LTR:

  • code และ highlighting
  • filesystem path
  • model ID
  • command และ log preview
  • tool output และ metadata
  • content ของ code block

Title ของ task, prompt ภาษาธรรมชาติ, error, filename และ preview command ใช้ทิศทาง text อัตโนมัติ

การแก้ปัญหา

Runtime Unavailable ด้วย npx

npx libre-webui start server บน host แต่ไม่ติดตั้ง Docker รัน docker info ด้วย OS user เดียวกัน ติดตั้ง/start Docker หรือแก้ permission แล้ว reload Work Verify Ollama พร้อมหรือ plugin active พร้อมโมเดลและ credential administrator ปัจจุบัน

Runtime Unavailable ใน Docker หรือ Kubernetes

Compose ใน repository ไม่ควรรายงาน error นี้: image มี CLI และ file mount host socket Panel บอกสาเหตุ—ขาด CLI, socket หรือ group สำหรับ group ให้ตั้ง DOCKER_GID และ recreate container ดู Work ใน Docker

บน Kubernetes ตั้ง --set work.enabled=true Libre รายงาน kubernetes ตรวจ API และ launch Pod พร้อม PVC อย่า mount runtime socket ของ node ดู Kubernetes

ไม่มีโมเดลที่เข้ากันกับ Work

สำหรับ Ollama เลือกโมเดลที่ประกาศ tools สำหรับ plugin ตรวจ:

  • ประเภท completion/chat
  • activation
  • โมเดลที่ตรงใน mapping
  • API key ของ administrator ปัจจุบัน
  • tool-call support ของโมเดล

Work ไม่ switch ไป provider อื่นเป็น fallback

ติดตั้ง Package ไม่ได้หรือ Git Remote ล้มเหลว

ตรวจว่า policy มีชื่อที่เลือกอนุญาต network ไม่มี toggle ต่อ task จากนั้นตรวจ DNS, proxy, firewall/NetworkPolicy, registry, certificate, runtime, service upstream และ command Tab Git เป็น local เท่านั้น ใช้ terminal/model สำหรับ Git remote เฉพาะ network/credential ที่อนุญาตชัด ห้าม paste token อายุยาว

Run หยุดที่ Limit ของ Agent

Budget round/call อาจหมด Work ขอ handoff สุดท้ายที่ไม่มี tool ให้ review งานและส่วนที่เหลือ ต้องการ input คือ terminal state ของ run ไม่ใช่ claim ว่าเสร็จ Start run ถัดไปหรือเพิ่ม WORK_MAX_AGENT_ROUNDS โดยตั้งใจหาก resource/cost อนุญาต

HTTP 429 ระหว่าง Run

ถึง limit runtime active หรือ task คงอยู่ รอ operation อื่น หยุด preview ที่ไม่ใช้ ลบ task เก่า หรือเพิ่ม WORK_MAX_* ที่เกี่ยวข้องหากทรัพยากรพอ

Preview ไม่พร้อม

Command ต้องรันต่อ bind 0.0.0.0 และ listen WORK_PREVIEW_PORT ภายใน 15 วินาที Field ว่างหา dev ใน package.json, index.html แบบง่าย หรือ app nested หนึ่งรายการ หากหลาย/ไม่มีให้ป้อน command ชัด เริ่มที่ /workspace ใช้ cd <app-directory> && ... สำหรับ app nested

Preview รันบน Server แต่ไม่รันใน Browser Remote

ตรวจ build proxy ลงลายเซ็นและ restart URL เก่า Reverse proxy/tunnel ต้องให้ WebSocket ที่ /api/work/previews/ Docker port ที่ publish ต้องอยู่ loopback และไม่ต้องเปิด firewall

File ยังอยู่แต่ Preview หยุด

นี่เป็น expected หลัง cancel, server restart, stop ชัด หรือ readiness check ล้มเหลว Process ชั่วคราว volume คงอยู่ เปิด task และ start preview ใหม่

File เปิดหรือ Save ไม่ได้

API รับ text UTF-8 ถึง 2 MB หาก file เปลี่ยนหลังเปิด ให้ reload ก่อน save Highlighting เป็น text ปกติเหนือ 8,000 ตัวอักษร/400 บรรทัด formatting limit 100,000 ตัวอักษร/4,000 บรรทัด และเฉพาะ type ที่ documented

Work รายงานการ Recovery Sandbox

เมื่อ startup/shutdown พิสูจน์ไม่ได้ว่า sandbox ที่รู้จัก stop แล้ว Work fail closed และ retry ทุก 10 วินาที แก้ access API Docker/Kubernetes และตรวจ server log อย่าลบแถวฐานข้อมูลจน resource มี label ถูก reconcile

ลบ Task ไม่ได้

ตรวจ runtime ว่า reachable Resource conflict ที่ไม่มี label ai.libre-webui.task ตามคาดถูกปฏิเสธโดยตั้งใจ แก้ conflict อย่างระวังแล้ว retry

สรุปความปลอดภัย

  • Work ค่าเริ่มต้นเฉพาะ administrator การเปิดทุกคนทำให้ account active ทุกบัญชีเป็น operator sandbox Folder host เฉพาะ admin
  • Server ต้อง control Docker daemon หรือ Kubernetes namespace ที่ตั้งค่า
  • Container ลด access filesystem แต่ไม่ใช่ VM
  • Task ที่ไม่มี policy offline มี egress การจำกัด target เป็นหน้าที่ operator
  • Volume Work ไม่มี disk quota อิสระ
  • Git เป็น local เท่านั้น credential remote ไม่ mount หรือรับโดย API
  • Firewall, daemon isolation, egress limit และ quota จริงให้โดย operator
  • Provider remote รับ result ที่ขอและอาจทำ paid call หลายครั้ง
  • Preview port อยู่ loopback และเข้าผ่าน URL ลงลายเซ็นที่ revoke ได้
  • Compose มาตรฐานให้ Docker; Kubernetes/Helm ให้ Pod/PVC ด้วย work.enabled=true
  • Backup ครบต้องใช้ฐานข้อมูล Libre WebUI และ volume Work

เอกสารที่เกี่ยวข้อง