กลับไปบล็อก

4 สาเหตุที่ทำให้งานเว็บของ AI Agent ไม่เสถียรและแนวทางทางวิศวกรรม

เมื่อ Agent ทำงานบนเว็บ ความล้มเหลวมักเกิดใน 4 จุด ได้แก่ การระบุตำแหน่ง element การรอและ timeout การเก็บ state และการถูกบล็อกจากฝั่ง environment การทำแต่ละขั้นให้ idempotent, retry เฉพาะความล้มเหลวที่กู้คืนได้, บันทึก state แบบถาวร และแยก environment ตามงาน ช่วยให้ success rate เสถียรขึ้นมาก

เมื่อเริ่มทำ web automation แนวคิดมักดูตรงไปตรงมา: เขียน flow แล้วให้ script ทำงาน Logic ดูเหมือนไม่มีปัญหา แต่ task ยังล้มเหลวเป็นระยะ และ state ของ account ก็มีความผิดปกติเป็นครั้งคราว ปฏิกิริยาแรกคือเช็ก code แต่เมื่อไล่ตรวจลึกลงไป มักพบว่าปัญหากระจุกอยู่ใน 4 จุด

AI Agent 网页任务不稳定的四类来源与工程做法的关键步骤与判断维度示意图

หน้าเว็บเปลี่ยน การระบุตำแหน่ง element ก็พัง

Script ส่วนใหญ่ใช้ selector เพื่อหา element เมื่อ selector ถูกเขียนแบบตายตัว การเปลี่ยนแปลงแทบทุกอย่างบน page ก็อาจทำให้ใช้ไม่ได้ เช่น button เปลี่ยน class name, ข้อความเปลี่ยนเพียงคำเดียว, section เปลี่ยนจาก server-side rendering เป็น asynchronous loading หรือ element ถูกครอบด้วย container ใหม่ ในการทำ A/B test หน้าเดียวกันอาจมี structure ต่างกันสำหรับคนละ account ได้ด้วย

อาการที่พบบ่อยคือหา element ไม่เจอ, click ผิดตำแหน่ง หรือไปกด control ที่ชื่อเหมือนกันแต่คนละตำแหน่ง ความล้มเหลวแบบนี้ไม่ใช่ network jitter ดังนั้น retry หลายครั้งก็ไม่ช่วย

แนวทางที่ใช้ได้จริงคือพึ่ง absolute path ให้น้อยลง ควรให้ความสำคัญกับ accessibility attributes, business ID ที่เสถียร หรือความสัมพันธ์แบบ relative ระหว่าง elements และเตรียม fallback selectors สำหรับ page ประเภทเดียวกัน เพื่อให้ลดระดับไปใช้ตัวสำรองอัตโนมัติเมื่อ primary selector ใช้ไม่ได้ หาก page มี iframe หรือ Shadow DOM ต้องสลับไปยัง context ที่ถูกต้องก่อน ไม่เช่นนั้นการหา element จะล้มเหลว

ตั้งช่วงเวลารอและ timeout ผิด

ถ้ารอสั้นเกินไป element อาจถูกตัดสินว่าล้มเหลวก่อน render เสร็จ ทำให้ดูเหมือน script มี bug แต่ถ้ารอนานเกินไป เวลาของ task เดียวจะยืดออกโดยไม่จำเป็น throughput ลดลง และ timeout ที่ยาวอาจบัง error จริง

Explicit wait เชื่อถือได้กว่า fixed sleep: รอ condition ที่ชัดเจน เช่น target element ปรากฏ, request ตอบกลับ หรือ loading animation หายไป Timeout budget ควรแบ่งเป็นหลายชั้น โดยมีขีดจำกัดแยกสำหรับหนึ่ง step, หนึ่ง page และทั้ง task และค่อย ๆ กระชับแต่ละชั้น แทนการใช้ค่าเดียวกันทุกจุด

ต้องแยกด้วยว่ากำลังรอให้ page ใช้งานได้ หรือรอให้ business result ถูกสร้างขึ้น กรณีแรกมักรอให้ DOM ready ก็พอ ส่วนกรณีหลังอาจต้องรอ API callback หรือการเปลี่ยนแปลงของ status text บน page หากรอสัญญาณผิด operation อาจดูเหมือนสำเร็จ ทั้งที่ data ยังไม่ได้ถูกเขียนจริง

งานหลายขั้นตอนคืบหน้าไปครึ่งทางแล้ว progress หาย

Task อย่าง registration, ordering และ publishing อาจมีมากกว่าสิบ steps ได้ง่าย หาก process ออกจากการทำงานกลางทางเพราะ timeout, browser crash หรือ host restart และเก็บ state ไว้แค่ใน memory การรันครั้งถัดไปต้องเริ่มใหม่ตั้งแต่ต้น หรือ submit step ก่อนหน้าซ้ำอีกครั้ง

ผลของ duplicate execution อาจตรวจหายากกว่าความล้มเหลวธรรมดา เพราะ operation เดียวกันถูกทำสองครั้ง, upstream system มี record เพิ่ม และหาต้นตอได้ยาก

วิธีแก้คือให้แต่ละ step มี persistence point เมื่อจบแต่ละขั้น ให้เขียน progress ไปยังพื้นที่ที่เก็บแบบถาวรพร้อม unique identifier ของ task จากนั้นหลัง restart ให้ทำต่อจากจุดล่าสุดที่สำเร็จ ไม่จำเป็นต้องใช้ framework ซับซ้อน แค่ file หนึ่งไฟล์หรือ state record หนึ่งรายการก็พอ

ถูกบล็อกจากฝั่ง environment แต่ดูเหมือน code error

ปัญหา 3 ประเภทแรกเกิดภายใน task แต่อีกประเภทมาจาก environment เว็บไซต์อาจประเมิน browser characteristics, access behavior และ network origin ร่วมกันเพื่อดูแหล่งที่มาของ traffic หากมองว่าน่าสงสัย อาจส่ง verification page, content ว่าง หรือ timeout ตรง ๆ จาก task logs แล้วแทบไม่ต่างจาก execution error

สาเหตุที่พบบ่อย ได้แก่:

  • ตำแหน่งของ egress IP, time zone และ language ไม่สอดคล้องกัน
  • ทุก task ส่ง requests จาก browser environment เดียวกัน ทำให้ request density ต่อหน่วยเวลาสูงกว่าผู้ใช้จริงอย่างชัดเจน
  • Environment เปลี่ยนบ่อย หรือ account login ใหม่ซ้ำ ๆ

4 สิ่งที่ช่วยเพิ่ม success rate

  1. ทำทุก step ให้ idempotent ก่อน execute ให้ตรวจว่า prerequisite ถูกทำครบแล้วหรือยัง เพื่อให้การทำ action ซ้ำไม่สร้าง side effect เพิ่ม Read operations เป็น idempotent โดยธรรมชาติ ส่วน write operations ต้องมี unique identifier หรือ deduplication key ป้องกัน
  2. แยกประเภทของ failure แบบชั่วคราว เช่น element ยัง render ไม่เสร็จ, network jitter หรือ API ตอบ 5xx สามารถ retry แบบ backoff ได้ แต่ failure แบบกำหนดแน่นอน เช่น account ถูกจำกัด, parameter ไม่ถูกต้อง หรือไม่มี target resource ต่อให้ retry กี่ครั้งก็เหมือนเดิม ควร mark ว่าจบเพื่อไม่ให้กิน concurrency capacity ต่อไป
  3. Persist state เป็นระยะ เก็บ progress, intermediate outputs และ current step ไว้แบบถาวร เพื่อให้หลัง task restart ทำต่อจากจุดเดิมแทนที่จะเริ่มจาก step แรก
  4. แยก runtime environment ตาม task แต่ละ account หรือ task ควรมี browser environment แยกกัน ไม่แชร์ Cookies และ local storage, fingerprint characteristics มีความแตกต่างอย่างสมเหตุสมผล และ time zone กับ language สอดคล้องกับ region ของ egress IP

ข้อ 4 สำคัญเป็นพิเศษเมื่อ scale ของ task ใหญ่ขึ้น เมื่อมี task หลายสิบหรือหลายร้อยรายการทำงานพร้อมกัน environment layer จะกำหนดเพดานของ stability และกำหนดด้วยว่าหากเกิดปัญหา ผลกระทบจะกว้างแค่ไหน ในสถานการณ์แบบนี้ PurpleMark ให้ความสามารถสร้าง isolated environments ตามต้องการและ reclaim เป็น batch โดยแต่ละ account มี environment ของตัวเอง จึงไม่เกิดการปนเปื้อน state ระหว่าง task

เนื้อหานี้มีไว้เพื่อการวิจัยทางเทคนิคและแบ่งปันแนวทางการพัฒนาเท่านั้น โปรดใช้เทคโนโลยีที่เกี่ยวข้องอย่างถูกกฎหมายและเป็นไปตามข้อกำหนด รวมถึงปฏิบัติตาม terms of service ของแพลตฟอร์มเป้าหมาย