สิ่งที่น่ากังวลที่สุดในงาน AI ที่ใช้เวลานานไม่จำเป็นต้องเป็นความล้มเหลว แต่คือ ความเงียบ
คนอาจทำงานบ้าน ไปซื้อของ กินข้าว แล้วกลับมาเห็น AI ยังขึ้นว่า “กำลังทำงาน” ซึ่งมีได้สองกรณีที่ต่างกันมาก:
- มันกำลังรันชุดทดสอบขนาดใหญ่อย่างจริงจัง
- มันค้างไปหลายชั่วโมงแล้ว
ตัวหมุนโหลดแยกสองกรณีนี้ไม่ได้ และการไม่มี commit ก็ไม่ได้แปลว่าหยุด เพราะการทดสอบ การค้นคว้า การเปรียบเทียบ การสร้างผลลัพธ์ หรือการรอระบบภายนอกอาจไม่มี artefact ใหม่อยู่พักใหญ่ได้ตามปกติ
ดังนั้น AI ที่ทำงานยาวจึงต้องมีสิ่งหนึ่งนอกจากความฉลาด นั่นคือ observability หรือความสามารถในการมองเห็นสถานะ
1. ข้อสรุป――ถ้างานอาจกินเวลานาน ควรเปิดเผยว่า “ตอนนี้อยู่ตรงไหน”
Agent ที่ทำงานยาวไม่ควรรายงานเฉพาะตอนจบ สถานะระหว่างทางก็ควรอ่านได้
ไม่จำเป็นต้องบอกทุกนาทีว่า “ยังมีชีวิตอยู่” แต่ควรตอบได้ว่า:
- ตอนนี้กำลังทำอะไร
- อะไรเสร็จแล้ว
- อะไรยังเหลือ
- กำลังทดสอบหรือไม่
- มี blocker หรือไม่
- ยืนยันการทำงานล่าสุดเมื่อไร
- มีการเปลี่ยนแปลงจริงล่าสุดเมื่อไร
ตัวอย่างการตั้งค่าเชิงปฏิบัติแบบหนึ่งคือ หากไม่มีผลลัพธ์ที่มองเห็นประมาณ 10 นาที ให้ update Heartbeat และถ้า Heartbeat เก่ากว่า 20 นาที ให้ตีความเป็น STALE_UNKNOWN ไม่ใช่ “หยุดแล้ว”
ความเงียบควรหมายถึง “ยังไม่รู้” ก่อนจะหมายถึง “ล้มเหลว”
2. ทำไมดูแค่ประวัติ commit ถึงไม่พอ
Git commit เหมาะมากสำหรับเป็นหลักฐานของ การเปลี่ยนแปลงจริง แต่ไม่ดีพอถ้าจะใช้เป็นหลักฐานเดียวของ การยังทำงานอยู่ตอนนี้
Regression test หนึ่งชั่วโมงอาจทำงานปกติโดยไม่มี commit เลย ในทางกลับกัน การ commit ไฟล์ Heartbeat ไร้สาระทุก 10 นาทีทำให้ history รกโดยไม่ได้ช่วยมาก
จึงควรแยก:
Heartbeat = สถานะปัจจุบัน Material change = หลักฐานว่า code, contract, artefact หรือการยืนยันเปลี่ยนจริง
เมื่อแยก lastHeartbeatAt กับ lastMaterialChangeAt เราจะเข้าใจสถานะแบบ “30 นาทีไม่มี commit แต่ 5 นาทีที่แล้ว Heartbeat ยังเป็น TESTING” ได้ทันที
เป้าหมายไม่ใช่มี commit เยอะขึ้น แต่คือทำให้ความเงียบอ่านความหมายได้
3. อย่างน้อยควรบันทึกอะไรบ้าง?
สำหรับ run ยาว ข้อมูลเหล่านี้มีประโยชน์มาก
runIdstate: RUNNING / BLOCKED / COMPLETED / STALE_UNKNOWN เป็นต้นphase: READING / IMPLEMENTING / TESTING / VERIFYING เป็นต้นworkingOnstartedAtlastHeartbeatAtlastMaterialChangeAtbranch / baseSha / headSha / PRcompletedMilestones / remainingMilestonesblockerstestsnextCheckpoint
เมื่อมีข้อมูลนี้ งานหกชั่วโมงจะไม่ใช่ “กล่องดำหกชั่วโมง” แต่จะอ่านได้ว่า:
IMPLEMENTING → TESTING → INTEGRATING → VERIFYING
กล่องดำที่ฉลาดมากก็ยังเป็นกล่องดำ และนานเข้า คนก็เริ่มกังวล
4. ช่วง testing ยิ่งต้องมี Heartbeat
การทดสอบนาน ๆ ดูจากข้างนอกแทบไม่ต่างจาก Agent ที่ค้าง
ก่อนเริ่มทดสอบยาว ควรบันทึก
phase = TESTING- ชื่อชุดทดสอบ
- ขอบเขต
- ตัวเลขจริงอย่าง
84 / 127หากมีจำนวนรวมตายตัว - มี failure แล้วหรือยัง
อย่าใช้เปอร์เซ็นต์เดา ๆ เช่น “เสร็จ 82%” สำหรับงานออกแบบหรือ debugging เพราะไม่มีใครรู้จริงว่า 18% ที่เหลือคืออะไร
เปอร์เซ็นต์มีความหมายเมื่อส่วนหารตายตัวเท่านั้น:
- 84 / 127 tests
- 3 / 5 acceptance gates
“implementation เสร็จ 82%” คือเวอร์ชัน AI ของคำว่า “ใกล้ถึงแล้ว” จากคนที่อาจยังไม่ออกจากบ้าน
5. อ่านคำถาม “หยุดหรือยัง?” แบบเป็นขั้น
ตัวอย่าง policy เชิงปฏิบัติสามารถแบ่งอายุ Heartbeat ได้ดังนี้
| อายุ Heartbeat | การตีความ |
|---|---|
| 0–10 นาที | CURRENT |
| 10–20 นาที | HEARTBEAT_OVERDUE |
| มากกว่า 20 นาที | STALE_UNKNOWN |
STALE_UNKNOWN ไม่ใช่ FAILED
จากนั้นตรวจตามลำดับ:
- บันทึกความคืบหน้าปัจจุบัน
- Check / Status
- branch / PR
- commit ล่าสุด
- ค่อยอนุมานเป็นอย่างสุดท้าย
ถ้า Heartbeat เก่าแต่หลังจากนั้นมี PR หรือ commit ใหม่ มักแปลว่า Agent ยังทำงานต่อ เพียงลืม update สถานะ
AI ก็มีเหตุการณ์แบบ ทำงานเสร็จแต่ลืมกรอก timesheet ได้เหมือนกัน
6. สิ่งที่ไม่ควรทำในการจัดการความคืบหน้า
อย่า commit Heartbeat-only ลง main
จะทำให้ history รก เพิ่ม conflict และอาจ trigger CI/deploy โดยไม่จำเป็น ใช้ surface ที่แก้ทับได้ เช่น Issue comment, Check, Status หรือพื้นที่ ops ที่ไม่ใช่ production ดีกว่า
อย่าสร้าง comment ใหม่ทุก Heartbeat
หนึ่ง run ต่อหนึ่ง record ที่แก้ไขได้อ่านง่ายกว่า ถ้ามี comment ใหม่ทุก 10 นาที สุดท้ายการดูความคืบหน้าจะกลายเป็นงานโบราณคดี
อย่าตีความความเงียบเป็น failure ทันที
ถ้าเพียง Heartbeat เก่า ให้ใช้ STALE_UNKNOWN และใช้สถานะ failure เมื่อมีหลักฐานยืนยันจริง
อย่าเขียน secret ลง log
ห้าม API key, token, password, private URL, raw private chat, ข้อมูลส่วนบุคคล หรือไฟล์ลับ
อย่าหยุดงานที่ปลอดภัยเพียงเพราะช่อง observability พัง
ถ้า progress API ใช้ไม่ได้ ให้ fallback ไป sink อื่น และทำงานอิสระที่ปลอดภัยต่อไป
7. Template ใช้งานจริง
State: RUNNING
Phase: TESTING
Run ID: agent-20260916-long-task
Started: 10:00
Last heartbeat: 14:05
Last material change: 13:42
Branch: feat/long-task
Head SHA: abc1234
PR: #123
Working on:
- regression tests
Completed:
- runtime implementation
- contract update
Remaining:
- regression completion
- merge verification
- production readback
Blockers:
- none
Tests:
- 84 / 127 passed so far
- no failure observed
Next checkpoint:
- finish regression, then integration
เพียงเท่านี้ “มันหยุดหรือยัง?” ก็เปลี่ยนเป็น “โอเค กำลังทดสอบอยู่”
จุดประสงค์ของการแสดงความคืบหน้าไม่ใช่เพื่อเร่ง AI แต่เพื่อป้องกันไม่ให้คน restart, interrupt หรือส่งคำสั่งซ้ำเพราะไม่รู้สถานะ
8. สรุป――ออกแบบ “ความฉลาด” และ “การมองเห็นสถานะ” แยกจากกัน
สำหรับ AI ที่ทำงานยาว ต้องแยกให้ชัดว่า
- ไม่มี commit ≠ หยุด
- มี Heartbeat ≠ มีความคืบหน้าจริง
- Heartbeat เก่า ≠ ล้มเหลว
- blocker หนึ่งจุด ≠ ทั้งระบบหยุด
- เงียบระหว่าง test ≠ หลับ
ถ้า AI ทำงานได้หกชั่วโมง คนไม่ควรต้องเฝ้าจอหกชั่วโมง
การออกแบบที่ดีกว่าคือ กลับมาดูเมื่อไรก็รู้ทันทีว่าตอนนี้อยู่ขั้นไหน
Agent ระยะยาวในอุดมคติไม่ใช่ Agent ที่พูดตลอดเวลา
มันทำงานเงียบ ๆ แต่พอเปิดดู เรารู้ทันทีว่ามันไปถึงไหนแล้ว

