Ubiquitous Language → system prompt + tools
บทที่ 2 ใช้ SubdomainSubdomainส่วนย่อยของปัญหาทางธุรกิจ (problem space) แบ่งเป็น core, supporting, generic — ก่อนจะออกแบบว่าจะมี agent กี่ตัวและแต่ละตัวทำอะไร ต้องวิเคราะห์ subdomain ของธุรกิจก่อนเสมอ ไม่ใช่เริ่มจากอยาก 'มี agent' แล้วค่อยหาเรื่องให้มันทำStrategic Design จำแนกว่ากล่องไหนในธุรกิจคู่ควรเป็น AgentAgentระบบซอฟต์แวร์ที่รับเป้าหมายแล้ววางแผน-ตัดสินใจ-เรียกใช้ tool ได้เองหลายรอบ (agentic loop) โดยไม่ต้องมีมนุษย์กำกับทุกก้าว ต่างจากโปรแกรมทั่วไปที่รันตามลำดับคำสั่งตายตัว — ในคอร์สนี้มองแต่ละ agent เหมือน1 Bounded Context ที่ต้องมีขอบเขต ภาษา และหน้าที่ของตัวเองชัดเจนArchitecture จริงๆ (core ที่ปลายเปิด) กล่องไหนควรเป็น workflow หรือแค่ tool ตอนนี้สมมติว่าเราได้ context หนึ่งที่ตัดสินแล้วว่าจะเป็น agent — เช่น “ดูแลลูกค้า” ของ ops-copilot คำถามของบทนี้คือ แล้วอะไรไปอยู่ข้างในมันบ้าง คำตอบสั้นๆ คือ Ubiquitous LanguageUbiquitous Languageภาษากลางที่ทีมและผู้เชี่ยวชาญธุรกิจใช้ร่วมกัน อิงกับ model โดยตรง — สำหรับ agent แล้ว ภาษานี้คือคำศัพท์ที่ปรากฏใน system prompt ชื่อ tool และ schema ของมันด้วย ถ้าคำใน code agent ไม่ตรงกับคำที่ผู้เชี่ยวชาญธุรกิจใช้ แปลว่ากำลังหลงทางStrategic Design ของ context นั้นแปลงร่างเป็นสองสิ่งที่จับต้องได้: System PromptSystem Promptชุดคำสั่งที่ฝังไว้ล่วงหน้าเพื่อกำหนดบทบาท ขอบเขตหน้าที่ ภาษา และกติกาของ agent ก่อนเริ่มสนทนาจริง เทียบได้กับสัญญา (contract) ที่ประกาศว่า Bounded Context นี้รับผิดชอบอะไร และปฏิเสธคำขอที่อยู่นอกขอบเขตArchitecture ที่ระดับความสูงพอดี กับชุด ToolToolfunction หรือ API ภายนอกที่ agent เรียกใช้ได้เพื่อกระทำสิ่งที่ model ภาษาเองทำไม่ได้ เช่น ค้นเว็บ อ่าน file เรียกฐานข้อมูล — ขอบเขตของชุด tool ที่ agent หนึ่งถืออยู่ก็คือส่วนหนึ่งที่นิยาม Bounded Context ของ agent นั้น ยิ่ง tool set กว้างเกินหน้าที่ ยิ่งเสี่ยงให้ agent ล้ำขอบเขตArchitecture ที่น้อย คม และตั้ง namespace ชัด นี่คือการแม็ปที่แข็งแรงที่สุดเส้นหนึ่งในคอร์ส — แข็งแรงพอที่จะสอนได้อย่างมั่นใจ เพราะคำศัพท์ที่ผู้เชี่ยวชาญธุรกิจพูดในห้อง Event Storming คือคำเดียวกับที่ควรโผล่ใน prompt และชื่อ tool ของ agent ตัวนั้นเป๊ะๆ
คอร์สนี้เป็น คอร์สออกแบบ ไม่ใช่ทัวร์ SDK — code ในบทคือ ภาพร่าง ของ system prompt, ชุด tool และโทโพโลยี (Thai Mermaid + pseudo-config สั้นๆ) ไม่ใช่ app ที่รันได้จริง ตัวอย่างต่อยอดจาก domain เดิมที่ repo kaen-food-ordering (กำลังจัดทำ) โดยมองมันผ่านเลนส์ใหม่: ระบบ ops-copilot ที่ช่วยทีมปฏิบัติการของ platform
ภาษาของ context คือวัตถุดิบของ prompt กับ tool
หัวข้อที่มีชื่อว่า “ภาษาของ context คือวัตถุดิบของ prompt กับ tool”ใน DDD ubiquitous language ไม่ใช่ “อภิธานศัพท์” ที่แขวนไว้เฉยๆ มันคือภาษาเดียวที่ทีมพูด model ใช้ และ code สะกดตาม ภายใน Bounded ContextBounded Contextขอบเขตที่ ubiquitous language และ model หนึ่งชุดมีความหมายคงเส้นคงวา นอกขอบเขตนี้คำเดียวกันอาจหมายถึงคนละอย่าง — เมื่อออกแบบระบบ agent ให้คิดว่าแต่ละ agent (หรือกลุ่ม agent ที่ทำงานร่วมกัน) ควรรับผิดชอบ Bounded Context เดียว ไม่ใช่ยัดทุกหน้าที่ไว้ใน agent เดียว หรือกระจาย agent ตามอำเภอใจStrategic Design หนึ่งอัน คำว่า “เคส” “การชดเชย” “SLA” มีความหมายคงเส้นคงวา พอเปลี่ยนสนามมาเป็น agent ภาษานี้ยังทำหน้าที่เดิม แต่ตกผลึกลงในที่ที่ต่างออกไปสองแห่ง:
- ลงใน system prompt — เป็นคำที่ agent ใช้บรรยายบทบาท ขอบเขต และหลักตัดสินใจของตัวเอง ถ้า prompt เรียกสิ่งที่ทีม CX เรียกว่า “เคส” ว่า “ticket bug report” ขึ้นมา แปลว่าภาษาเริ่มเพี้ยนตั้งแต่ต้นน้ำ
- ลงในชื่อ tool และ schema ของมัน — ชื่อ tool, ชื่อ parameter และรูปผลลัพธ์ ล้วนเป็นคำศัพท์ของ context นั้น agent อ่านชื่อ tool เพื่อเดาว่ามันทำอะไร เหมือนที่คนอ่านชื่อ function ชื่อที่ตรงภาษาคือครึ่งหนึ่งของเอกสาร
กล่าวอีกแบบ: prompt กับ tool คือ พื้นผิว ที่ ubiquitous language ของ context โผล่ออกมาให้ model เห็น ถ้าสองพื้นผิวนี้พูดคนละภาษากับที่ทีมพูด agent จะสับสนแบบเดียวกับโปรแกรมเมอร์ที่อ่าน code ซึ่งตั้งชื่อมั่ว
system prompt ที่ระดับความสูงพอดี
หัวข้อที่มีชื่อว่า “system prompt ที่ระดับความสูงพอดี”คำถามแรกไม่ใช่ “เขียน prompt ยังไงให้เก่ง” แต่คือ “เขียนที่ ระดับ ไหน” ทีม Applied AI ของ Anthropic เรียกจุดที่ถูกต้องว่า right altitude ใน Effective context engineering for AI agents (Anthropic, Sep 2025) — prompt ควรมี เฉพาะส่วนที่จำเป็นเพื่อกำหนดพฤติกรรมให้ครบ ไม่มากไปไม่น้อยไป มันคือโซนพอดีระหว่างสองความผิดพลาด:
- ต่ำเกินไป — ยัดกฎ if/else ราย-คำเข้าไปเป็นร้อยข้อ (“ถ้าลูกค้าพิมพ์คำว่า X ให้ตอบ Y”) เปราะมาก เคสที่ไม่ตรงคำเป๊ะๆ ร่วงหมด และไม่มีใครไล่แก้ทัน
- สูงเกินไป — เขียนกว้างลอย (“ช่วยลูกค้าให้ดีที่สุด”) จน agent ต้องเดาเอาเองว่าขอบเขตอยู่ตรงไหน อะไรทำได้ อะไรห้ามแตะ
agent: customer-supportsystem_prompt: | ถ้าลูกค้าพิมพ์ "เงิน" หรือ "คืน" ให้เรียก issue_refund ทันที ถ้าพิมพ์ "ช้า" ให้ตอบ "ขออภัยในความล่าช้า" ถ้าพิมพ์ "อาหารผิด" ให้... (ตามด้วยกฎ if/else อีกห้าสิบข้อ) # เปราะ: เคสที่พูดคนละคำแต่ความหมายเดียวกันร่วงหมด # อันตราย: ผูก issue_refund ที่ย้อนกลับไม่ได้กับแค่ keywordagent: customer-supportsystem_prompt: | บทบาท: คุณคือผู้ช่วยฝ่ายดูแลลูกค้าของ platform ฟู้ดเดลิเวอรี ขอบเขต: ตอบเรื่องสถานะเคส นโยบายคืนเงิน และช่วยร่างคำตอบ เรื่องครัว ราคาเมนู หรือการจัดคิวไรเดอร์ ไม่ใช่งานของคุณ — ส่งต่อ ภาษา: ใช้คำว่า "เคส" "นโยบาย" "การชดเชย" ตามที่ทีม CX ใช้จริง หลักตัดสินใจ: การกระทำที่มีเงินเกี่ยวข้องต้องให้คนอนุมัติก่อนเสมอ # พอดี: กำหนดพฤติกรรมครบโดยไม่ผูกติด if/else ราย-คำสังเกตว่า version พอดีไม่ได้สั้นที่สุด แต่มัน ครบ พอที่จะกำหนดพฤติกรรม — บอกว่าเป็นใคร รับผิดชอบแค่ไหน ปฏิเสธอะไร ใช้คำอะไร และเส้นความเสี่ยงอยู่ตรงไหน สิ่งที่มันจงใจ ไม่ ทำคือแจกแจงทุกสถานการณ์ล่วงหน้า เพราะนั่นคืองานของ model ไม่ใช่ของ prompt right altitude จึงเป็นเรื่องของ “ให้ heuristic ที่แข็งแรง แล้วไว้ใจให้ model ปรับใช้เอง” ไม่ใช่ “เขียน script ให้มันเดินตามทุกก้าว”
tool ที่น้อย คม และตั้ง namespace
หัวข้อที่มีชื่อว่า “tool ที่น้อย คม และตั้ง namespace”พื้นผิวที่สองคือชุด tool และหลักก็เหมือนกับ prompt: น้อยแต่คม ชนะเยอะแต่กำกวม สัญชาตญาณที่ผิดคือ “backend เรามี endpoint อะไร ก็ยกมาเป็น tool ให้ครบทุกอัน” — ได้ tool ที่เกือบซ้ำกันมากอง จนถึงจุดตัดสินใจ agent ต้องเลือกระหว่าง get_ticket_by_id, get_ticket_by_email, search_tickets_open ที่ทับซ้อนกัน Writing effective tools for AI agents (Anthropic) วางกฎไว้ที่นี่: ถ้าคนยังบอกไม่ได้ว่าควรใช้ tool ไหน agent ก็บอกไม่ได้เหมือนกัน tool ที่มากเกินไปไม่ได้เพิ่มความสามารถ มันเพิ่มจุดตัดสินใจกำกวม แล้วจุดกำกวมทุกจุดคือที่ที่ agent พลาดได้
บทความเดียวกันให้ทางแก้สองข้อที่ใช้ได้ทันที:
- รวม operation ที่เกี่ยวข้องไว้ใต้ parameter
action— แทนที่จะมี6 tool สำหรับ “หาเคส” ให้มี tool เดียวที่รับaction: get | searchจำนวน tool ลด จุดตัดสินใจก็ลดตาม - ตั้งชื่อตาม service/resource — ใช้ namespace อย่าง
support.ticket,support.replyแทนชื่อลอยๆ อย่างgetTicketnamespace บอกทั้งว่า tool นี้อยู่ context ไหน และช่วยไม่ให้ชื่อชนกันเมื่อระบบโต
tools: - get_ticket_by_id - get_ticket_by_email - get_ticket_by_order - search_tickets_open - search_tickets_closed - list_recent_tickets # หกวิธี "หาเคส" ที่เกือบซ้ำกัน — คนยังงงว่าจะใช้ตัวไหน agent ยิ่งงงtools: - name: support.ticket description: อ่านและค้นเคสของฝ่ายดูแลลูกค้า params: action: [get, search] # รวมหลาย operation ไว้ที่เดียว query: "เลขเคส อีเมล หรือเลขออเดอร์" - name: support.reply description: ร่างคำตอบถึงลูกค้า (ยังไม่ส่งจนกว่าคนจะอนุมัติ)tool คือจุดที่ agent จะไปแตะโลกจริง มันจึงเป็นที่ที่ Anti-Corruption LayerAnti-Corruption Layer (ACL)ชั้นแปลภาษา/model ที่กั้นระหว่าง context สองอัน ไม่ให้ model ของอีกฝ่ายรั่วเข้ามาปนเปื้อน — เมื่อ agent เรียก tool หรือ agent อื่นจากภายนอก ควรมีชั้นแปลผลลัพธ์กลับมาเป็นภาษาของ agent เราเอง ไม่ปล่อยให้ schema แปลก ๆ ของฝั่งนู้นไหลเข้ามาปนใน context ของเราStrategic Design จะมาอยู่ในบทที่ 6 — ชั้นแปลที่กันความรกของ backend ไม่ให้ไหลเข้ามาปน context บทนี้ปักหมุดแค่ รูป ของ tool surface ให้ตรงภาษาก่อน เรื่องการแปลข้ามระบบไว้ค่อยว่ากัน
ภาษาเป็นราย-context → prompt กับ namespace เป็นราย-agent
หัวข้อที่มีชื่อว่า “ภาษาเป็นราย-context → prompt กับ namespace เป็นราย-agent”เพราะ ubiquitous language นิยามอยู่ ภายใน bounded context หนึ่งๆ พื้นผิวทั้งสองจึงต้องเป็นราย-context ด้วย: agent “ดูแลลูกค้า” พูดภาษาเคส/นโยบาย และถือ namespace support.* เท่านั้น มันไม่ควรถือ kitchen.mark_ready หรือ rider.reassign เลย — ไม่ใช่เพราะกลัวมันทำพัง แต่เพราะ tool ของครัวมาพร้อม ภาษาของครัว และภาษานั้นจะรกอยู่ใน prompt ของ context ที่ไม่ได้พูดภาษาครัว การกันไม่ให้ support agent ถือ tool ครัวจึงเป็นการ รักษา ให้ภาษาของแต่ละ context คมและไม่ปนกัน — หลักเดียวกับที่ห้าม model Order ในครัวรู้เรื่องบิลลิ่ง
แต่ตรงนี้ต้องระวังไม่ให้เลยเถิด “ราย-context” ไม่ได้ แปลว่า “ต้องมี agent process แยกกันหนึ่งตัวต่อ1 context เสมอ” — บาง context เริ่มเป็น workflow ก่อน บางคู่ที่ภาษาใกล้กันพออาจอยู่ใน agent เดียวกันด้วยซ้ำ เส้นที่เราลากในบทนี้คือ เส้นภาษา ว่า prompt กับ tool namespace ชุดไหนควรอยู่ด้วยกัน ส่วนคำถามว่าจะแตกเป็นกี่ agent จริงคือเรื่องของ Multi-agentMulti-agentระบบที่มี agent มากกว่าหนึ่งตัวทำงานร่วมกัน แต่ละตัวควรมี Bounded Context ของตัวเองชัดเจนและเชื่อมกันผ่าน context map/handoff ที่ออกแบบไว้ — ไม่ใช่คำตอบสำเร็จรูปสำหรับทุกปัญหา หลายงานทำด้วย agent เดียวหรือ workflow ธรรมดาก็เพียงพอและเชื่อถือได้กว่าArchitecture ในบทที่ 5 ซึ่งต้องมีเหตุผลรองรับ ไม่ใช่แตกอัตโนมัติตาม subdomain — วินัยของทั้งคอร์สยังเหมือนเดิม: รู้ว่าอะไรควรอยู่ใน agent ที่มีขอบเขตดี ตัวเดียว ก่อน
แผนที่การแม็ป: ภาษา1 context สู่ prompt กับ tool
หัวข้อที่มีชื่อว่า “แผนที่การแม็ป: ภาษา1 context สู่ prompt กับ tool”flowchart TB
subgraph UL["Ubiquitous Language ของ context ดูแลลูกค้า"]
W["คำศัพท์ร่วมของทีม CX<br/>เคส · นโยบายคืนเงิน · การชดเชย · SLA"]
R["กฎที่ทีมพูดออกมา<br/>เงินเกี่ยวข้อง = ต้องมีคนอนุมัติ"]
end
subgraph AG["agent Customer-Support หนึ่งตัว = bounded context หนึ่งอัน"]
SP["System Prompt (ระดับความสูงพอดี)<br/>บทบาท + ขอบเขต + ภาษา CX + หลักตัดสินใจ<br/>เรื่องครัว/ไรเดอร์ = ส่งต่อ ไม่ใช่งานเรา"]
TS["Tool surface (ตั้ง namespace)<br/>support.ticket · action = get / search<br/>support.reply — ไม่มี kitchen.* / rider.* ปน"]
end
W ==>|"ภาษาเดียวกันไหลเข้า prompt"| SP
W ==>|"คำศัพท์กลายเป็นชื่อ tool/param"| TS
R ==>|"กฎกลายเป็นหลักตัดสินใจ + guardrail"| SP
classDef ul fill:#fef3c7,stroke:#b45309,color:#1a1a1f;
classDef ag fill:#c7d2fe,stroke:#3730a3,color:#1a1a1f;
class W,R ul;
class SP,TS ag;
คำบรรยายภาพ: ภาษาของ context “ดูแลลูกค้า” หนึ่งอัน (เหลือง) แตกเป็นสองพื้นผิวของ agent ตัวเดียว (น้ำเงิน) — คำศัพท์ร่วมไหลเข้าทั้ง system prompt และชื่อ tool/param ส่วนกฎที่ทีมพูดกลายเป็นหลักตัดสินใจใน prompt และ GuardrailGuardrailกติกาที่ควบคุมไม่ให้ agent ทำเกินขอบเขตหรือก่อความเสียหาย เช่น จำกัด tool ที่เรียกได้ ตรวจ output ก่อนส่งออก บังคับ human approval สำหรับการกระทำที่ย้อนกลับไม่ได้ — เป็นสิ่งที่รักษาขอบเขตของ Bounded Context ของ agent ให้ไม่ล้ำเส้นProcess สังเกตว่า tool surface สะอาด ไม่มี kitchen.* หรือ rider.* ปน — นั่นคือเส้นภาษาของ context นี้ ไม่ใช่คำสั่งว่าต้องแยก agent process ออกจากตัวอื่นเสมอ (บาง context เริ่มเป็น workflow หรือรวมกับตัวข้างๆ ได้ ถ้าภาษาใกล้กันพอ) และย้ำอีกชั้น: ลูกศรทั้งสามเป็น ความตั้งใจ ที่เขียนลง prompt ไม่ใช่ invariant ที่บังคับใช้แบบ atomic เหมือน aggregate — prompt สัญญาไม่ได้ว่า agent จะทำตามทุกครั้ง
prompt เป็น heuristic ไม่ใช่ schema
หัวข้อที่มีชื่อว่า “prompt เป็น heuristic ไม่ใช่ schema”จบบทด้วยคำเตือนที่ต้องพูดตรงๆ เพราะการแม็ปข้างบนแข็งแรงจนน่าหลงเชื่อเกิน: prompt กับชื่อ tool ที่เขียนดีแล้ว ก็ยังเป็นแค่ heuristic ไม่ใช่ schema เวลาเราเขียนใน prompt ว่า “เรื่องครัวไม่ใช่งานของคุณ” นั่นเป็น ความตั้งใจ ที่เราส่งให้ model ไม่ใช่กฎที่ระบบบังคับใช้ได้เอง มันต่างจาก aggregate ใน DDD ตรงนี้ชัดมาก: aggregate รักษา invariant แบบ atomic — code ปฏิเสธ transaction ที่ทำให้ยอดติดลบตรงๆ ไม่มีทางหลุด แต่ขอบเขตที่เขียนไว้ใน prompt เป็น best-effort ยิ่งพอ context ถูกบีบอัด (compaction) หรือสรุปย่อระหว่าง Agentic LoopAgentic Loopวงจรที่ agent ทำซ้ำจนกว่าจะบรรลุเป้าหมาย: รับ input → วางแผน/ตัดสินใจ → เรียก tool → สังเกตผลลัพธ์ → วนกลับไปตัดสินใจใหม่ — ต่างจากโปรแกรมทั่วไปที่รันเส้นทางเดียวจบ วงจรนี้เองที่ทำให้ agent ยืดหยุ่น แต่ก็เสี่ยง context rot ถ้าวนนานเกินไปโดยไม่มีขอบเขตProcess ยาวๆ คำสั่งเดิมอาจจางลงหรือถูกตีความใหม่ได้
นี่ไม่ใช่เหตุผลให้เลิกเขียน prompt ดีๆ — แต่เป็นเหตุผลว่าทำไม prompt เพียงอย่างเดียวไม่พอ และทำไมสามอย่างต่อไปนี้ถึงต้องมาเสริม: Agent MemoryAgent Memoryกลไกที่ agent เก็บข้อมูลข้ามรอบของ agentic loop หรือข้าม session เช่น สรุปบทสนทนาเก่า บันทึกข้อเท็จจริงระยะยาว หรือผลลัพธ์ก่อนหน้าที่ต้องอ้างอิงต่อ — ออกแบบให้ดีต้องเลือกว่าอะไรควรเก็บ อะไรควรทิ้ง ไม่ใช่ยัดประวัติทั้งหมดกลับเข้า context ทุกครั้งจนเกิด context rotArchitecture ที่เลือกเก็บสิ่งสำคัญไว้ไม่ให้หายตอนบีบอัด context, guardrail ที่บังคับกฎแข็งๆ นอก prompt (เช่น “ห้ามยิง tool คืนเงินถ้าไม่มี human approval” เป็น code จริง ไม่ใช่ประโยคใน prompt), และ EvalEvalการวัดผลอย่างเป็นระบบว่า agent ทำงานตรงตามที่ออกแบบไว้จริงหรือไม่ ด้วยชุดกรณีทดสอบและเกณฑ์ที่ชัดเจน แทนการดูจากความรู้สึกว่า 'ตอบดูดี' — จำเป็นเพราะ agentic loop มีความไม่แน่นอนสูงกว่า code ทั่วไป ต้องมี eval ก่อนเชื่อว่า Bounded Context ของ agent ทำงานถูกต้องตามสัญญาProcess ที่วัดว่า agent ทำตามขอบเขตจริงหรือไม่ พูดให้คม: ขอบเขตที่เขียนใน prompt ยังเป็นแค่สมมติฐานจนกว่า eval จะยืนยัน บทที่ 4 จะลงลึกเรื่องการรักษาบริบท1 agent ด้วยเครื่องมือสามอย่างนี้ พร้อมยอมรับจุดที่ agent ไม่ เหมือน aggregate อย่างตรงไปตรงมา
เจาะลึกแนวคิดในบทนี้ต่อได้ที่คลังอ้างอิง DevIQ:
- Ubiquitous Language — ภาษากลางที่ทีมและผู้เชี่ยวชาญธุรกิจใช้ร่วมกัน หัวใจที่บทนี้ยืมมาเป็นวัตถุดิบของ system prompt และชื่อ tool
- Bounded Context — ขอบเขตที่ model และภาษาหนึ่งชุดคงความหมายไว้ เหตุผลว่าทำไม prompt กับ tool namespace ถึงต้องเป็นราย-context
เช็กความเข้าใจ — บทที่ 3
ข้อ 1 / 3ทำไม tool ที่ "น้อยแต่คม" ถึงดีกว่าการยกทุก endpoint ของ backend มาเป็น tool ให้ครบ?