Subdomain → ขอบเขตของ agent (บันไดการยกระดับ)
บทที่แล้วปักวิทยานิพนธ์ไว้ว่า agent หนึ่งตัวควรเป็น bounded context หนึ่งอัน และปิดท้ายด้วยทิศเดียว: อย่าเริ่มที่ความซับซ้อนสูงสุด บทนี้แปลทิศนั้นให้เป็นขั้นตอนที่จับต้องได้ โดยหยิบเครื่องมือเชิงกลยุทธ์ของ DDD ชิ้นที่คุณใช้คล่องอยู่แล้วมาเป็นด่านแรก — การจำแนก SubdomainSubdomainส่วนย่อยของปัญหาทางธุรกิจ (problem space) แบ่งเป็น core, supporting, generic — ก่อนจะออกแบบว่าจะมี agent กี่ตัวและแต่ละตัวทำอะไร ต้องวิเคราะห์ subdomain ของธุรกิจก่อนเสมอ ไม่ใช่เริ่มจากอยาก 'มี agent' แล้วค่อยหาเรื่องให้มันทำStrategic Design
DDD แบ่ง problem space ของธุรกิจออกเป็นสามชนิด: core (สิ่งที่ทำให้เราชนะคู่แข่ง ต้องปั้นเองให้ดีที่สุด), supporting (จำเป็นต่อธุรกิจแต่ไม่ใช่จุดต่าง) และ generic (ใครก็ทำได้เหมือนกันหมด ซื้อสำเร็จรูปคุ้มกว่าปั้นเอง) การจำแนกนี้ตอบคำถามเชิงกลยุทธ์ว่า “ควรลงแรงตรงไหน” ก่อนคำถามเชิงเทคนิคว่า “จะสร้างด้วยอะไร” เสมอ และมันคือด่านแรกที่กันไม่ให้เรา default เป็น “สร้าง agent” กับทุกกล่องบนกระดาน
คอร์สนี้เป็น คอร์สออกแบบ ไม่ใช่ทัวร์ SDK — code ในบทคือ ภาพร่าง ของ system prompt, ชุด tool และโทโพโลยี (Thai Mermaid + pseudo-config สั้นๆ) ไม่ใช่ app ที่รันได้จริง ตัวอย่างต่อยอดจาก domain เดิมที่ repo kaen-food-ordering (กำลังจัดทำ) โดยมองมันผ่านเลนส์ใหม่: ระบบ ops-copilot ที่ช่วยทีมปฏิบัติการของ platform
บันไดการยกระดับ: เลือกขั้นที่ต่ำที่สุดที่พอ
หัวข้อที่มีชื่อว่า “บันไดการยกระดับ: เลือกขั้นที่ต่ำที่สุดที่พอ”คำแนะนำแกนกลางจาก Building Effective Agents (Anthropic, Dec 2024) ประโยคเดียวคือ เริ่มจากสิ่งที่ง่ายที่สุดที่แก้ปัญหาได้ แล้วเพิ่มความซับซ้อนเมื่อจำเป็น เท่านั้น วิธีที่ทำให้คำแนะนำนี้ใช้งานได้จริงคือมองมันเป็น “บันได” สามขั้น ไล่จากต้นทุนและความไม่แน่นอนต่ำสุดขึ้นไปสูงสุด:
- ขั้น 1 — single LLM call (augmented LLM: เรียก model ครั้งเดียวพร้อม tool/retrieval เท่าที่จำเป็น) เหมาะกับงานที่จบในครั้งเดียว เช่น จัดหมวดตั๋ว สรุปข้อความ ดึงข้อมูลตอบกลับ
- ขั้น 2 — workflow pattern code กำหนดลำดับขั้นไว้ล่วงหน้าและร้อยการเรียก LLM หลายครั้งเข้าด้วยกันตามเส้นทางที่รู้อยู่แล้ว
- ขั้น 3 — autonomous agent ปล่อยให้ LLM สั่งการ Agentic LoopAgentic Loopวงจรที่ agent ทำซ้ำจนกว่าจะบรรลุเป้าหมาย: รับ input → วางแผน/ตัดสินใจ → เรียก tool → สังเกตผลลัพธ์ → วนกลับไปตัดสินใจใหม่ — ต่างจากโปรแกรมทั่วไปที่รันเส้นทางเดียวจบ วงจรนี้เองที่ทำให้ agent ยืดหยุ่น แต่ก็เสี่ยง context rot ถ้าวนนานเกินไปโดยไม่มีขอบเขตProcess ของตัวเอง — วางแผน เรียก tool อ่านผล แล้วตัดสินใจก้าวถัดไปเองจนกว่าจะจบ
กติกาการปีนมีข้อเดียว: ขึ้นทีละขั้น และขึ้นต่อเมื่อขั้นล่างพิสูจน์แล้วว่าไม่พอ ไม่ใช่กระโดดขึ้นขั้น 3 เพราะมันฟังดูล้ำ หน้าตาของบันไดและเกณฑ์ตัดสินแต่ละขั้นเป็นดังนี้:
flowchart TD
S["subdomain ที่จะสร้างระบบให้"] --> Q{"งานปลายเปิด และต้องให้ระบบ<br/>ตัดสินใจเส้นทางเองหรือไม่"}
Q -->|"ไม่ · งานเดียวจบ · generic"| R1["ขั้น 1 — single LLM call<br/>augmented LLM = prompt + tool + retrieval<br/>เกณฑ์: generic subdomain, งานจบในครั้งเดียว<br/>ทางเลือก: ซื้อของสำเร็จ หรือเรียก LLM ตรง ๆ"]
Q -->|"ไม่ · แต่มีหลายขั้นที่รู้ล่วงหน้า"| R2["ขั้น 2 — workflow pattern<br/>prompt chaining · routing · parallelization ·<br/>orchestrator-workers · evaluator-optimizer<br/>เกณฑ์: supporting subdomain, เส้นทางคาดเดาได้<br/>code กำหนดเส้นทาง test ได้ ถูกและนิ่ง"]
Q -->|"ใช่ · ปลายเปิดจริง และคุ้มค่าความยืดหยุ่น"| R3["ขั้น 3 — autonomous agent<br/>LLM สั่งการ agentic loop ของตัวเอง<br/>เกณฑ์: core subdomain + ปลายเปิด<br/>เฉพาะเมื่อมี sandbox + guardrails + เงื่อนไขหยุด"]
R1 -.->|"ไต่ขึ้นเมื่อพิสูจน์แล้วว่าไม่พอ"| R2
R2 -.->|"ไต่ขึ้นเมื่อพิสูจน์แล้วว่าไม่พอ"| R3
classDef rung fill:#c7d2fe,stroke:#3730a3,color:#1a1a1f;
classDef agent fill:#f59e0b,stroke:#92400e,color:#1a1a1f;
class R1,R2 rung;
class R3 agent;
คำบรรยายภาพ: บันไดสามขั้นไล่จากต้นทุน/ความไม่แน่นอนต่ำสุด (ขั้น 1) ขึ้นไปสูงสุด (ขั้น 3) เกณฑ์แต่ละขั้นผูกกับชนิดของ subdomain และระดับความปลายเปิดของงาน — generic กับงานครั้งเดียวจอดที่ขั้น 1, supporting ที่เส้นทางคาดเดาได้จอดที่ขั้น 2, มีแต่ core ที่ปลายเปิดจริงเท่านั้นที่ มีสิทธิ์ ขึ้นขั้น 3 ลูกศรประคือการไต่ขึ้นเมื่อขั้นล่างไม่พอ ไม่ใช่ default ที่กระโดดข้ามได้ สังเกตว่าขั้น 3 (สีส้ม) เป็นขั้นเดียวที่ต้องมี sandbox + guardrails + เงื่อนไขหยุดกำกับ และ subdomain ส่วนใหญ่ในระบบจริงไม่เคยไปถึงขั้นนี้ — บันไดนี้จึงเป็นเครื่องมือ ลด จำนวน agent ไม่ใช่แจก agent ให้ทุกกล่อง
workflow กับ agent คือเส้นแบ่งจริง ไม่ใช่ป้ายการตลาด
หัวข้อที่มีชื่อว่า “workflow กับ agent คือเส้นแบ่งจริง ไม่ใช่ป้ายการตลาด”ระหว่างขั้น 2 กับขั้น 3 มีเส้นแบ่งที่คมกว่าที่หลายคนคิด และมันคือหัวใจของบทนี้ workflow กับ agentWorkflow vs Agentความต่างสำคัญที่มักถูกมองข้าม: workflow คือ code ที่กำหนดลำดับขั้นตอนตายตัวไว้ล่วงหน้า (คาดเดาได้ ทดสอบง่าย) ส่วน agent คือระบบที่ตัดสินใจเส้นทางเองแบบไดนามิกผ่าน agentic loop (ยืดหยุ่นกว่าแต่คาดเดายากกว่า) — โจทย์ส่วนใหญ่ไม่ต้องการ agent เต็มรูปแบบ workflow ที่ออกแบบดีมักพอเพียงและเชื่อถือได้กว่าProcess ต่างกันตรงที่ ใครเป็นคนกำหนดเส้นทาง:
- ใน workflow code ของคุณเขียนเส้นทางไว้ล่วงหน้า — LLM เติมช่องว่างในแต่ละก้าว แต่ลำดับก้าวถูกล็อกไว้แล้ว ผลคือคาดเดาได้ test ได้เหมือน code ปกติ ถูกและเร็ว
- ใน agent LLM เป็นคนตัดสินเองว่าก้าวถัดไปคืออะไร วน agentic loop ของตัวเองจนกว่าจะบรรลุเป้า ผลคือยืดหยุ่นกับงานที่คาดเดาเส้นทางล่วงหน้าไม่ได้ แต่แลกมาด้วย token ที่บานปลาย, latency ที่สูงขึ้น และผลลัพธ์ที่คาดเดายากกว่า
จุดที่ต้องฝังให้ขึ้นใจคือ การขยับจากขั้น 2 ไปขั้น 3 ไม่ใช่ “อัปเกรดฟรี” — มันคือการจ่ายค่าความยืดหยุ่นด้วยต้นทุน, ความหน่วง และความไม่แน่นอน ถ้างานหนึ่งเส้นทางตายตัวอยู่แล้ว การยกมันขึ้นเป็น agent มีแต่จะทำให้แพงขึ้น ช้าลง และ test ยากขึ้น โดยไม่ได้อะไรกลับมา
และนี่คือเหตุผลที่ workflow ขั้น 2 ไม่ได้มีแค่แบบเดียว Building Effective Agents ให้เมนู workflow pattern ห้าแบบที่นั่งอยู่ ใต้ เกณฑ์ agent พอดี — prompt chaining (ร้อยเป็นทอดๆ), routing (แยกทางตามชนิด input), parallelization (ยิงขนานแล้วรวมผล), orchestrator-workersOrchestrator-Workersโทโพโลยีที่ agent ตัวหนึ่ง (orchestrator) แตกงานใหญ่เป็นงานย่อยแล้วมอบหมายให้ agent ลูกทีม (worker) แต่ละตัวที่มี Bounded Context แคบและชัดเจนของตัวเอง ก่อนรวมผลลัพธ์กลับ — ต่างจากการปล่อยให้ agent หลายตัวคุยกันเองแบบไม่มีใครคุมภาพรวมArchitecture (ตัวประสานแตกงานให้ลูกทีม) และ evaluator-optimizer (วนแก้ตามคำวิจารณ์) ก่อนจะเอื้อมไปขั้น 3 ให้ถามก่อนเสมอว่าห้าแบบนี้แบบใดแบบหนึ่งครอบงานได้หรือยัง เพราะทุกแบบล้วนคาดเดาได้และถูกกว่า agent เต็มรูป
แม็ป subdomain ของ ops-copilot เข้ากับบันได
หัวข้อที่มีชื่อว่า “แม็ป subdomain ของ ops-copilot เข้ากับบันได”เอาบันไดมาวางบน domain ฟู้ดเดลิเวอรีเดิม สมมติทีมปฏิบัติการอยากได้ ops-copilot เต็มรูป เราไล่จำแนก subdomain แล้วเลือกขั้นให้แต่ละอันแทนที่จะเหมารวมว่าทุกอันต้องเป็น agent:
- generic → ขั้น 1 หรือไม่ใช้ AI เลย งานอย่างส่งอีเมลยืนยันออเดอร์, ออกใบเสร็จ, login — ใครๆ ก็ทำเหมือนกัน ซื้อของสำเร็จรูปหรือเรียก API ตรงๆ จบ ถ้าต้องแตะ LLM จริงก็แค่ single call เช่น “สรุปตั๋วยาวๆ ให้สั้น” หรือ “จัดหมวดคำถามลูกค้า” ไม่มีเหตุผลให้เป็น agent
- supporting → ขั้น 2 (workflow หรือ tool) งานติดตามสถานะออเดอร์ (order-tracking) มีขั้นตอนตายตัว: อ่านสถานะ → คำนวณ ETA → ร่างข้อความตอบ นี่คือ prompt chaining หรือ routing ตรงๆ ไม่ต้องมี agentic loop เช่นเดียวกับงานหลังร้าน (restaurant-ops) แบบปรับคิวตามกติกาที่รู้อยู่แล้ว — เป็น ToolToolfunction หรือ API ภายนอกที่ agent เรียกใช้ได้เพื่อกระทำสิ่งที่ model ภาษาเองทำไม่ได้ เช่น ค้นเว็บ อ่าน file เรียกฐานข้อมูล — ขอบเขตของชุด tool ที่ agent หนึ่งถืออยู่ก็คือส่วนหนึ่งที่นิยาม Bounded Context ของ agent นั้น ยิ่ง tool set กว้างเกินหน้าที่ ยิ่งเสี่ยงให้ agent ล้ำขอบเขตArchitecture ที่มี workflow ห่อ ก็เชื่อถือได้กว่าและถูกกว่า agent
- core + ปลายเปิด → ขั้น 3 (ผู้สมัคร agent) งานแก้ข้อพิพาทลูกค้าที่ซับซ้อน (customer-support) — ตีความนโยบาย ชั่งน้ำหนักหลักฐาน เลือกวิธีชดเชย ต่อรองไปมา — เป็นงานที่เส้นทางคาดเดาล่วงหน้าไม่ได้จริง นี่คือกล่องเดียวในตัวอย่างที่ AgentAgentระบบซอฟต์แวร์ที่รับเป้าหมายแล้ววางแผน-ตัดสินใจ-เรียกใช้ tool ได้เองหลายรอบ (agentic loop) โดยไม่ต้องมีมนุษย์กำกับทุกก้าว ต่างจากโปรแกรมทั่วไปที่รันตามลำดับคำสั่งตายตัว — ในคอร์สนี้มองแต่ละ agent เหมือน1 Bounded Context ที่ต้องมีขอบเขต ภาษา และหน้าที่ของตัวเองชัดเจนArchitecture เต็มรูปเริ่ม คุ้ม ค่าความยืดหยุ่นที่จ่ายไป
สังเกตคำว่า ผู้สมัคร ให้ดี — core + ปลายเปิดทำให้งานนั้น มีสิทธิ์สมัคร เป็น agent เท่านั้น ยังไม่ใช่ใบผ่านทาง เพราะขั้น 3 มาพร้อมเงื่อนไขบังคับ: เฉพาะเมื่อมี sandbox (จำกัดพื้นที่ทำงาน), guardrailsGuardrailกติกาที่ควบคุมไม่ให้ agent ทำเกินขอบเขตหรือก่อความเสียหาย เช่น จำกัด tool ที่เรียกได้ ตรวจ output ก่อนส่งออก บังคับ human approval สำหรับการกระทำที่ย้อนกลับไม่ได้ — เป็นสิ่งที่รักษาขอบเขตของ Bounded Context ของ agent ให้ไม่ล้ำเส้นProcess + human-in-the-loopHuman-in-the-loopการออกแบบให้มนุษย์เข้ามาตรวจสอบหรืออนุมัติในจุดที่การกระทำของ agent มีความเสี่ยงสูงหรือย้อนกลับไม่ได้ เช่น ก่อนโอนเงินหรือลบข้อมูลจริง — เป็น guardrail ชนิดหนึ่งที่ยังจำเป็นแม้ agent จะฉลาดขึ้นเรื่อย ๆ เพราะบางการตัดสินใจไม่ควรปล่อยให้ agent ตัดสินใจเองทั้งหมดProcess (ดักการกระทำเสี่ยงก่อนเกิดจริง เช่น คืนเงินต้องมีคนอนุมัติ) และเงื่อนไขหยุด (กันวนไม่รู้จบ) ครบทั้งสามอย่างเท่านั้นจึงจะปล่อยงานขึ้นขั้น 3 ได้
เงื่อนไขสามข้อข้างบนไม่ใช่พิธีกรรม แต่ปิดรอยรั่วจริงของการเปรียบ agent กับ bounded context: aggregate ใน DDD รักษา invariant แบบ atomic — กติกาถูกบังคับ ณ ขอบเขตธุรกรรมเสมอ ไม่มีทางหลุด แต่ context ของ agent หลัง compaction/summarization ไม่ได้บังคับอะไรแบบนั้น กฎที่เขียนไว้ใน system prompt อาจถูกสรุปทิ้งหรือเจือจางเมื่อ context ยาวขึ้น การรักษากติกาของ agent จึงเป็นแบบ best-effort ล้วนๆ นี่คือเหตุผลที่ขั้น 3 ต้องมี sandbox + guardrails + เงื่อนไขหยุด (และทำไมบทหลังๆ ถึงต้องพึ่ง agent memory และ eval) — การยกงานขึ้นเป็น agent ไม่ใช่การได้ความสามารถมาฟรี แต่คือการรับภาระรักษากติกาที่ระบบไม่บังคับให้เองมาไว้บนบ่า
❌ version ดิบ: agent หนึ่งตัวต่อ1 box
หัวข้อที่มีชื่อว่า “❌ version ดิบ: agent หนึ่งตัวต่อ1 box”สัญชาตญาณที่ผิดที่สุดหลังจำแนก subdomain เสร็จคือ “ในเมื่อแบ่งกล่องมาสวยแล้ว ก็ทำ agent หนึ่งตัวต่อหนึ่งกล่องสิ” — วาด subdomain ห้ากล่อง แล้วปั้น agent ห้าตัวแม็ปตรงตัว มันดูเป็นระเบียบ แต่มันคือ version ดิบที่ข้ามบันไดทั้งอันไป:
subdomains_to_agents: notifications (generic): agent # ผิด — ขั้น 1: ส่งอีเมลตรง ๆ ก็จบ ไม่ต้องมี LLM ด้วยซ้ำ order-tracking (supporting): agent # ผิด — ขั้น 2: ขั้นตอนตายตัว เป็น workflow ก็พอ sales-report (generic): agent # ผิด — ขั้น 1: single LLM call สรุปให้พอ restaurant-ops (supporting): agent # ผิด — ขั้น 2: ปรับคิวตามกติกา = workflow + tool dispute-resolution (core, ปลายเปิด): agent # ✅ กล่องเดียวที่ผ่านเกณฑ์ขั้น 3 จริงจากห้ากล่อง มีเพียงกล่องเดียวที่ผ่านเกณฑ์ขั้น 3 ส่วนที่เหลือถูกยกเกินความจำเป็นทั้งหมด ผลคือระบบ multi-agent ห้าตัวที่แพงกว่า ช้ากว่า และเปราะกว่าการมี workflow สามชิ้นกับ agent ตัวเดียว When to use multi-agent systems (and when not to) (Anthropic/Claude) เตือนไว้ตรงกัน: multi-agentMulti-agentระบบที่มี agent มากกว่าหนึ่งตัวทำงานร่วมกัน แต่ละตัวควรมี Bounded Context ของตัวเองชัดเจนและเชื่อมกันผ่าน context map/handoff ที่ออกแบบไว้ — ไม่ใช่คำตอบสำเร็จรูปสำหรับทุกปัญหา หลายงานทำด้วย agent เดียวหรือ workflow ธรรมดาก็เพียงพอและเชื่อถือได้กว่าArchitecture เผา token ราว 3–10 เท่าของการทำงานแบบ agent เดี่ยว และเพิ่มภาระการประสานงานมหาศาล มันควรเป็น ข้อยกเว้นที่พิสูจน์ด้วยเหตุผล ไม่ใช่ค่าเริ่มต้น
เส้นแบ่งของ agent ยังคงลากบนความไม่ต่อเนื่องของ ภาษาและความไว้ใจ เหมือนบทที่แล้ว ไม่ใช่บนตำแหน่งงานหรือชื่อ subdomain การมี subdomain แยกกันไม่ได้แปลว่าต้องมี agent แยกกัน — บาง subdomain ควรเป็น workflow, บางคู่ที่ภาษาใกล้กันอาจรวมเป็น agent เดียว และหลายอันไม่ควรมี agent เลย DDD คือวินัยที่บอกว่าอะไรควรอยู่ใน agent ที่มีขอบเขตดี ตัวเดียว ก่อน ส่วนการแตกเป็นหลายตัวเป็นเรื่องของบทที่ 5 ที่ต้องมีเหตุผลมีชื่อรองรับ
สิ่งที่จะทำต่อ
หัวข้อที่มีชื่อว่า “สิ่งที่จะทำต่อ”บทนี้เพิ่มขั้นตอนจับต้องได้ให้วิทยานิพนธ์: จำแนก subdomain ก่อน แล้วปีนบันไดจากขั้นต่ำสุดขึ้นไป — generic จอดที่ single call หรือซื้อของสำเร็จ, supporting จอดที่ workflow, มีแต่ core ที่ปลายเปิดเท่านั้นที่มีสิทธิ์เป็น agent และยังต้องมี sandbox + guardrails + เงื่อนไขหยุดกำกับ อย่า default เป็น “สร้าง agent” และอย่าแม็ป agent หนึ่งตัวต่อ1 subdomain แบบอัตโนมัติ บทถัดไปจะลงไปในกล่องที่ผ่านเกณฑ์ agent จริง แล้วแปลง ubiquitous language ของมันให้เป็น system prompt ที่ระดับความสูงพอดี พร้อมชุด tool ที่ตั้งชื่อเป็น namespace ชัด
เจาะลึกแนวคิดในบทนี้ต่อได้ที่คลังอ้างอิง DevIQ และคอร์สที่เกี่ยวข้อง:
- Subdomain — การแบ่ง problem space เป็น core/supporting/generic ที่บทนี้ใช้เลือกขั้นบันได
- Strategic Design — ภาพรวมการตัดสินใจเชิงกลยุทธ์ของ DDD ที่ “ควรลงแรงตรงไหน” มาก่อน “สร้างด้วยอะไร”
- คอร์ส Bounded Contexts & Integration — ที่มาของ subdomain กับ bounded context ที่คอร์สนี้ยืมมาใช้กับ agent
เช็กความเข้าใจ — บทที่ 2
ข้อ 1 / 3บนบันไดการยกระดับ subdomain แบบ core (ปลายเปิด) กับ generic แม็ปกับขั้นไหน?