← Harness Engineering Handbook
LEVEL 1 · เสาหลัก
Tool Design — ออกแบบ API ให้ผู้ใช้ที่เป็น AI
ทีมหนึ่งต่อ MCP server เข้า agent อย่างภูมิใจ — เครื่องมือ 60 ตัวพร้อมใช้ · ผลคือ agent กลับโง่ลง: เลือกเครื่องมือผิด สับสนระหว่าง get_user กับ fetch_user ที่ต่างกันนิดเดียว แถมจ่ายค่า context ให้ schema ที่แทบไม่เคยถูกเรียก · บทนี้ว่าด้วยศาสตร์ที่ฟังดูคุ้นแต่กติกาใหม่: ออกแบบ API ที่ "ผู้ใช้" เป็น AI
4.1 tool หนึ่งตัว = สัญญา 3 ส่วน
เครื่องมือหนึ่งตัวที่ harness ประกาศให้โมเดลเห็น ประกอบด้วย name (ชื่อ), description (คำอธิบาย), และ input schema (ฟอร์มที่ต้องกรอก) · จุดที่คนมองข้าม: description คือ prompt ที่ฝังถาวร — มันนั่งอยู่ใน context ทุกรอบ และโมเดลอ่านมันทุกครั้งที่ตัดสินใจว่าจะหยิบเครื่องมือไหน เขียน description ห่วย = เขียน prompt ห่วยที่ส่งซ้ำอัตโนมัติตลอดกาล
4.2 ดี vs แย่ — คู่เดียวเห็นครบ
✗ tool ที่ออกแบบตาม API ดิบ
{ "name": "api_v2_query_exec", ← ชื่อบอกแค่ "รันคิวรี" — งานอะไร? เมื่อไหร่ควรใช้?
"description": "Executes query against the v2 endpoint",
"input_schema": {
"type": "object",
"properties": {
"q": { "type": "string" }, ← q คืออะไร? SQL? ข้อความ? format ไหน?
"opts": { "type": "string",
"description": "JSON-encoded options" } } } }
← JSON ซ้อนใน string — จุดพังคลาสสิก✓ tool ที่ออกแบบตาม workflow
{ "name": "search_customer_orders",
"description": "ค้นออร์เดอร์ของลูกค้าจากชื่อหรืออีเมล
ใช้เมื่อผู้ใช้ถามถึงสถานะหรือประวัติการสั่งซื้อ
คืนไม่เกิน 20 รายการ (ใหม่→เก่า) — อยากได้หน้าถัดไปส่ง page เพิ่ม",
"input_schema": {
"type": "object",
"properties": {
"customer": { "type": "string", "description": "ชื่อหรืออีเมลลูกค้า" },
"status": { "type": "string", "enum": ["paid","shipped","refunded"] },
"page": { "type": "integer", "default": 1 }
},
"required": ["customer"] } }4.3 หลักออกแบบสามข้อ
- ออกแบบตาม workflow ไม่ใช่ตาม API ดิบ — นักพัฒนาที่เป็นคนอ่าน docs ได้ จำ state ข้ามหน้าจอได้ แต่โมเดลรู้เท่าที่ description ใน context บอก · เครื่องมือที่ดีคือ "หนึ่ง intent จบในตัว" (ค้นออร์เดอร์ของลูกค้าคนนี้) ไม่ใช่ "ประตูไปยัง endpoint" ที่ผู้ใช้ต้องประกอบเอง 3 จังหวะ
- จำนวนพอดี ไม่ใช่ 100 ชิ้นจิ๋ว — ทุก schema กิน context (บท 3) และทุกตัวเลือกที่เพิ่มคือโอกาสเลือกผิดที่เพิ่ม โดยเฉพาะเครื่องมือที่ทับซ้อนกันเอง · เครื่องมือน้อยตัวแต่ทรงพลัง ชนะเครื่องมือเยอะแต่จิ๋วเกือบทุกครั้ง
- ผลลัพธ์ต้องกระชับ — เพราะผลลัพธ์กลายเป็น context ทันที: คืนเฉพาะฟิลด์ที่ใช้ มี pagination ตัด log ให้เหลือท่อนที่เกี่ยว · tool ที่ dump ข้อมูลดิบ 5,000 บรรทัดคือ tool ที่สั่งให้ agent โง่ลงในอีก 10 รอบข้างหน้า
4.4 error message = prompt ขากลับ
เมื่อ tool พัง ข้อความ error จะถูกยัดกลับเข้า context และโมเดลจะอ่านมันแน่นอนเพื่อวางแผนรอบถัดไป — error จึงไม่ใช่ log แต่คือ prompt ที่เราส่งให้โมเดลตอนมันกำลังหลงทาง:
✗ Error: 400 Bad Request
โมเดลไปต่อไม่ถูก → เดามั่ว หรือวนเรียกซ้ำท่าเดิม (บท 8)
✓ Error: ไม่พบลูกค้าชื่อ "สมชาย จ."
ชื่ออาจสะกดไม่ตรงกับในระบบ — ลองอย่างใดอย่างหนึ่ง:
· ค้นด้วยอีเมลแทน: search_customer_orders(customer="somchai@...")
· หรือเรียก list_customers(query="สมชาย") หา id ที่ถูกก่อน
บอกว่าผิดอะไร + แก้ยังไง → รอบถัดไปแก้เกมถูกทันที4.5 MCP — มาตรฐานเปิดของการเสียบเครื่องมือ
เล่ม #07 แนะนำ MCP (Model Context Protocol) ไว้ว่าเป็น "ปลั๊ก USB" ที่ต่อ AI เข้ากับแอปและข้อมูลจริง · มุมของคนออกแบบ harness: MCP แยกคนสร้างเครื่องมือออกจากคนสร้าง harness — เขียน server ครั้งเดียว เสียบได้กับทุก harness ที่พูดโปรโตคอลนี้ ไม่ต้องผูกกับ vendor ไหน · แต่ระวัง: MCP ทำให้เสียบง่ายขึ้น ไม่ได้ทำให้ออกแบบดีขึ้น — server ที่ดัมพ์ API ดิบทั้งชุด 60 endpoints คือตัวอย่างคลาสสิกของสิ่งที่บทนี้เตือนทั้งบท
อัปเดตที่ตอกย้ำหลักการนี้: harness ยุคใหม่เริ่มไม่ยัด schema ของทุกเครื่องมือใน MCP server ทั้งชุดเข้า context ตั้งแต่ต้นอีกต่อไป — แต่ให้ agent ค้นหาก่อนว่ามีเครื่องมือไหนเกี่ยวกับงานตรงหน้า แล้วค่อยโหลด schema เฉพาะตัวที่จะใช้จริง · หลัก progressive disclosure (บทที่ 9) ไล่ตามมาถึงชั้น tools เองในที่สุด — ต่อ MCP server กี่สิบตัวก็ไม่ต้องแลกกับ context ที่บวมแบบที่เคยเป็นปัญหาคลาสสิกอีกต่อไป
✅ สรุปบทที่ 4 — tool = สัญญา 3 ส่วน (name, description, schema) — description คือ prompt ที่ฝังถาวร · ออกแบบตาม workflow ไม่ใช่ API ดิบ · จำนวนพอดี — ทุก schema กิน context ทุกตัวเลือกเพิ่มโอกาสพลาด · ผลลัพธ์กระชับเพราะมันกลายเป็น context · error ที่ดี = prompt ขากลับที่สอนวิธีแก้ · MCP ทำให้เสียบง่าย แต่หลักออกแบบทั้งบทนี้ยังใช้เต็ม ๆ