CCA · Foundations

PostToolUse hook ปรับข้อมูลต่างรูปแบบให้เป็นหนึ่งเดียว

แนวคิด

hook คือ callback ที่รันโค้ดของเราตอบสนองต่อเหตุการณ์ในวงจร agent หนึ่งในรูปแบบที่มีประโยชน์คือ PostToolUse ซึ่งทำงานหลัง tool คืนผลลัพธ์แล้ว ก่อนที่โมเดลจะได้เห็นผลนั้น จุดนี้เหมาะกับการแปลงผลลัพธ์ให้อยู่ในรูปแบบเดียวกัน

ปัญหาที่พบคือ tool หรือ MCP server หลายตัวคืนข้อมูลชนิดเดียวกันในรูปแบบต่างกัน เช่น เวลาบางตัวคืนเป็น Unix timestamp บางตัวเป็น ISO 8601 สถานะบางตัวเป็นตัวเลข บางตัวเป็นข้อความ ถ้าปล่อยให้โมเดลเจอความหลากหลายนี้เอง มันต้องเดาและตีความ ซึ่งเพิ่มโอกาสพลาด

PostToolUse hook แก้ตรงนี้ได้ ใน Agent SDK เราตั้งค่า hookSpecificOutput.updatedToolOutput เพื่อแทนที่ผลของ tool ก่อนโมเดลเห็น หรือใช้ additionalContext เพื่อต่อท้ายข้อมูลอธิบายเข้าไปในผลลัพธ์ hook จึงทำหน้าที่ normalize ข้อมูลจากแหล่งต่างรูปแบบให้เป็นสคีมาเดียวที่ agent ประมวลผลได้ง่าย

ทำไมสำคัญ

การ normalize ที่ชั้น hook ดีกว่าการหวังให้โมเดลจัดการเอง เพราะมันเป็นการแปลงเชิงกำหนดแน่ ทำเหมือนกันทุกครั้ง โมเดลจึงเห็นข้อมูลรูปแบบเดียวเสมอ ลดภาระการตีความและลดจุดที่เกิด error จากการอ่านรูปแบบผิด

ถ้าไม่ normalize agent ต้องเผื่อทุกความเป็นไปได้ในการอ่านค่า เช่น ต้องเดาว่า 1719900000 เป็นวินาทีหรือมิลลิวินาที หรือ 2 หมายถึงสถานะอะไร ยิ่งมี MCP server มากขึ้น ความหลากหลายยิ่งบานปลาย hook ที่แปลงให้เป็นมาตรฐานเดียวจึงเป็นการลงทุนที่คุ้ม

ตัวอย่าง

async def normalize_timestamps(input_data, tool_use_id, context):
    if input_data["hook_event_name"] != "PostToolUse":
        return {}
    raw = input_data["tool_output"]
    fixed = to_iso8601(raw)  # แปลง Unix/ตัวเลขให้เป็น ISO 8601 เสมอ
    return {
        "hookSpecificOutput": {
            "hookEventName": "PostToolUse",
            "updatedToolOutput": fixed,
        }
    }

หลังผ่าน hook นี้ ไม่ว่า tool ต้นทางจะคืนเวลารูปแบบใด agent จะเห็นเป็น ISO 8601 เสมอ

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

PostToolUse hook ทำงานจังหวะใดในวงจร และเหมาะกับงานอะไร

ใน PostToolUse hook เราแทนที่ผลของ tool ก่อนโมเดลเห็นได้ด้วยฟิลด์ใด

อ่านต่อ