Tools
การตรวจจับลูปของเครื่องมือ
OpenClaw มีกลไกป้องกันสองแบบที่ทำงานร่วมกันเพื่อป้องกันรูปแบบการเรียกใช้เครื่องมือซ้ำ ๆ
โดยทั้งสองกำหนดค่าได้ภายใต้ tools.loopDetection:
- การตรวจจับลูป (
enabled) - ปิดใช้งานโดยค่าเริ่มต้น ตรวจสอบประวัติ การเรียกใช้เครื่องมือแบบเลื่อนต่อเนื่อง เพื่อค้นหารูปแบบซ้ำและการลองเรียกเครื่องมือที่ไม่รู้จักซ้ำ - กลไกป้องกันหลัง Compaction (
postCompactionGuard) - เปิดใช้งานเมื่อใดก็ตามที่enabledไม่ได้ถูกกำหนดเป็นfalseอย่างชัดเจน กลไกจะพร้อมทำงานหลังการลองใหม่ภายหลัง Compaction ทุกครั้ง และยุติการทำงานหากเอเจนต์ทำซ้ำชุดสามค่า(tool, args, result)เดิม ภายในหน้าต่างที่กำหนด
กำหนด tools.loopDetection.enabled: false เพื่อปิดกลไกป้องกันทั้งสองแบบ
เหตุผลที่มีคุณสมบัตินี้
- ตรวจจับลำดับการทำงานซ้ำที่ไม่มีความคืบหน้า
- ตรวจจับลูปที่ไม่ให้ผลลัพธ์และเกิดถี่มาก (เครื่องมือเดิม อินพุตเดิม และข้อผิดพลาด ซ้ำเดิม)
- ตรวจจับรูปแบบการเรียกซ้ำเฉพาะสำหรับเครื่องมือโพลที่รู้จัก
- หยุดวงจรบริบทล้น -> Compaction -> กลับเข้าสู่ลูปเดิม แทนที่จะปล่อยให้ ทำงานต่อไปอย่างไม่สิ้นสุด
บล็อกการกำหนดค่า
ค่าเริ่มต้นส่วนกลาง พร้อมแสดงทุกฟิลด์ที่มีเอกสารกำกับ:
{ tools: { loopDetection: { enabled: false, // master switch for the rolling-history detectors historySize: 30, warningThreshold: 10, criticalThreshold: 20, unknownToolThreshold: 10, globalCircuitBreakerThreshold: 30, detectors: { genericRepeat: true, knownPollNoProgress: true, pingPong: true, }, postCompactionGuard: { windowSize: 3, // armed after compaction-retry; runs unless enabled is explicitly false }, }, },}การเขียนทับค่ารายเอเจนต์ (ไม่บังคับ ที่ agents.list[].tools.loopDetection):
{ agents: { list: [ { id: "safe-runner", tools: { loopDetection: { enabled: true, warningThreshold: 8, criticalThreshold: 16, }, }, }, ], },}การตั้งค่ารายเอเจนต์จะซ้อนทับบล็อกส่วนกลางทีละฟิลด์ (รวมถึง
detectors และ postCompactionGuard ที่ซ้อนอยู่ภายใน) ดังนั้นเอเจนต์จึงต้องกำหนดเฉพาะ
ฟิลด์ที่ต้องการเปลี่ยนเท่านั้น
ลักษณะการทำงานของฟิลด์
| ฟิลด์ | ค่าเริ่มต้น | ผล |
|---|---|---|
enabled |
false |
สวิตช์หลักสำหรับตัวตรวจจับประวัติแบบเลื่อนต่อเนื่อง ค่า false จะปิดกลไกป้องกันหลัง Compaction ด้วย |
historySize |
30 |
จำนวนการเรียกใช้เครื่องมือล่าสุดที่เก็บไว้สำหรับการวิเคราะห์ |
warningThreshold |
10 |
จำนวนครั้งที่ทำซ้ำก่อนจัดรูปแบบนั้นเป็นเพียงคำเตือน |
criticalThreshold |
20 |
จำนวนครั้งที่ทำซ้ำก่อนบล็อกรูปแบบลูปที่ไม่มีความคืบหน้า หากกำหนดค่าไม่ถูกต้อง รันไทม์จะปรับค่านี้ให้สูงกว่า warningThreshold |
unknownToolThreshold |
10 |
บล็อกการเรียกเครื่องมือเดิมที่ไม่มีอยู่ซ้ำ หลังหาไม่พบครบจำนวนครั้งนี้ ไม่ขึ้นกับ detectors |
globalCircuitBreakerThreshold |
30 |
ตัวตัดวงจรส่วนกลางสำหรับภาวะไม่มีความคืบหน้าในทุกตัวตรวจจับ หากกำหนดค่าไม่ถูกต้อง รันไทม์จะปรับค่านี้ให้สูงกว่า criticalThreshold ไม่ขึ้นกับ detectors |
detectors.genericRepeat |
true |
เตือนเมื่อเรียกเครื่องมือเดิมด้วยอาร์กิวเมนต์เดิมซ้ำ และบล็อกเมื่อการเรียกเหล่านั้นให้ผลลัพธ์เหมือนกันด้วย |
detectors.knownPollNoProgress |
true |
ตรวจจับรูปแบบการโพลที่รู้จักซึ่งไม่มีความคืบหน้า (process ที่มี action: "poll"/"log", command_status) |
detectors.pingPong |
true |
ตรวจจับรูปแบบปิงปองที่สลับไปมาระหว่างการเรียกสองรายการโดยไม่มีความคืบหน้า |
postCompactionGuard.windowSize |
3 |
จำนวนครั้งที่กลไกป้องกันยังคงพร้อมทำงานหลัง Compaction และจำนวนชุดสามค่าที่เหมือนกันซึ่งจะทำให้ยุติการทำงาน |
สำหรับ exec การแฮชเพื่อตรวจสอบภาวะไม่มีความคืบหน้าจะเปรียบเทียบผลลัพธ์ของคำสั่งที่คงที่ (สถานะ
รหัสออก แฟล็กหมดเวลา และเอาต์พุต) และละเว้นข้อมูลเมตาของรันไทม์ที่เปลี่ยนแปลงได้ เช่น
ระยะเวลา PID รหัสเซสชัน และไดเรกทอรีทำงาน ผลลัพธ์จากการส่งข้อความออก
จะถูกแฮชโดยตัดรหัสที่เปลี่ยนในแต่ละครั้ง (รหัสข้อความ รหัสไฟล์ และการประทับเวลา)
ออก เพื่อไม่ให้ผลลัพธ์ "sent" รายการหนึ่งดูเหมือนกับผลลัพธ์ "sent"
อีกรายการ เมื่อมีรหัสการทำงาน ระบบจะประเมินประวัติเฉพาะภายในการทำงานนั้น
ดังนั้นรอบ Heartbeat ตามกำหนดเวลาและการทำงานใหม่จะไม่รับช่วงจำนวนลูปเก่า
จากการทำงานก่อนหน้า
การตั้งค่าที่แนะนำ
- สำหรับโมเดลขนาดเล็ก ให้กำหนด
enabled: trueและใช้ค่าเกณฑ์ เริ่มต้นต่อไป โดยทั่วไปโมเดลระดับเรือธงแทบไม่ต้องใช้การตรวจจับจากประวัติแบบเลื่อนต่อเนื่อง และสามารถ คงสวิตช์หลักเป็นfalseขณะที่ยังได้รับประโยชน์จาก กลไกป้องกันหลัง Compaction - เรียงค่าเกณฑ์ให้เป็น
warningThreshold < criticalThreshold < globalCircuitBreakerThreshold; รันไทม์จะปรับcriticalThresholdและglobalCircuitBreakerThresholdให้สูงขึ้น หากคุณกำหนดค่าไว้เท่ากับหรือต่ำกว่า เกณฑ์ที่ค่านั้นต้องสูงกว่า - หากเกิดผลบวกลวง:
- เพิ่ม
warningThresholdและ/หรือcriticalThreshold - อาจเพิ่ม
globalCircuitBreakerThresholdด้วย - ปิดใช้งานเฉพาะตัวตรวจจับที่ก่อปัญหา (
detectors.<name>: false) - ลด
historySizeเพื่อให้หน้าต่างประวัติสั้นลง
- เพิ่ม
- หากต้องการปิดทุกอย่าง รวมถึงกลไกป้องกันหลัง Compaction ให้กำหนด
tools.loopDetection.enabled: falseอย่างชัดเจน
กลไกป้องกันหลัง Compaction
หลังการลองใหม่ภายหลัง Compaction ซึ่งเกิดจากบริบทล้น ตัวดำเนินการจะเตรียม
กลไกป้องกันแบบหน้าต่างสั้นสำหรับการเรียกใช้เครื่องมือสองสามครั้งถัดไป หากเอเจนต์ส่ง
ชุดสามค่า (toolName, argsHash, resultHash) เดิมครบ postCompactionGuard.windowSize
ครั้งภายในหน้าต่างนั้น กลไกป้องกันจะสรุปว่า Compaction ไม่สามารถหยุด
ลูปได้ และยุติการทำงานด้วยข้อผิดพลาด compaction_loop_persisted
กลไกป้องกันนี้ควบคุมโดยแฟล็กหลัก tools.loopDetection.enabled แต่มี
ข้อแตกต่างหนึ่งประการ คือจะยังคง เปิดใช้งานเมื่อไม่ได้กำหนดแฟล็กหรือกำหนดเป็น true และจะปิด
เมื่อกำหนดแฟล็กเป็น false อย่างชัดเจนเท่านั้น พฤติกรรมนี้เป็นไปโดยตั้งใจ เพราะกลไกป้องกัน
มีไว้เพื่อออกจากลูป Compaction ซึ่งมิฉะนั้นอาจใช้โทเค็นอย่างไม่มีขีดจำกัด
ดังนั้นผู้ใช้ที่ไม่ได้กำหนดค่าใด ๆ ก็ยังได้รับการป้องกัน
{ tools: { loopDetection: { // master switch; set false to disable the guard along with the rolling detectors enabled: true, postCompactionGuard: { windowSize: 3, // default }, }, },}windowSizeที่ต่ำกว่าจะเข้มงวดกว่า (มีจำนวนครั้งให้ลองน้อยกว่าก่อนยุติ)windowSizeที่สูงกว่าจะเปิดโอกาสให้เอเจนต์ลองกู้คืนได้มากขึ้น- กลไกป้องกันจะไม่ยุติการทำงานขณะที่ผลลัพธ์ยังเปลี่ยนแปลง โดยจะทำงานเมื่อมีเพียงผลลัพธ์ที่ เหมือนกันทุกไบต์ตลอดหน้าต่างเท่านั้น
- กลไกจะพร้อมทำงานเฉพาะทันทีหลังการลองใหม่ภายหลัง Compaction ไม่ใช่ที่จุดอื่น ในการทำงาน
บันทึกและลักษณะการทำงานที่คาดหวัง
เมื่อตรวจพบลูป OpenClaw จะบันทึกเหตุการณ์ลูปและเตือนหรือบล็อก รอบการใช้เครื่องมือถัดไปตามระดับความรุนแรง เพื่อป้องกันการใช้โทเค็น อย่างควบคุมไม่ได้และการค้าง ขณะที่ยังคงให้เข้าถึงเครื่องมือตามปกติ
- ระบบจะแสดงคำเตือนก่อน
- ระบบจะเริ่มบล็อกเมื่อรูปแบบยังคงดำเนินต่อเกินเกณฑ์คำเตือน
- เกณฑ์วิกฤตจะบล็อกรอบการใช้เครื่องมือถัดไป และแสดงเหตุผล การตรวจจับลูปอย่างชัดเจนในบันทึกการทำงาน
- กลไกป้องกันหลัง Compaction จะส่งข้อผิดพลาด
compaction_loop_persistedซึ่งระบุ เครื่องมือที่เป็นสาเหตุและจำนวนการเรียกที่เหมือนกัน