← Harness Engineering Handbook
LEVEL 4 · แงะของจริง
ออกแบบ harness ของตัวเอง — หลักคิดก่อนโค้ด
ถึงจุดที่หลายคนรอ: อยากสร้าง harness ของตัวเอง เริ่มตรงไหน? · คำตอบขัดใจนิดหน่อย: อย่าเพิ่งเปิด editor — เพราะการตัดสินใจที่ชี้เป็นชี้ตายทั้งหมดเกิดก่อนโค้ดบรรทัดแรก
13.1 ลำดับการคิด (ไม่ใช่ลำดับการเขียนโค้ด)
- ① เริ่มจาก verifier — คำถามแรกไม่ใช่ "ใช้โมเดลไหน" แต่คือ "งานนี้รู้ได้ยังไงว่าถูก" (บทที่ 5) · ถ้ายังตอบไม่ได้ agent ที่สร้างจะเป็นแค่เครื่องผลิตของที่คนต้องนั่งตรวจเองทั้งหมด — ออกแบบหรือสร้าง verifier ให้ได้ก่อนอย่างอื่นทั้งหมด
- ② เลือก tools น้อยที่สุดที่พองาน — เริ่ม 2–5 ตัว (บทที่ 4) อย่าใส่เผื่อ · เครื่องมือที่ "อาจได้ใช้" คือ context ที่เสียเปล่าและตัวเลือกที่ชวนสับสน
- ③ วาง guardrails ตามแผนที่จริง — ไล่แผนที่ blast radius × reversibility (บทที่ 6) ของงานนี้โดยเฉพาะ: จุดไหนคือหายนะที่แท้จริง จุดนั้นคือที่ที่ด่านต้องอยู่
- ④ เติม memory / subagents เมื่อเจ็บจริง — อย่าใส่วันแรก · ยังไม่เจอปัญหา context ยาว ก็ยังไม่ต้องมียาแก้ (บทที่ 9–10 รอได้เสมอ)
13.2 minimal harness — แก่นมันเล็กแค่นี้
โค้ดข้างล่างคือ harness ที่ทำงานได้จริงทั้งตัว ไม่ถึง 40 บรรทัด — loop จากบทที่ 2 + เครื่องมือไม่กี่ตัว + verifier หนึ่งตัว + การ์ดจากบทที่ 6 และ 8 · สังเกตว่าทุกบรรทัดคือบทหนึ่งของเล่มนี้:
▸ pseudocode: minimal harness ทั้งระบบ
# minimal harness — loop + tools + verifier เดียว
TOOLS = [
read_file(path), # ตา (บท 4)
write_file(path, content), # มือ — จุดเดียวที่แตะโลกจริง
run_tests(), # verifier — หัวใจของทั้งระบบ (บท 5)
]
SYSTEM = """คุณคือ agent แก้โค้ดใน repo นี้
อ่านไฟล์ก่อนแก้เสมอ · แก้ให้เล็กที่สุดที่พอ
ห้ามบอกว่าเสร็จ จนกว่า run_tests จะผ่าน""" # กติกา "เสร็จจริง" (บท 8)
def agent(task, max_turns=30): # เพดานกัน doom loop (บท 8)
history = [task]
for turn in range(max_turns):
resp = model(SYSTEM, TOOLS, history)
if resp.is_text: # โมเดลบอกว่าจบงาน
if not tests_passed(history): # เสร็จปลอม? → ตีกลับ
history += ["ยังไม่เห็นเทสต์ผ่าน — รัน run_tests ก่อนสรุป"]
continue
return resp.text
call = resp.tool_call
if call.name == "write_file" and not allowed(call.path):
history += [call, "path นี้ต้องให้คนอนุมัติก่อน"] # guardrail (บท 6)
continue
result = execute(call)
history += [call, truncate(result, 2000)] # กัน context บวม (บท 3)
log(turn, call.name, cost(history)) # observability (บท 7)
return "หมดโควตารอบ — สรุปที่ทำไป + จุดที่ติด ให้คนดูต่อ"ที่เหลือทั้งหมดของ harness ระดับ production — compaction ฉลาด ๆ, permission หลายชั้น, subagents, eval suite — คือความประณีตที่ค่อย ๆ เติมบนแก่นนี้เมื่องานเรียกร้อง ไม่ใช่ของที่ต้องมีวันแรก
13.3 อย่าสร้างเอง ถ้าของสำเร็จรูปพอ
ความจริงที่ควรพูดตรง ๆ: งานส่วนใหญ่ไม่ต้องสร้าง harness ใหม่ · Claude Code + CLAUDE.md + skills + hooks + MCP ปรับแต่งได้ไกลกว่าที่คิดมาก — และการปรับแต่ง harness สำเร็จรูปให้เข้ากับทีมก็คือ harness engineering เหมือนกัน เป็นจุดเริ่มที่ถูกต้องสำหรับ 90% ของงาน
สร้างเองเมื่อไหร่: workflow เฉพาะทางที่ harness ทั่วไปไม่รองรับ (agent ฝังใน product ของเรา, loop พิเศษเฉพาะโดเมน), ต้องคุม infra/ข้อมูลระดับเข้มข้น, หรือ harness คือตัว product เอง · และถ้าจะสร้าง — Agent SDK และ framework ต่าง ๆ มี loop + tool plumbing สำเร็จให้แล้ว: เวลาของเราควรหมดไปกับชิ้นส่วนทั้งห้าของบทที่ 1 ไม่ใช่ไปกับท่อ
13.4 ตารางเทียบ cost/latency — เครื่องมือตัดสินใจรวมทั้งเล่ม
ทุกบทที่ผ่านมาซ่อน trade-off แบบเดียวกันไว้ซ้ำ ๆ : หมุนไปทางเร็ว/ประหยัด หรือหมุนไปทางแม่น/ปลอดภัย — ไม่มีทางเลือกไหน "ถูกเสมอ" มีแต่เหมาะกับสถานการณ์ไหน ตารางนี้รวบทุกจุดที่เคยแยกกันพูดไว้ในบทก่อน ๆ ให้เห็นพร้อมกันในที่เดียว:
| การตัดสินใจ | หมุนไปทาง "เร็ว/ประหยัด" | หมุนไปทาง "แม่น/ปลอดภัย" | เอียงไปทางไหนเมื่อไหร่ |
|---|---|---|---|
| ความหนาของ sandbox (บท 6) | ไม่มี/บาง — รันทันที ไม่มี overhead ตั้งกรง | container/worktree แยก, ตัด network — ทุก tool call แบกค่าความปลอดภัย | งานแตะข้อมูลเสี่ยงหรือรับ input จากนอก → หนา · งานอ่านอย่างเดียวในเครื่องปิด → บางพอ |
| ความถี่ compaction (บท 3) | สรุปบ่อย/สั้น — context เบา ประหยัดทุกรอบ | เก็บดิบไว้นาน — รายละเอียด/เหตุผลก่อนหน้าไม่หาย | งานตรงไปตรงมา ยาวแต่ไม่ซับซ้อน → สรุปถี่ได้ · งาน debug ที่รายละเอียดเก่าคือกุญแจ → ยืดอายุ context ดิบ |
| ความช้าของ verifier (บท 5, 11) | เทสต์ย่อยไว — วนได้หลายรอบต่อนาที แต่ตรวจได้แค่ผิวเผิน | suite เต็ม/ช้า — มั่นใจกว่ามาก แต่ 20 นาทีต่อรอบ = วนได้ไม่กี่ครั้ง | ระหว่างวนแก้ → ใช้ตัวไวก่อน · ก่อนประกาศเสร็จจริง → ต้องผ่านตัวเต็มด้วย (ใช้สองชั้นซ้อนกันได้) |
| ความถี่การถามสิทธิ์ (บท 6) | auto มาก ถามน้อย — งานลื่นไม่สะดุด | ถามถี่ทุกจุดเสี่ยง — คุมแน่นกว่า แต่ถี่เกินจะเจอ alarm fatigue จนคนกดผ่านโดยไม่อ่าน | วางเส้นถามตาม blast radius × reversibility ของ FIG 6.1 — ไม่ใช่ตามความรู้สึกกลัว |
| แตกงานให้ subagent (บท 10) | ทำเองตัวเดียว — ไม่มี overhead ตั้งต้นซ้ำ (system prompt, สำรวจใหม่) | แตกหลายตัว — context isolation + ทำขนานได้ แต่จ่าย overhead ต่อหัวทุกตัว | งานสรุปกลับได้สั้นและอิสระจริง (บท 10.4) → แตก · งานเล็กหรือต้องแชร์ state ถี่ → ทำเอง |
สังเกตแกนร่วมของทุกแถว: ด้าน "เร็ว/ประหยัด" จ่ายด้วยความเสี่ยงที่ค้นพบช้าลง ส่วนด้าน "แม่น/ปลอดภัย" จ่ายด้วยเวลาและ token ที่มากขึ้น — ไม่มีจุดไหนหมุนไปสุดทางใดทางหนึ่งได้ตลอด งานเสี่ยงต่ำหมุนไปทางเร็วได้เต็มที่ งานเสี่ยงสูงต้องยอมจ่ายแพงขึ้น โจทย์ของคนออกแบบ harness ไม่ใช่หาค่าเดียวที่ดีที่สุด แต่คือรู้ว่าน็อบตัวไหนควบคุมอะไร แล้วหมุนให้เข้ากับความเสี่ยงของงานตรงหน้า
13.5 checklist ก่อนลงมือ
# CHECKLIST — ตอบให้ครบก่อนเขียนโค้ดบรรทัดแรก
[ ] งานนี้มี verifier ที่เชื่อได้ไหม? ไม่มี → หยุด ออกแบบ verifier ก่อน (บท 5)
[ ] ของสำเร็จรูป + ปรับแต่ง พอไหม? พอ → ใช้เลย อย่าสร้าง (บท 13.3)
[ ] tools ชุดเล็กสุดที่จบงานคืออะไร? เริ่ม 2–5 ตัว — เพิ่มเมื่อเจ็บจริง (บท 4)
[ ] action ไหนย้อนกลับยากสุด? จุดนั้นต้องมีด่าน / sandbox (บท 6)
[ ] นิยาม "เสร็จ" + เพดานอยู่ตรงไหน? verifier ก่อนจบ · max turns · งบ (บท 8)
[ ] เก็บ transcript ตั้งแต่วันแรกไหม? debug ไม่ได้ถ้ามองไม่เห็น (บท 7)
[ ] มีชุดงานทดสอบ ~10 ชิ้นไว้เทียบไหม? ไม่มีตัวเลข = ปรับมั่ว (บท 11)✅ สรุปบทที่ 13 — ลำดับคิด: verifier ก่อน → tools น้อยสุดที่พอ → guardrails ตามแผนที่ความเสี่ยงจริง → memory/subagents เมื่อเจ็บจริง · แก่นของ harness เล็กมาก (loop ไม่ถึง 40 บรรทัด) — ที่เหลือคือความประณีตที่เติมทีหลังได้ · 90% ของงานควรปรับแต่งของสำเร็จรูป ไม่ใช่สร้างใหม่ — และถ้าสร้าง ใช้ SDK จัดการท่อ เวลาเราไว้คิดชิ้นส่วนทั้งห้า · ทุกน็อบ (sandbox, compaction, verifier, permission, subagent) หมุนบนแกนเร็ว/ประหยัด vs แม่น/ปลอดภัยแกนเดียวกัน — เลือกตามความเสี่ยงของงาน ไม่มีค่าที่ดีที่สุดค่าเดียว