Claude Code Harness Foundations
The agentic loop
ทำนายและอธิบายลูป gather → act → verify ของ harness ในฐานะลูปที่ขัดจังหวะได้กลางทาง เพื่อให้รู้ว่าการหยุดเพื่อสั่งแก้ระหว่างงานเป็นเรื่องปกติ ไม่ใช่ความล้มเหลว
1) จุดสับสน: งานที่ดูเหมือนรันสคริปต์ แต่จริง ๆ วนหลายรอบ
คุณขอ Claude Code ในโปรเจกต์ shop-api ว่า "เพิ่ม validation ให้ `POST /orders` แล้วรันเทสต์ให้ผ่าน" สิ่งที่คุณเห็นในเทอร์มินัลคือลำดับยาว ๆ: อ่าน `src/routes/orders.ts` แล้วอ่าน `src/domain/order.ts` แล้วอ่านเทสต์ที่มีอยู่ แก้ handler รัน `pnpm test` เจอ fail อ่าน error แก้ใหม่ รันอีกครั้ง จนผ่าน แล้วจึงสรุป จากภายนอกมันดูเหมือนสคริปต์ที่รันครั้งเดียวจบ แต่จริง ๆ มันคือการตัดสินใจหลายรอบต่อเนื่องกัน โดยแต่ละรอบอิงผลลัพธ์จริงของรอบก่อน
ครึ่งทางของงานหนึ่ง คุณเห็นว่ามันกำลังจะแก้ผิดไฟล์ จึงกดหยุดแล้วพิมพ์แก้ทิศทาง คำถามที่ตามมาคือ: งานที่ทำไปแล้วหายไปหรือยัง? session เสียหรือไม่? และทำไมการขัดจังหวะจึงรู้สึกเหมือนเป็นความล้มเหลว ทั้งที่ควรเป็นเรื่องปกติของการทำงาน? บทนี้จะอธิบายกลไกของลูปก่อน เพื่อให้คุณตอบสามคำถามนี้ได้ด้วยตัวเอง
2) Mental model: ลูปที่ harness เป็นเจ้าของ และโมเดลตัดสินใจทีละรอบ
ลูปการทำงานของ harness มีสามจังหวะสลับกันไป: **gather** (ประกอบ context) → **act** (ลงมือผ่านเครื่องมือ) → **verify** (เก็บผลจริงกลับเข้า context) แล้ววนกลับไป gather ใหม่ด้วยข้อมูลที่มากขึ้น สองข้อที่ต้องแยกให้ออก: - **หนึ่งรอบ = หนึ่งการตัดสินใจของโมเดล** — โมเดลไม่เคยรันลูปเอง มันเห็น context แล้วเลือกสิ่งถัดไปหนึ่งอย่าง แล้วรอบนั้นจบ - **harness เป็นเจ้าของการวน** — เป็นคนประกอบ context ตรวจสิทธิ์ รันเครื่องมือ และป้อนผลจริงกลับ รวมทั้งกำหนดเพดานของลูปได้ (เช่น จำนวนรอบสูงสุด) แต่จุดที่ลูปจบตามปกติคือตอนที่โมเดลสร้าง output โดยไม่มีคำขอเรียกเครื่องมือ — การตัดสินใจหยุดจึงเป็นของโมเดล ลูปมีอยู่เพราะโมเดลไม่มีทางรู้ว่าการกระทำของมันได้ผลจริงหรือไม่ จนกว่าจะเห็นผลลัพธ์ ถ้าไม่มีจังหวะ verify ทุกคำตอบก็เป็นเพียงการเดาจากความน่าจะเป็น การป้อนผลจริงกลับเข้าไปคือสิ่งที่เปลี่ยนการเดาให้เป็นการแก้ไขที่ตรวจสอบได้
อ่านลูปให้เป็นสามจังหวะ
gather
harness เลือกและประกอบสิ่งที่โมเดลจะเห็น: คำสั่งของคุณ ไฟล์ instruction ประวัติของ session และผลลัพธ์จริงจากรอบก่อน
act
โมเดลเลือกว่าจะตอบเป็นข้อความหรือขอเรียกเครื่องมือ; harness ตรวจสิทธิ์ก่อน แล้วจึงลงมือรันจริง
verify
output จริงของเครื่องมือกลับเข้า context เป็นข้อเท็จจริง — ไม่ใช่ความคาดเดาของโมเดล — แล้วรอบถัดไปเริ่มจากข้อมูลที่มากขึ้น
3) กลไก: หนึ่งรอบเดินอย่างไร และทำไมจึงขัดจังหวะได้
ใน shop-api หนึ่งรอบมีลำดับดังนี้: 1. **gather** — harness ประกอบ context จากคำสั่งของคุณ + ไฟล์ instruction ของโปรเจกต์ + ประวัติของ session + ผลลัพธ์ของรอบก่อน 2. **act** — โมเดลอ่าน context แล้วขอเรียกเครื่องมือหนึ่งอย่าง เช่น อ่าน `tests/routes/products.test.ts` เพื่อดูแนวทางเทสต์ของโปรเจกต์ 3. **ตรวจสิทธิ์** — harness เทียบคำขอกับกฎก่อนลงมือ ถ้ากฎห้าม การกระทำไม่เกิดขึ้น และโมเดลได้รู้ว่าโดนปฏิเสธ 4. **verify** — harness รันเครื่องมือ เก็บ output จริง แล้วใส่กลับเข้า context 5. **ตัดสินรอบถัดไป** — โมเดลเห็นผลจริงแล้วเลือก: ทำต่อด้วยวิธีเดิม เปลี่ยนวิธี หรือสรุปว่าจบ จุดที่ต้องสังเกตคือ **การขัดจังหวะไม่ผูกกับขอบรอบ** — การกด `Esc` หยุด Claude ทันทีและยกเลิกเครื่องมือที่กำลังรันอยู่ จากนั้น Claude จะรอคำสั่งถัดไปของคุณ (ถ้าคุณพิมพ์ข้อความค้างไว้ระหว่างที่เครื่องมือยังรัน ข้อความนั้นจะถูกอ่านทันทีที่การเรียกที่ค้างอยู่จบลง) การหยุดไม่ได้ย้อนงานที่ทำไปแล้ว: transcript ของ session และไฟล์ที่แก้แล้วยังอยู่ คำสั่งถัดไปของคุณกลายเป็นข้อมูลใหม่ในจังหวะ gather ของรอบต่อไป ส่วนการย้อนกลับไปยังสถานะก่อนหน้าเป็นกลไกแยกต่างหาก — กด `Esc` สองครั้งเพื่อย้อนไปยังสถานะก่อนหน้า และการแก้ไฟล์ย้อนกลับได้ผ่าน snapshot ที่เก็บไว้
| จังหวะ | ใครเป็นเจ้าของ | ถ้าจังหวะนี้หายไปจะเกิดอะไร |
|---|---|---|
| gather | harness | โมเดลตัดสินใจจากข้อมูลเก่าหรือไม่ครบ — คำตอบดูสมเหตุสมผลแต่ไม่ตรงกับโปรเจกต์ |
| act | โมเดลขอ / harness รัน | ไม่มีอะไรเปลี่ยนแปลงในโปรเจกต์ — ได้เพียงข้อความ |
| ตรวจสิทธิ์ | harness | การกระทำที่ควรถูกห้ามเกิดขึ้นโดยไม่มีใครยับยั้ง |
| verify | harness + โมเดล | โมเดลไม่มีทางรู้ว่าการกระทำได้ผลจริงหรือไม่ ลูปจึงแก้ตัวเองไม่ได้ |
| ตัดสินรอบถัดไป | โมเดล | ลูปวนโดยไม่มีจุดปิด — ทำซ้ำหรือหยุดกลางทางโดยไม่รู้ว่าจบหรือยัง |
ลูปจบได้สองทาง: โมเดลเห็นผลจริงแล้วสรุปว่าเป้าหมายสำเร็จ หรืองานมาถึงจุดที่ต้องรอการตัดสินใจของคุณ (เช่น การอนุมัติที่ถูกถาม) แล้วคุณหยุดมันเอง ทั้งสองทางเป็นเรื่องปกติ การขัดจังหวะจึงไม่ใช่การทำให้ session เสีย แต่คือการเพิ่มข้อมูลเข้าไปในลูปที่กำลังทำงาน — กลไกเดียวกับที่ผลลัพธ์จริงของเครื่องมือถูกป้อนกลับ
4) Contrast: ตอบครั้งเดียว กับ ลูปที่ตรวจผลจริง
ความต่างระหว่างการตอบครั้งเดียวกับการวนลูปไม่ได้อยู่ที่ความยาวของคำตอบ แต่อยู่ที่ว่ามีผลลัพธ์จริงถูกป้อนกลับเข้าสู่การตัดสินใจหรือไม่
สองรูปร่างของการทำงาน
ฝั่งซ้ายตัดสินใจครั้งเดียวจากข้อมูลที่มี ฝั่งขวาตัดสินใจใหม่ทุกครั้งที่เห็นผลจริง และคุณแทรกคำสั่งได้ทุกเมื่อระหว่างลูป
การตัดสินใจทั้งหมดเกิดก่อนเห็นผลจริง ถ้าสมมติฐานผิด ก็ไม่มีรอบถัดไปให้แก้
ลูปเปลี่ยนสมมติฐานให้เป็นการแก้ที่ตรวจสอบได้ เพราะทุกการตัดสินใจมีผลลัพธ์จริงรองรับ
5) ตรวจความเข้าใจและก้าวต่อไป
ทดสอบความเข้าใจ: ลูปการทำงานของ harness
ตอบคำถามต่อไปนี้เพื่อยืนยันว่าคุณอ่านลูปออก และรู้ว่าการขัดจังหวะอยู่ตรงไหนของกลไก
ทำไมลูปต้องมีจังหวะ verify?
เมื่อคุณกดหยุดกลางลูป สิ่งใดเกิดขึ้น?
ลูปของ harness คือ gather → ______ → verify
ตอบเป็นภาษาอังกฤษคำเดียว
ข้อใดเป็นจริงเกี่ยวกับลูปนี้ (เลือกได้มากกว่าหนึ่งข้อ)
- ลูปหลักคือ gather → act → verify โดยมีจังหวะตรวจสิทธิ์คั่นก่อนการกระทำทุกครั้ง
- หนึ่งรอบ = หนึ่งการตัดสินใจของโมเดล; harness เป็นเจ้าของการวนและเป็นคนป้อนผลจริงกลับ
- verify ทำให้ลูปแก้ตัวเองได้ และคุณขัดจังหวะหรือแทรกคำสั่งได้ทุกเมื่อระหว่างลูป
- ก้าวต่อไป: บทถัดไปคือ Built-in tools ซึ่งจะพาไปรู้จักเครื่องมือที่โมเดลขอเรียกในจังหวะ act และวิธีที่ harness จัดหมวดความสามารถของมัน