CCA · Foundations

isError flag กับ error ที่มีโครงสร้าง

แนวคิด

เมื่อ tool ทำงานล้มเหลว เราต้องบอกให้โมเดลรู้ ในการเรียก tool ผ่าน Messages API เราส่งผลกลับเป็น tool_result block และถ้าล้มเหลว เราตั้ง is_error เป็น true พร้อมใส่ข้อความอธิบายใน content ในฝั่ง MCP โปรโตคอลใช้ฟิลด์ชื่อ isError ทำหน้าที่เดียวกัน คือเป็นธงบอกว่าผลนี้เป็นความล้มเหลว ไม่ใช่ผลปกติ

หัวใจไม่ได้อยู่แค่ที่การตั้งธง แต่อยู่ที่คุณภาพของข้อความที่แนบไปด้วย เอกสารแนะนำให้เขียน error message ที่ให้ข้อมูล แทนที่จะเขียนแค่ "failed" ให้บอกว่าเกิดอะไรขึ้นและโมเดลควรลองทำอะไรต่อ เช่น "Rate limit exceeded. Retry after 60 seconds." ข้อความแบบนี้ให้บริบทที่โมเดลใช้กู้คืนหรือปรับตัวได้โดยไม่ต้องเดา

ทำไมสำคัญ

เหตุผลที่ error แบบเหมารวมเป็นอันตราย คือมันปิดทางให้โมเดลตัดสินใจกู้คืนอย่างเหมาะสม ถ้าทุกความล้มเหลวคืนค่าเดียวกันว่า "Operation failed" โมเดลจะไม่รู้ว่านี่เป็นปัญหาชั่วคราวที่ควรลองใหม่ เป็น input ผิดที่ต้องแก้ หรือเป็นกฎธุรกิจที่ต้องอธิบายให้ผู้ใช้ฟัง มันจึงได้แต่เดา และมักเดาผิด

เมื่อ error มีโครงสร้าง โมเดลเลือกการกระทำได้ตรงตามชนิดของปัญหา ความล้มเหลวชั่วคราว เช่น timeout หรือบริการล่ม ควรลองใหม่ ปัญหา validation เช่น input ผิดรูป โมเดลควรแก้ input ของตัวเองแล้วเรียกใหม่ การละเมิดกฎธุรกิจเป็นข้อมูลที่คาดหมายได้และควรสื่อสารกับผู้ใช้ ไม่ใช่พยายามกู้คืน ส่วนปัญหา permission ที่โมเดลแก้เองไม่ได้ ควรส่งต่อให้มนุษย์

ธงเดียวจึงไม่พอ เราต้องแนบ metadata ที่บอกชนิดของ error ไปด้วย เพื่อให้ปลายทางแยกแยะได้ นี่คือความต่างระหว่างการบอกแค่ว่า "ล้มเหลว" กับการบอกว่า "ล้มเหลวเพราะอะไร และควรทำอะไรต่อ" ซึ่งเป็นเส้นแบ่งระหว่างระบบที่กู้คืนเองได้กับระบบที่ค้างหรือรายงานผลผิด

ตัวอย่าง

// error แบบเหมารวม — โมเดลกู้คืนไม่ได้
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "Operation failed", "is_error": true }

// error ที่มีโครงสร้าง — บอกชนิดและทางไปต่อ
{
  "type": "tool_result",
  "tool_use_id": "toolu_01",
  "is_error": true,
  "content": "{\"errorCategory\": \"transient\", \"isRetryable\": true, \"message\": \"Rate limit exceeded. Retry after 60 seconds.\"}"
}

ตัวหลังให้โมเดลรู้ทั้งว่าเป็นปัญหาชั่วคราว ลองใหม่ได้ และควรรออีกนานเท่าไร แทนที่จะเห็นแค่คำว่า failed

agent action: retry

transient failure และ caller ระบุว่า retryable — ลองเรียกซ้ำได้เลย

เช็คความเข้าใจ

ในการคืนผล tool ผ่าน Messages API เราบอกว่าเป็นความล้มเหลวด้วยฟิลด์ใด และฝั่ง MCP ใช้ชื่ออะไร

ทำไม error แบบเหมารวมว่า Operation failed จึงเป็นปัญหา

อ่านต่อ