การส่งผลลัพธ์ tool กลับเข้าประวัติการสนทนา
แนวคิด
เมื่อ Claude ตอบด้วย stop_reason: "tool_use" มันยังไม่เห็นผลลัพธ์ของ tool มันเพียงแค่ "ขอ" ให้เรารัน หน้าที่ของแอปคือรัน tool นั้น แล้วเอาผลลัพธ์ใส่กลับเข้าไปในประวัติการสนทนาเป็น tool_result block ใน turn ถัดไป โมเดลจึงจะได้ข้อมูลใหม่มาใช้คิดก้าวต่อไป
รูปร่างของ request รอบถัดไปสำคัญมาก มันต้องประกอบด้วยของเดิมทั้งหมด บวกกับคำตอบของ assistant รอบที่แล้ว (ซึ่งมี tool_use block) และต่อท้ายด้วย user turn ใหม่ที่บรรจุ tool_result แต่ละอัน การแนบคำตอบ assistant กลับเข้าไปด้วยเป็นสิ่งที่ห้ามลืม เพราะ tool_result ต้องจับคู่กับ tool_use ที่มันตอบ
การจับคู่ทำผ่านฟิลด์ tool_use_id ทุก tool_use block มี id ประจำตัว และทุก tool_result ต้องอ้าง id เดียวกันผ่าน tool_use_id เพื่อบอกว่าผลนี้คือคำตอบของคำขอใด ถ้า Claude เรียกหลาย tool พร้อมกันในคำตอบเดียว ผลลัพธ์ทั้งหมดต้องรวมอยู่ใน user message เดียว ไม่ใช่แยกหลายข้อความ
ทำไมสำคัญ
ที่ต้องเป๊ะเรื่องนี้ เพราะการต่อประวัติการสนทนาคือช่องทางเดียวที่โมเดลจะ "รู้" ผลของการกระทำ Claude ไม่มีหน่วยความจำข้ามคำขอ ทุกอย่างที่มันเห็นคือ messages ที่เราส่งไปในรอบนั้น ถ้า tool_result หายไปหรือ id ไม่ตรง โมเดลจะเหมือนเรียกเครื่องมือแล้วไม่เคยได้คำตอบ มันจะเดา เรียกซ้ำ หรือหลุดออกนอกเรื่อง
อีกกับดักที่พบบ่อยคือการแยก tool_result ของการเรียกแบบขนานออกเป็นหลาย user message การทำแบบนั้นค่อย ๆ สอนให้โมเดลเลิกเรียก tool แบบขนาน เพราะรูปแบบข้อความที่มันเห็นไม่สอดคล้องกับที่มันส่งออกไป
ตัวอย่าง
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "อุณหภูมิ 31 องศา ฝนตกช่วงบ่าย"
}
]
}
ถ้า tool ทำงานล้มเหลว อย่าเงียบหรือทิ้ง block ไป ให้ส่ง tool_result ที่มี is_error: true พร้อมข้อความอธิบาย โมเดลจะได้รับรู้ความผิดพลาดและปรับวิธี เช่น ลองเส้นทางอื่นหรือถามผู้ใช้เพิ่ม
เช็คความเข้าใจ
tool_result ต้องอ้างอิงฟิลด์ใดของ tool_use เพื่อจับคู่ให้ถูกอัน
ถ้า Claude เรียกสาม tool พร้อมกันในคำตอบเดียว ควรส่งผลลัพธ์กลับอย่างไร