บทที่ 31

บทที่ 31 — Loop และ Goal (`/loop`, `/goal`)

สองคำสั่งสำหรับงานที่ต้องใช้มากกว่าหนึ่ง turn

/loop เป็นตัวส่งซ้ำแบบโง่ ๆ คือส่งข้อความเดิมซ้ำตามเวลาที่ตั้งไว้ จนกว่าคุณจะสั่งหยุด ส่วน /goal เป็นเป้าหมายที่ engine คอยติดตามให้ — มีงบประมาณ มีวินัยในการ audit และมีเพดานแข็งที่หยุดสิ่งที่วิ่งหลุด

ทั้งคู่ใช้ร่วมกันได้ผลดีที่สุด goal บอกว่า อะไร และเงื่อนไขหยุด ส่วน loop บอกว่า ทำต่อไป แต่แต่ละตัวก็ใช้เดี่ยว ๆ ได้ และ /goal --auto ก็ตัดความ จำเป็นของ loop ออกไปเลย

/loop — ส่งซ้ำตามเวลา

❯ /loop 30s check whether the build finished and summarise any new errors
loop started (every 30s): check whether the build finished and summarise any new errors

token แรกคือช่วงเวลา (30s, 5m, 2h, 1d) ที่เหลือทั้งหมดคือข้อความที่ จะถูกส่งซ้ำ ถ้าไม่ใส่ช่วงเวลา ทั้งบรรทัดจะกลายเป็นเนื้อความ แล้วยิงทุก 5 นาที

❯ /loop /goal continue
loop started (self-paced (5min default)): /goal continue

การจัดการ

คำสั่ง ทำอะไร
/loop <interval> <body> เริ่ม — ช่วงเวลาต้องมาก่อนเท่านั้นถึงจะถูกอ่านว่าเป็นช่วงเวลา
/loop หรือ /loop status (หรือ list) แสดงเนื้อความของ loop ที่ทำงานอยู่
/loop stop (หรือ cancel / kill / off) หยุด

หนึ่ง loop ต่อหนึ่งครั้ง การเริ่มตัวที่สองขณะที่ตัวแรกยังทำงานจะขึ้นว่า loop already running — /loop stop first แทนที่จะซ้อนกัน

เนื้อความถูกส่งตรงตามที่พิมพ์ จะเป็น prompt, slash command หรืออะไรก็ได้ที่ คุณพิมพ์เองได้ และ loop ไม่ได้รอ ให้ turn ก่อนหน้าจบก่อนที่ช่วงเวลา ถัดไปจะมาถึง — มันเป็นตัวจับเวลา ไม่ใช่คิว

/goal — เป้าหมายที่ engine ติดตามให้

❯ /goal start "migrate every test file to the new fixture" --budget-tokens 400000

goal หนึ่งตัวมีทั้งเป้าหมาย งบประมาณ (ถ้าตั้ง) จำนวนโทเคนและรอบที่ใช้ไป และ สถานะ มันถูกเก็บอยู่ใน session จึงอยู่รอดข้าม /load

ตัวที่น่าสนใจคือ /goal continue มันไม่ได้แค่ prompt ซ้ำ แต่สร้าง audit prompt จากสถานะปัจจุบัน ซึ่งสั่งให้โมเดล

  • แปลงเป้าหมายกลับมาเป็นสิ่งส่งมอบที่จับต้องได้
  • ทำ checklist จาก prompt ไปถึง artifact
  • ตรวจหลักฐานจริง — ไฟล์ ผลลัพธ์เทส ผลของคำสั่ง
  • ห้าม รับสัญญาณตัวแทนว่าเป็นการเสร็จสิ้น
  • ถือว่าความไม่แน่ใจ = ยังทำไม่สำเร็จ

สองข้อสุดท้ายคือหัวใจ โมเดลที่ถูกถามว่า “เสร็จหรือยัง” มักตอบว่าเสร็จ ส่วน โมเดลที่ถูกสั่งว่า “ไปตรวจ artifact และถือว่าความไม่แน่ใจคือยังไม่สำเร็จ” จะไปดูจริง

คำสั่งย่อย

คำสั่ง ทำอะไร
/goal start <objective> [flags] (หรือ set / new) เริ่ม ใส่เครื่องหมายคำพูดครอบเป้าหมายถ้ามีคำที่ขึ้นต้นด้วย --
/goal หรือ /goal status สถานะบรรทัดเดียว
/goal show (หรือ info) สถานะเต็ม: งบประมาณ โทเคนที่ใช้ จำนวนรอบ audit ล่าสุด
/goal continue (หรือ next) ยิง audit หนึ่งรอบ
/goal complete [reason] (หรือ done) ปิดเองว่าเสร็จแล้ว
/goal abandon [reason] (หรือ stop / cancel) ยอมแพ้

Flag ของ /goal start

Flag ผล
--budget-tokens N (หรือ --tokens) เพดานโทเคนแบบอ่อน ที่ 1.0× โมเดลจะถูกเตือนให้สรุปงาน ที่ 1.5× engine หยุดให้ (ดูข้างล่าง)
--budget-time T (หรือ --time) เหมือนกัน แต่เป็นเวลาจริง เช่น 30m, 2h
--auto (หรือ --auto-continue) เดินต่อเองโดยไม่ต้องมี /loop ครอบ (ดูข้างล่าง)
--require <path> ไฟล์ที่ต้องมีอยู่จริงก่อนจะปิด goal ได้ ใส่ซ้ำได้หลายตัว (ดูข้างล่าง)

การรัน goal จนจบ

ทำได้สองแบบ

แบบมี loop — เขียนออกมาชัด ๆ

❯ /goal start "get the integration suite green" --budget-time 2h
❯ /loop 2m /goal continue

ทุกสองนาทีจะ audit หนึ่งรอบ เมื่อ goal ไปถึงสถานะปลายทาง loop จะ หยุดตัวเอง

loop auto-stopped (goal complete)

แบบ --auto — ไม่ต้องมี loop เลย

❯ /goal start "get the integration suite green" --budget-time 2h --auto

หลังจบทุก turn ที่มีการเรียก tool engine จะเข้าคิว /goal continue ตัวถัดไป ทันที ไม่ต้องรอครบช่วงเวลา แบบนี้มักเป็นสิ่งที่คุณต้องการ เพราะเร็วกว่า และ ยิงซ้อนไม่ได้

อย่าใช้ทั้งสองพร้อมกัน --auto จะถอยให้โดยเจตนาเมื่อมี /loop ทำงานอยู่ เพื่อไม่ให้ทั้งคู่เข้าคิวรอบใหม่พร้อมกัน

กลไกความปลอดภัย

ส่วนนี้ควรอ่านก่อนปล่อย goal ให้ทำงานโดยไม่มีคนเฝ้า มีจุดหยุดที่เป็นอิสระ จากกันสี่ชั้น และมันมีอยู่เพราะ “ให้โมเดลตัดสินเองว่าเสร็จเมื่อไร” ไม่ใช่ ดีไซน์ที่ปลอดภัยถ้ามีอยู่ลำพัง

1. งบอ่อน แล้วตามด้วยเพดานแข็ง

การใช้เกินงบโทเคนหรือเวลาที่ 1.0× จะสลับ prompt เป็นแบบให้สรุปงาน โมเดล จะถูกบอกว่าหมดงบแล้วและควรรวบให้จบ

ส่วนการเกิน 1.5× เป็นเรื่องของ engine ไม่ใช่ของโมเดล goal จะถูกบังคับให้ เป็น blocked ตัว loop ถูก abort และคุณจะได้รู้เหตุผล

/goal continue — hard limit: token budget overrun (612000 used ≥ 1.5× 400000 budget).
Auto-blocking goal + stopping loop.

ช่วงผ่อนผัน 1.5× มีไว้เพื่อไม่ให้โมเดลที่เหลืออีกก้าวเดียวจะจบถูกตัดกลางคัน ขณะเดียวกันโมเดลที่เลิกลู่เข้าหาคำตอบแล้วก็ใช้เงินต่อไปไม่ได้

2. เพดานจำนวนรอบ

100 ครั้งของ /goal continue ไม่ว่าจะตั้งงบไว้หรือไม่ การ audit จริง ๆ ลู่เข้าได้ต่ำกว่านี้มาก เพดานนี้มีไว้จับตัวที่วิ่งหลุดเท่านั้น และเป็นเหตุผล ที่ goal ซึ่งไม่ตั้งงบอะไรเลยก็ยังมีขอบเขต

3. ตัวกันรอบที่ว่างเปล่า

ถ้า turn ที่อยู่ใน loop ไม่มีการเรียก tool เลย — โมเดลพูดคนเดียวโดยไม่ได้ทำ อะไร — รอบถัดไปจะถูกข้ามหนึ่งครั้ง

(/goal continue suppressed: prior turn made no tool calls — model just
 monologued. Will retry next /loop firing.)

ข้ามครั้งเดียว ไม่ใช่ถาวร ตัวกันจะรีเซ็ตตัวเอง turn ที่ครุ่นคิดหนึ่งครั้งจึง ไม่ทำให้ loop ตาย

4. สถานะปลายทางหยุดทุกอย่าง

complete, abandoned และ blocked เป็นสถานะปลายทาง การไปถึงสถานะใด สถานะหนึ่งจะ abort loop ที่ทำงานอยู่และปฏิเสธ /goal continue ต่อไป ส่วน goal ที่ blocked คือถูก พัก ไม่ใช่ตาย แก้ตัวติดขัดแล้วสั่ง /goal continue เองได้ หรือจะ /goal abandon ก็ได้

--require — ประตูที่โมเดลพูดผ่านไม่ได้

audit prompt สั่งให้โมเดลตรวจ artifact ส่วน --require ให้ engine เป็น คนตรวจแทน

❯ /goal start "write the migration guide" \
    --require docs/migration.md \
    --require docs/migration-th.md \
    --auto

ตอนนี้ MarkGoalComplete จะ ถูกปฏิเสธ ตราบใดที่ยังมีไฟล์ไหนหายไป พร้อม ระบุชื่อไฟล์ที่ขาด goal จะยังเป็น active ต่อไป loop แบบ --auto จึงทำงาน ต่อแทนที่จะประกาศชัยชนะ

นี่คือการเปลี่ยนข้อตกลงระดับ prompt ให้กลายเป็นข้อเท็จจริงที่แข็ง โมเดลถูก ทำให้เชื่อได้ว่ามันเขียนไฟล์ไปแล้ว แต่มันทำให้ไฟล์มีอยู่จริงไม่ได้ ใช้ flag นี้ทุกครั้งที่ผลลัพธ์ของ goal เป็นไฟล์ที่คุณระบุชื่อได้ล่วงหน้า — มันเป็น สิ่งที่ได้ผลที่สุดในบทนี้

path อ้างอิงจาก working directory และใส่ซ้ำได้หลายตัว

โมเดลทำอะไรกับ goal ได้บ้าง

มีสาม tool ที่ถูกแยกออกจากกันโดยเจตนา เพื่อให้ “บันทึกความคืบหน้า” กับ “ประกาศชัยชนะ” เป็นคนละการกระทำ

Tool ผล
RecordGoalProgress จุดตรวจกลางทาง สถานะยังเป็น active รอบต่อไปยังยิง ส่วนสรุปจะถูกพกไปให้รอบหลัง ๆ เป็น hint prior_audit เพื่อไม่ต้อง audit ใหม่ตั้งแต่ต้น
MarkGoalComplete ปลายทาง complete ต้องมีสรุป audit ว่าตรวจอะไรไปบ้างและหลักฐานคืออะไร ถูกปฏิเสธถ้ายังมี path ใน --require ขาดอยู่
MarkGoalBlocked ปลายทาง blocked ต้องมี reason เช่น ไม่มี API key, สเปกกำกวม, หรือมีเรื่องที่คุณเท่านั้นตัดสินใจได้

การแยกนี้สำคัญ ก่อนหน้านี้มี tool ตัวเดียวทำทั้งสามอย่าง และทางที่ถูกที่สุด สำหรับโมเดลที่ไม่แน่ใจคือประกาศว่าเสร็จ ตอนนี้ทางของความไม่แน่ใจคือ RecordGoalProgress ซึ่งทำให้ loop เดินต่อ — คำอธิบายของ tool เขียนไว้ตรง ๆ ว่า “การจบ loop ด้วยหลักฐานที่ไม่พอคือ failure mode ที่แย่ที่สุด”

เมื่อไหร่ที่ไม่ควรใช้

  • งานเดี่ยวที่ระบุชัดอยู่แล้ว สั่งไปตรง ๆ เลย goal จะเพิ่มงานบันทึกและ รอบ audit ที่คุณไม่ต้องการ
  • งานที่กระจายออกไปหลายไฟล์ นั่นคือ Workflows ซึ่ง deterministic ขนานได้ และ resume ได้ ส่วน goal คืองานเส้นเดียวที่เดินต่อไป เรื่อย ๆ ไม่ใช่หลายเส้นพร้อมกัน
  • อะไรที่อิงตารางเวลามากกว่าช่วงเวลา /loop ตายไปพร้อม session ถ้าอยาก ได้ “ทุกวันทำงาน 08:30” ให้ใช้ Scheduling ซึ่งอยู่รอด ข้าม restart และรันจาก daemon ได้

การแก้ปัญหา

อาการ สาเหตุ วิธีแก้
loop already running หนึ่ง loop ต่อหนึ่ง session /loop stop ก่อน
loop ยิงแต่ไม่มีอะไรเกิดขึ้น เนื้อความถูกตัวกันรอบว่างเปล่าระงับไว้ มองหาข้อความแจ้งการระงับ รอบถัดไปจะลองใหม่
goal กลายเป็น blocked เอง ชนเพดานแข็ง — 1.5× ของงบ หรือครบ 100 รอบ /goal show จะบอกเหตุผล ตั้งงบใหม่ใน goal ตัวใหม่ หรือทำเป้าหมายให้แคบลง
โมเดลบอกว่าเสร็จแล้วทั้งที่ยังไม่เสร็จ ไม่มีอะไรบังคับให้มันพิสูจน์ เริ่ม goal ใหม่พร้อม --require <path> สำหรับทุก artifact
--auto ไม่ยอมยิง มี /loop ทำงานอยู่ หรือ turn ล่าสุดไม่ได้เรียก tool /loop stop แล้วปล่อยให้ --auto เป็นคนขับ
goal อยู่รอดข้าม restart ทั้งที่ไม่อยากให้อยู่ goal ถูกเก็บไว้ใน session /goal abandon หรือเริ่ม session ใหม่

ดูเพิ่มเติม

  • บทที่ 18 — plan mode สำหรับตอนที่อยากได้ ขั้นตอน เรียงลำดับที่คุณอนุมัติ มากกว่าเป้าหมายปลายเปิด plan mode มี driver และ retry budget ของตัวเอง
  • บทที่ 25 — workflows สำหรับงานกระจายจำนวนมาก
  • บทที่ 19 — schedule สำหรับการทำซ้ำที่ต้องอยู่รอด นานกว่า session