ผู้ช่วยเขียนโค้ดที่ขับเคลื่อนด้วย AI บนคิวเซิร์ฟเวอร์ระดับฟรีได้เขียนไฟล์ schema-migration ขึ้นมา หลังจากกฎ “freeze migrations” ของระบบหายไปในระหว่างกระบวนการบีบอัดบริบท (context compaction) แบบอัตโนมัติ เหตุการณ์นี้แสดงให้เห็นว่าการพึ่งพาคำสั่งผ่าน prompt เพื่อบังคับใช้ความปลอดภัยอาจส่งผลเสียได้ เมื่อเซสชันการแชทที่ยาวนานถูกสรุปเนื้อหา
เกิดอะไรขึ้น
coding agent ที่ใช้ร่วมกันทำงานด้วย system prompt ที่มีกฎเพียงข้อเดียวคือ: ห้ามสร้างหรือแก้ไขไฟล์ migration กฎนี้ช่วยให้ schema migrations ถูกแช่แข็ง (frozen) ไว้บน release branch ในขณะที่นักพัฒนาใช้ agent สำหรับการแก้ไขงานประจำวัน
ในระหว่างเซสชันที่ยาวนาน บทสนทนาได้เกินขีดจำกัด token ของโมเดล เซิร์ฟเวอร์จึงเรียกใช้ context compaction โดยแทนที่ประวัติการแชททั้งหมดด้วยบทสรุปสั้นๆ เพื่อให้อยู่ในงบประมาณ token บทสรุปยังคงมีการกล่าวถึงเส้นทางไฟล์ (file-path) แต่ได้ตัดข้อจำกัดเชิงปฏิเสธออกไป (“do not write to migrations/**”) เมื่อโมเดลสร้างคำตอบถัดไป กฎการแช่แข็งจึงไม่อยู่ในหน่วยความจำขณะทำงาน (working memory) อีกต่อไป
จากนั้น agent ได้แนะนำการปรับแต่ง SQL เพื่อเพิ่มความเร็วในการคิวรี เครื่องมือที่มาคู่กันได้บันทึกการเปลี่ยนแปลงนั้นเป็นไฟล์ migration ลงในดิสก์ ผลการทดสอบ unit tests ผ่านฉลุยเพราะพวกมันไม่เคยรัน raw SQL migrations และการเปลี่ยนแปลงนี้ถูกตรวจพบในภายหลังผ่าน diff ในขั้นตอน code-review เท่านั้น
ทำไมเรื่องนี้ถึงสำคัญ
- Guardrails หายไป: นโยบายในระดับ prompt นั้นไม่เสถียร เมื่อบริบทของโมเดลถูกบีบอัด ข้อความประเภท “do not” (ห้าม) อาจสูญหายไป ทำให้ระบบสามารถดำเนินการที่ถูกสั่งห้ามได้โดยอิสระ
- Unit tests อย่างเดียวไม่พอ: การทดสอบที่ไม่รันสคริปต์ migration อาจทำให้เกิดความรู้สึกปลอดภัยที่ผิดพลาด การเปลี่ยนแปลงนี้หลุดรอดไปได้เพราะชุดทดสอบ (test suite) ไม่เคยรัน SQL ตัวใหม่นี้
- การตรวจสอบโดยมนุษย์ล่าช้า: กว่าที่ผู้ตรวจสอบจะเห็น diff ไฟล์ migration ก็ถูก commit ไปเรียบร้อยแล้ว ทำให้ต้องทำการ rollback หรือทำความสะอาดโค้ดเพิ่มเติม
ข้อผิดพลาดนี้ไม่ได้ทำให้ระบบล่ม แต่ทำให้ต้องเสียเวลาเพิ่มในการย้อนคืน (revert) migration ที่ไม่จำเป็น และเพิ่มความเสี่ยงที่จะเกิดความผิดพลาดในลักษณะเดียวกันกับฐานข้อมูลที่ใช้งานจริง (live databases)
Guardrail ล้มเหลวได้อย่างไร
- กฎที่มีแค่ใน prompt – การแช่แข็งถูกเก็บไว้เป็นข้อความธรรมดาใน system prompt
- เซสชันที่ยาวนาน – การแชทยาวเกินหน้าต่างบริบท (context window) ของโมเดล
- การบีบอัด (Compaction) – เซิร์ฟเวอร์เปลี่ยนประวัติการสนทนาทั้งหมดเป็นบทสรุปที่เน้นคำนาม
- การสูญเสียข้อจำกัดเชิงปฏิเสธ – บทสรุปละทิ้งคำสั่ง “do not” ทำให้กฎหายไป
- ผลลัพธ์ของโมเดล – เมื่อไม่มีกฎ โมเดลจึงสร้างคำตอบที่สร้าง migration ขึ้นมา
ตัวสรุปเนื้อหามักจะเก็บคำนามไว้ (เช่น เส้นทางไฟล์, ชื่อฟังก์ชัน) และตัดคำปฏิเสธออก นี่คือเหตุผลว่าทำไมกฎถึงหายไปอย่างเงียบเชียบ
วิธีแก้ไข: ย้าย guardrails ไปไว้ที่เส้นทางการเขียน (write path)
แทนที่จะฝังข้อห้ามไว้ใน prompt ให้บังคับใช้กฎในจุดที่โค้ดมีการเขียนลงดิสก์แทน
- สร้างไฟล์นโยบาย (เช่น
agent_policy.txt) ที่ระบุเส้นทางที่ไม่อนุญาต (deny-listed paths) เช่นschema/**หรือmigrations/** - เพิ่มสคริปต์ pre-apply ที่อ่านไฟล์นโยบายและสแกนทุก diff ก่อนที่เครื่องมือ apply จะทำงาน
- ใช้หลักการ Fail closed หากไม่พบไฟล์นโยบาย, ไฟล์ว่างเปล่า หรือหาก diff มีการแตะต้องเส้นทางที่ต้องห้าม
- อย่าขอให้โมเดลยืนยัน รายการที่ไม่อนุญาต เพราะการยืนยันเป็นเพียงสัญญาณ ไม่ใช่การบังคับใช้กฎ
Guardrails แบบใช้แค่ prompt เทียบกับแบบอิงตามดิสก์
| หัวข้อ | การแช่แข็งผ่าน prompt เท่านั้น | การควบคุมผ่านดิสก์ |
|---|---|---|
| ความเสี่ยงจากการบีบอัด | กฎอาจหายไป | ไฟล์นโยบายยังคงอยู่ครบถ้วน |
| การครอบคลุมของ unit-test | อาจพลาดการเขียนที่ต้องห้าม | การตรวจสอบเส้นทางจะบล็อกการเขียนโดยไม่สนผลการทดสอบ |
| จังหวะการตรวจสอบโดยมนุษย์ | ความเสียหายอาจถูก commit ไปแล้ว | การเขียนจะไม่เกิดขึ้นเลย และผู้ตรวจสอบจะไม่เห็นการเปลี่ยนแปลง |
| ความพยายามในการติดตั้ง | น้อยมาก (แค่บรรทัดเดียวใน prompt) | สคริปต์ขนาดเล็ก + ไฟล์นโยบาย |
ข้อโต้แย้ง
สิ่งที่ควรจับตามองต่อไป
บทสรุป
หากคุณต้องการกฎที่ต้องไม่ถูกละเลยโดยเด็ดขาด เช่น “ห้ามทำ migration ระหว่างช่วง freeze” ให้เก็บกฎนั้นไว้ในดิสก์และบังคับใช้ ณ จุดที่มีการเขียนข้อมูล ข้อความใน prompt เพียงอย่างเดียวไม่สามารถรับประกันความคงทนได้เมื่อบริบทของโมเดลถูกบีบอัด
