Agentic loop กับ stop_reason
แนวคิด
Agentic loop คือวงจรที่ทำให้โมเดลทำงานหลายขั้นตอนได้เองโดยไม่ต้องเขียนสคริปต์กำกับทุกก้าว หัวใจของมันคือการวนซ้ำสี่จังหวะ ได้แก่ ส่ง request ไปหา Claude, อ่านค่า stop_reason ที่ตอบกลับมา, ลงมือรัน tool ที่ถูกขอ, แล้วส่งผลลัพธ์กลับเข้าไปเป็นข้อมูลของรอบถัดไป
จุดตัดสินใจอยู่ที่ stop_reason ทุกครั้งที่ Claude ตอบ มันจะแนบค่านี้มาบอกว่า "ทำไมจึงหยุดพูด" ถ้าค่าเป็น tool_use แปลว่าโมเดลอยากเรียกเครื่องมือ และในคำตอบจะมี tool_use block อย่างน้อยหนึ่งอันพร้อมชื่อ tool กับอาร์กิวเมนต์ที่เป็น JSON แอปของเราต้องรัน tool นั้นแล้วส่งผลกลับ จากนั้นวนกลับไปถามใหม่
ถ้าค่าเป็น end_turn แปลว่า Claude คิดว่างานจบแล้วและได้ให้คำตอบสุดท้าย เราจึงออกจาก loop รูปแบบมาตรฐานจึงเขียนเป็นประโยคเดียวได้ว่า วนต่อไปเรื่อย ๆ ตราบใดที่ stop_reason ยังเป็น tool_use และหยุดเมื่อกลายเป็นค่าอื่น
สิ่งที่มักถูกลืมคือ end_turn ไม่ใช่ทางออกเดียว loop ควรจบเมื่อ stop_reason เป็นค่าใดก็ตามที่ไม่ใช่ tool_use ซึ่งรวมถึง max_tokens, stop_sequence และ refusal ด้วย แต่ละค่าบอกเหตุผลต่างกันและแอปควรจัดการให้เหมาะ ไม่ใช่วนต่อแบบไม่รู้จบ
ทำไมสำคัญ
เหตุผลที่ต้องยึด stop_reason เป็นตัวควบคุม เพราะมันเป็นสัญญาณที่โมเดลตั้งใจส่งออกมาโดยตรง ไม่ใช่การเดา ถ้าเราไปพยายามอ่านข้อความภาษาธรรมชาติของ Claude เพื่อทายว่า "งานจบหรือยัง" เราจะเจอ loop ที่ค้างหรือจบก่อนเวลา เพราะข้อความอาจมีคำว่า "เสร็จแล้ว" ทั้งที่ยังต้องเรียก tool ต่อ หรือกลับกัน
อีกกับดักคือการใช้จำนวนรอบสูงสุดเป็นกลไกหยุดหลัก การตั้งเพดานรอบไว้กันลูปหลุดเป็นเรื่องดีในฐานะตาข่ายนิรภัย แต่ถ้าใช้มันเป็นเงื่อนไขจบหลักแทน stop_reason งานที่ต้องใช้หลายขั้นตอนจริงจะถูกตัดกลางคัน ส่วนงานสั้นก็จะเสียรอบเปล่า
ตัวอย่าง
messages = [{"role": "user", "content": user_query}]
while True:
resp = client.messages.create(
model="claude-opus-4-8",
max_tokens=16000,
tools=tools,
messages=messages,
)
if resp.stop_reason != "tool_use":
break # end_turn, max_tokens, refusal ... ล้วนออกจาก loop
messages.append({"role": "assistant", "content": resp.content})
results = [run_tool(b) for b in resp.content if b.type == "tool_use"]
messages.append({"role": "user", "content": results})
stop_reason ปัจจุบัน: –
เช็คความเข้าใจ
ตัวควบคุมหลักที่บอกว่าควรวน loop ต่อหรือหยุด คือฟิลด์ใดในคำตอบของ Claude
ถ้า stop_reason เป็น max_tokens เราควรทำอย่างไรกับ loop