- ในผลิตภัณฑ์ประเภท เอเจนต์ที่ทำงานระยะยาว นั้น prompt caching คือเทคโนโลยีหลักที่ช่วยนำการประมวลผลจากรอบก่อนหน้ากลับมาใช้ซ้ำ เพื่อลดทั้งความหน่วงและต้นทุนได้อย่างมาก และสถาปัตยกรรมทั้งหมดของ Claude Code ก็ถูกออกแบบโดยยึดสิ่งนี้เป็นศูนย์กลาง
- แคชทำงานด้วยวิธี การจับคู่ prefix ดังนั้นการออกแบบลำดับโดยวางเนื้อหาแบบคงที่ไว้ด้านหน้า และเนื้อหาแบบไดนามิกไว้ด้านหลัง จึงเป็นตัวชี้ขาดทั้งต้นทุนและประสิทธิภาพ
- หาก เปลี่ยนเครื่องมือหรือโมเดลระหว่างเซสชัน แคชจะถูกทำให้ใช้ไม่ได้ ดังนั้นจึงจำเป็นต้องใช้ออกแบบเลี่ยงด้วยสตับแบบเบาและเครื่องมือสำหรับสลับสถานะแทนการลบเครื่องมือ
- แม้แต่งาน compaction (สรุปย่อเพื่อลดขนาด) ที่ทำเมื่อเกิน context window ก็ต้องแชร์ cache prefix ของบทสนทนาแม่ เพื่อป้องกันไม่ให้ต้นทุนพุ่งสูง
- ต้อง มอนิเตอร์อัตรา cache hit เหมือน uptime และแม้ cache miss เพียงไม่กี่เปอร์เซ็นต์ก็ส่งผลรุนแรงต่อทั้งต้นทุนและความหน่วง จึงควร ปฏิบัติต่อมันเหมือน incident
- “Cache Rules Everything Around Me” ใช้ได้กับเอเจนต์เช่นกัน
- prompt caching คือสิ่งที่ทำให้ผลิตภัณฑ์เอเจนต์ที่ทำงานยาวนานอย่าง Claude Code เป็นไปได้
- ช่วยนำการคำนวณจากรอบก่อนหน้ากลับมาใช้ใหม่ จึงลด latency และ cost ได้อย่างมาก
หลักการทำงานของ prompt caching และการจัดวาง system prompt
- prompt caching ทำงานแบบ การจับคู่ prefix โดย API จะทำแคชทุกอย่างตั้งแต่ต้นคำขอไปจนถึงแต่ละจุดหยุด
cache_control
- หัวใจสำคัญคือการ ทำให้ shared prefix ระหว่างคำขอมีมากที่สุด ซึ่งทำได้โดย วางเนื้อหาแบบคงที่ก่อน และเนื้อหาแบบไดนามิกทีหลัง
- ลำดับการจัดวางของ Claude Code:
- system prompt แบบคงที่ และเครื่องมือ (แคชแบบทั่วทั้งระบบ)
- Claude.MD (แคชภายในโปรเจกต์)
- session context (แคชภายในเซสชัน)
- ข้อความบทสนทนา
- ลำดับนี้เปราะบางอย่างน่าประหลาด และอาจทำให้แคชใช้ไม่ได้จากกรณีอย่างเช่น
การแทรก timestamp แบบละเอียด ลงใน system prompt แบบคงที่,
การสลับลำดับเครื่องมือแบบไม่กำหนดแน่นอน,
การอัปเดตพารามิเตอร์ของเครื่องมือ
กลยุทธ์การอัปเดตด้วย system message
- มีสถานการณ์ที่ข้อมูลในพรอมป์ตล้าสมัยได้ เช่น ข้อมูลเวลาเปลี่ยน หรือผู้ใช้แก้ไขไฟล์แล้ว
- หาก อัปเดตพรอมป์ตโดยตรง จะนำไปสู่ cache miss และอาจเพิ่มค่าใช้จ่ายให้ผู้ใช้
- ทางเลือกคือ ส่งข้อมูลผ่านข้อความในเทิร์นถัดไป
- Claude Code จะแทรกข้อมูลอัปเดตใน user message ถัดไปหรือผลลัพธ์ของ tool ด้วยแท็ก
<system-reminder>
- ตัวอย่างเช่น ส่งข้อมูลอัปเดตเวลาอย่าง “ตอนนี้เป็นวันพุธแล้ว”
- หากใช้ system messages ในลักษณะนี้ ก็จะรักษาแคชไว้ได้
เหตุผลที่ไม่ควรเปลี่ยนโมเดลกลางเซสชัน
- prompt cache นั้น เป็นของเฉพาะแต่ละโมเดล ดังนั้นการคำนวณต้นทุนของแคชอาจไม่เป็นไปตามที่คาด
- ตัวอย่าง: ในบทสนทนา 100k token บน Opus หากสลับไปใช้ Haiku เพื่อถามคำถามง่าย ๆ, ต้องสร้างแคชของ Haiku ใหม่ทั้งหมดตั้งแต่ต้น ทำให้ต้นทุนสูงกว่าการให้ Opus ตอบต่อเสียอีก
- หากจำเป็นต้องสลับโมเดล วิธีที่ดีที่สุดคือใช้แนวทางแบบ sub-agent โดยให้ Opus เตรียมข้อความ "handoff" ส่งต่อไปยังอีกโมเดลหนึ่ง
- Explore agent ของ Claude Code ก็ใช้วิธีนี้เมื่อทำงานกับ Haiku
ห้ามเพิ่มหรือลบเครื่องมือระหว่างเซสชัน
- การเปลี่ยนชุดเครื่องมือเป็นหนึ่งใน สาเหตุที่พบบ่อยที่สุด ของการทำให้แคชใช้ไม่ได้
- เพราะเครื่องมือเป็นส่วนหนึ่งของ prefix ที่ถูกแคชไว้ ดังนั้นการเพิ่มหรือลบเครื่องมือเพียงหนึ่งรายการก็จะ ทำให้แคชของทั้งบทสนทนาใช้ไม่ได้
-
Plan Mode — การออกแบบที่ยึดแคชเป็นศูนย์กลาง
- แนวทางตามสัญชาตญาณ: เมื่อผู้ใช้เข้า plan mode ก็ เหลือไว้เฉพาะเครื่องมือแบบอ่านอย่างเดียว → ทำลายแคช
- การออกแบบจริง: ใส่เครื่องมือทั้งหมดไว้ในทุกคำขอเสมอ และ ทำ EnterPlanMode กับ ExitPlanMode ให้เป็นเครื่องมือ
- เมื่อเข้า plan mode จะส่งคำสั่งผ่าน system message ว่าให้สำรวจเฉพาะโค้ดเบส ห้ามแก้ไขไฟล์ และเมื่อเสร็จแล้วให้เรียก ExitPlanMode
- นิยามของเครื่องมือจะไม่เปลี่ยนเลย
- ข้อดีเพิ่มเติม: เพราะ EnterPlanMode เป็นเครื่องมือที่โมเดลเรียกใช้เองได้ จึงสามารถ เข้าสู่ plan mode โดยอัตโนมัติ เมื่อพบปัญหาที่ยาก โดยไม่ทำลายแคช
-
Tool Search — โหลดแบบหน่วงแทนการลบ
- Claude Code สามารถโหลด เครื่องมือ MCP ได้หลายสิบรายการ ถ้าใส่ทั้งหมดก็มีต้นทุนสูง แต่ถ้าลบออกก็ทำลายแคช
- วิธีแก้คือใช้แบบ defer_loading โดยแทนที่จะลบเครื่องมือ จะส่งสตับขนาดเบาที่มีเพียงชื่อและ
defer_loading: true
- หากโมเดลต้องใช้ จึงค่อยโหลด schema เต็มผ่าน เครื่องมือ ToolSearch
- เนื่องจากสตับเดิมจะอยู่ในลำดับเดิมเสมอ จึงรักษา cached prefix ให้คงที่ได้
- ฟีเจอร์ tool search ของ API ช่วยทำให้รูปแบบนี้ง่ายขึ้นได้
Context Forking — Compaction
- เมื่อเกิน context window จะทำ compaction โดยสรุปบทสนทนาแล้วเริ่มเซสชันใหม่
- หากใช้การออกแบบตามสัญชาตญาณ (สร้างสรุปด้วย API call แยกต่างหาก โดยไม่มี system prompt และเครื่องมือชุดเดิม) จะทำให้ ไม่ตรงกับ cache prefix ของบทสนทนาหลักเลย และต้องจ่ายต้นทุนเต็มสำหรับ input token ทั้งหมด
-
โซลูชัน Cache-Safe Forking
- ตอนทำ compaction ให้ใช้ system prompt, user context, system context และนิยามของเครื่องมือชุดเดียวกัน กับบทสนทนาแม่
- วางข้อความบทสนทนาของบทสนทนาแม่ไว้ด้านหน้า แล้วเพิ่มพรอมป์ตสำหรับ compaction เป็น user message ใหม่ที่ท้ายสุด
- ในมุมมองของ API คำขอนี้จึงดูเกือบเหมือนกับคำขอสุดท้ายของบทสนทนาแม่ ทำให้ นำ cached prefix กลับมาใช้ได้ และ token ใหม่มีเพียงพรอมป์ตสำหรับ compaction เท่านั้น
- ต้องกัน "compaction buffer" ไว้ใน context window สำหรับข้อความ compact และ token ของผลลัพธ์สรุป
- จากแพตเทิร์นนี้ Anthropic จึง ฝังความสามารถ compaction ไว้ใน API โดยตรง เพื่อให้นักพัฒนานำไปใช้ได้ง่าย
สรุปบทเรียนสำคัญ
- prompt caching คือการจับคู่ prefix และหากมีการเปลี่ยนแปลงที่ตำแหน่งใดใน prefix แคชทั้งหมดหลังจากนั้นจะใช้ไม่ได้ → จึงต้องออกแบบทั้งระบบโดยยึดข้อจำกัดนี้เป็นหลัก
- แทนที่จะเปลี่ยน system prompt ควรใช้วิธี แทรก system message ระหว่างบทสนทนา เพื่อรักษาแคช
- อย่าเปลี่ยนเครื่องมือหรือโมเดลกลางบทสนทนา → ให้โมเดลสถานะเป็นเครื่องมือ และใช้การโหลดแบบหน่วงแทนการลบเครื่องมือ
- ต้อง มอนิเตอร์อัตรา cache hit เหมือน uptime เพราะแม้ cache miss เพียงไม่กี่เปอร์เซ็นต์ก็ส่งผลอย่างมากต่อต้นทุนและความหน่วง
- งาน fork ต่าง ๆ (compaction, summary, การรันสกิล) ต้อง แชร์ prefix ของต้นทาง จึงจะเกิด cache hit ได้
- หากกำลังสร้างเอเจนต์ ควร ออกแบบโดยยึด prompt caching เป็นศูนย์กลางตั้งแต่วันแรก
5 ความคิดเห็น
หัวใจสำคัญคือการเปลี่ยนจาก prompt engineering ไปเป็น context engineering และในทางปฏิบัติดูเหมือนว่า “การแยกความรับผิดชอบ” คือคำตอบ
หากจัดการ persona, กฎพฤติกรรม และ memory แยกกันคนละไฟล์ ก็จะช่วยลด context rot ได้อย่างมีประสิทธิภาพ เพราะการโหลดเฉพาะไฟล์ที่จำเป็น แทนที่จะใช้ prompt แบบ monolithic นั้นเอื้อต่อ attention budget มากกว่ามาก ดังนั้น OpenClaw (หรือเฟรมเวิร์กที่คล้ายกัน) จึงน่าจะจัดการ persona (SOUL.md), กฎพฤติกรรม (AGENTS.md) และ memory (MEMORY.md) แยกจากกัน
อ้อ อย่างนี้นี่เอง ราคาต่อโทเค็นของ Opus ถึงได้แพงขนาดนั้น
สงสัยเหมือนกันว่ามีรีวิวที่พูดถึงความแตกต่างของการจัดการคอนเท็กซ์ระหว่าง Antigravity กับ Claude Code ไหม
ถึงจะเป็นโมเดล Opus เหมือนกัน แต่ก็น่าจะต่างกันชัดเจน :)
เป็นบทความที่มีประโยชน์มากจริง ๆ ครับ
ผู้อ่านตัวจริง:
คนที่สร้าง “เอเจนต์ที่รันเป็นเวลานาน” แบบ Claude Code
(โดยเฉพาะวิศวกรผลิตภัณฑ์/แพลตฟอร์ม และวิศวกรโครงสร้างพื้นฐาน LLM)
ใครอ่านแล้วจะได้ประโยชน์ที่สุด?
✅ 1) ทีมที่สร้างผลิตภัณฑ์ AI agent
✅ 2) วิศวกรที่ปรับต้นทุน/latency ของ LLM ให้เหมาะสม
✅ 3) คนที่ต่อเครื่องมือ MCP ไว้เยอะมาก
ในทางกลับกัน ผู้ใช้ทั่วไปแทบจะไม่อ่าน
มันไม่ใช่บทความแนว “เขียนพรอมป์ต์ให้ดีทำอย่างไร”
แต่เป็น
“ควรจัดการพรอมป์ต์อย่างไรในระดับสถาปัตยกรรมผลิตภัณฑ์”
สรุปสั้น ๆ
บทความนี้สำหรับคนที่สร้าง LLM ไม่ใช่ให้เป็นแค่ “แชต” แต่เป็น “ระบบโปรดักชัน”
แทบไม่ต่างจากการปรับแต่ง Docker layer ให้เหมาะสมเลย