ชนิดของ error กับ isRetryable metadata
แนวคิด
error ที่มีโครงสร้างจะมีประโยชน์ก็ต่อเมื่อเราแบ่งชนิดให้ถูก exam guide แยก error ออกเป็นสี่ชนิดหลัก แต่ละชนิดนำไปสู่การกระทำที่ต่างกัน
ชนิดแรกคือ transient error เช่น timeout หรือบริการไม่พร้อมใช้งาน เป็นความล้มเหลวชั่วคราวที่ลองใหม่แล้วอาจสำเร็จ ชนิดที่สองคือ validation error คือ input ไม่ถูกต้อง โมเดลควรแก้ input ของตัวเองแล้วเรียกใหม่ ชนิดที่สามคือ business error คือการละเมิดนโยบายหรือกฎธุรกิจ เช่น ยอดเกินวงเงิน เป็นข้อมูลที่คาดหมายได้และมุ่งสื่อสารกับผู้ใช้ ชนิดที่สี่คือ permission error คือไม่มีสิทธิ์ ซึ่งโมเดลมักแก้เองไม่ได้
วิธีสื่อชนิดเหล่านี้คือแนบ metadata ไปกับผล เช่น ฟิลด์ errorCategory ที่ระบุ transient/validation/permission, ฟิลด์ boolean isRetryable ที่บอกว่าลองใหม่ได้ไหม, และคำอธิบายที่มนุษย์อ่านรู้เรื่อง สำหรับ business error ควรใส่ธง retriable: false กับคำอธิบายที่เป็นมิตรต่อลูกค้า เพื่อให้ agent สื่อสารได้อย่างเหมาะสมแทนที่จะพยายามลองใหม่ไปเรื่อย
ทำไมสำคัญ
เหตุผลที่ต้องแยก retryable กับ non-retryable คือมันกันการลองใหม่ที่เสียเปล่า ถ้าโมเดลลองใหม่กับ error ที่ลองไปก็ไม่มีวันสำเร็จ เช่น input ผิดรูปหรือไม่มีสิทธิ์ มันจะวนเสียรอบและเสียโทเคน metadata ที่บอกชัดว่า isRetryable เป็น false ช่วยตัดวงจรนี้ตั้งแต่ต้น
มีความแตกต่างที่ละเอียดแต่สำคัญมาก คือระหว่าง access failure กับ valid empty result access failure คือเข้าถึงข้อมูลไม่ได้ ซึ่งต้องมีการตัดสินใจว่าจะลองใหม่ไหม จึงควรตั้ง is_error เป็น true พร้อม metadata ส่วน valid empty result คือ query สำเร็จแต่ไม่มีผลลัพธ์ตรงเงื่อนไข เช่น ค้นแล้วไม่เจอออเดอร์ที่ตรง นี่ไม่ใช่ความล้มเหลว จึงไม่ควรตั้ง is_error แต่คืนผลว่างตามปกติ
ถ้าเราสับสนสองอย่างนี้ จะเกิดปัญหาสองทาง ถ้าปั้น valid empty result ให้เป็น error โมเดลอาจลองใหม่ทั้งที่คำตอบที่ถูกคือ "ไม่มีข้อมูล" กลับกัน ถ้าปั้น access failure ให้เป็นผลว่างที่ทำเครื่องหมายว่าสำเร็จ โมเดลจะเข้าใจว่าไม่มีข้อมูลจริง ทั้งที่จริงแค่เข้าถึงไม่ได้ และจะรายงานผลที่ไม่ครบ
ตัวอย่าง
// transient — ลองใหม่ได้
{ "errorCategory": "transient", "isRetryable": true,
"message": "Upstream timeout after 30s. Safe to retry." }
// validation — โมเดลแก้ input เอง
{ "errorCategory": "validation", "isRetryable": false,
"message": "order_id must match #NNNNN; got 'last one'." }
// business — สื่อสารกับผู้ใช้ ไม่ลองใหม่
{ "errorCategory": "business", "retriable": false,
"message": "Refund exceeds the $500 self-service limit; needs a supervisor." }
// valid empty result — ไม่ใช่ error: ไม่ตั้ง is_error
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "{\"orders\": []}" }
เช็คความเข้าใจ
error สี่ชนิดคืออะไร และแต่ละชนิดนำไปสู่การกระทำใด
access failure กับ valid empty result ต่างกันอย่างไรในการตั้งธง