Composition & ecosystem (sampling, elicitation)
หกบทที่ผ่านมาเดินไปในทิศเดียวเป็นส่วนใหญ่: server เปิด primitive (tool/resource/prompt) ออกมา แล้ว host/client เป็นฝ่ายเรียกเข้าหา server การไหลของอำนาจจึงเป็น Host/Client → Server เกือบตลอด แต่การออกแบบ server จริงจะชนกำแพงหนึ่งเร็วมาก: บางที server เองต่างหากที่ต้องการอะไรบางอย่างกลับ — ต้องการให้ model ช่วยสรุป/ตัดสินกลางทาง หรือต้องการถามผู้ใช้เพิ่มเพราะข้อมูลไม่พอ MCP มีช่องให้ทำสองอย่างนี้ผ่านความสามารถที่ สลับทิศ คือ sampling และ elicitation และเมื่อถอยออกมามองภาพกว้าง คำถามสุดท้ายของการออกแบบไม่ใช่ “server ตัวเดียวควรเปิดอะไร” แต่คือ “เมื่อ host ถือ server หลายตัวพร้อมกัน มันประกอบกันเป็นระบบนิเวศแบบไหน และเราคุมสัญญา (contract) ระหว่างกันอย่างไร” บทนี้ตอบทั้งสองเรื่อง
คอร์สนี้เป็น คอร์สออกแบบ — code ในบทนี้คือ ภาพร่าง ของรูปแบบคำขอ sampling/elicitation และโทโพโลยีการประกอบหลาย server ไม่ใช่ server ที่รันได้จริง ตัวอย่างต่อยอดจาก domain เดิมที่ repo kaen-food-ordering (กำลังจัดทำ): server ออเดอร์ และ การเงิน ที่ต้องขอให้ model ช่วยจัดหมวดคำร้องเรียนกลางทาง (sampling) หรือถาม ops ยืนยันก่อนยิง refund (elicitation) โดยมี ops-copilot (host) เป็นตัวประกอบทั้งหมดเข้าด้วยกัน
Sampling: server ขอ completion จาก LLM ผ่าน client
หัวข้อที่มีชื่อว่า “Sampling: server ขอ completion จาก LLM ผ่าน client”SamplingSamplingกลไกที่ Server ขอให้ Client ยิง completion จาก LLM แทนตัวเอง (Server เองไม่ต้องผูก LLM key ของตัวเอง) เช่น ให้ model ช่วยสรุปผลลัพธ์กลางทางก่อนทำขั้นต่อไป — เป็นความสามารถฝั่ง Client สลับทิศทางจากปกติที่การเรียกไปทาง Host/Client → Server เท่านั้น spec กำหนดเป็นระดับ SHOULD ว่าผู้ใช้ควรได้รีวิวทั้ง prompt และผลลัพธ์ ไม่ใช่ MUST — ณ spec 2026-07-28 Sampling เป็น Deprecated ตาม SEP-2577 (ยังใช้งานได้ มีช่วงเปลี่ยนผ่านอย่างน้อย 12 เดือน) แนวทางที่เอกสารแนะนำแทนคือต่อ LLM provider API ตรง ๆ ส่วนคำขอที่ Server เป็นฝ่ายเริ่มถูกแทนด้วย Multi Round-Trip RequestsArchitecture คือกลไกที่ server ขอให้ client ยิง completion จาก LLM ให้ แทนที่ server จะต้องผูก LLM ของตัวเอง spec อธิบายไว้ว่ามันคือ “วิธีมาตรฐานให้ server ร้องขอการทำ LLM sampling… ผ่าน client… โดยไม่ต้องมี API key ฝั่ง server” (sampling, MCP spec 2025-11-25) method คือ sampling/createMessage — server ส่งชุดข้อความ (พร้อมเงื่อนไข) ขึ้นไป แล้ว client เป็นคนไปคุยกับ model จริงแล้วส่งผลกลับลงมา
จุดออกแบบสำคัญสามข้อ:
- server ไม่ถือ API key ของ LLM — นี่คือทั้งความสะดวกและเส้นความปลอดภัย server ที่คุณเขียนไม่ต้องมีสิทธิ์เข้าถึง model โดยตรง มันแค่ ขอ ให้ host จัดการให้ ค่าใช้จ่าย โควตา และการเลือกผู้ให้บริการ model จึงอยู่ที่ host ที่เดียว ไม่กระจายไปทุก server
- เลือก model ด้วยลำดับความสำคัญเชิงนามธรรม ไม่ใช่ล็อกชื่อรุ่น — server บอกความอยากได้ผ่าน
costPriority/speedPriority/intelligencePriority(บวก hint เป็นคำแนะนำ) แล้วปล่อยให้ host เลือกรุ่นจริงเอง (sampling, MCP spec 2025-11-25) การไม่ล็อกชื่อรุ่นตายตัวคือสิ่งที่ทำให้ server ยังเป็นกลางทางค่าย — server ตัวเดียวใช้ได้กับ host ที่หลังบ้านเป็น model คนละยี่ห้อ - มนุษย์ควรรีวิวทั้งขาออกและขาเข้า — spec กำหนดเป็น SHOULD ว่าผู้ใช้ควรได้เห็นและอนุมัติทั้ง prompt ที่ server ส่งออกไป และผลที่ model ตอบกลับ ก่อนมันจะไหลกลับเข้า server นี่คือหลักการ LLM Sampling Controls ข้อเดียวกับที่บทที่ 6 ยกมา — และย้ำอีกครั้งว่าเป็นข้อ แนะนำ ไม่ใช่ข้อบังคับ (MUST) อย่าออกแบบระบบโดยเดาว่าโพรโทคอลบังคับ human gate ให้แล้ว
เหตุที่ sampling ทรงพลัง (และอันตราย) คือมัน สลับทิศการควบคุม: ปกติ model เป็นคนเรียก tool ของ server แต่ตอน sampling กลายเป็น server ที่ยืมสมองของ model มาใช้กลางทาง ใน domain ฟู้ดเดลิเวอรี server ออเดอร์อาจขอให้ model ช่วยจัดหมวดคำร้องเรียนของลูกค้าเป็น “ของขาด / มาช้า / อาหารผิด” ก่อนตัดสินใจขั้นต่อไป — โดยที่ server เองไม่ต้องมี model ของตัวเอง
บทนี้อธิบาย sampling ตามฉบับ 2025-11-25 ซึ่งเพิ่ม parameter tools และ toolChoice (SEP-1577) ให้ completion วน tool-calling ได้เอง (changelog, MCP spec 2025-11-25)
ฉบับถัดมา 2026-07-28 ประกาศให้ Roots, Sampling และ Logging เป็น Deprecated ทั้งชุด (SEP-2577) ยังใช้งานได้อยู่และมีช่วงเปลี่ยนผ่านอย่างน้อยสิบสองเดือนตามนโยบายวงจรชีวิตฟีเจอร์ของ spec แต่ของที่เขียนใหม่ไม่ควรรับมันเข้ามา
เอกสารแนะนำให้ต่อ LLM provider API ตรงๆ แทน (deprecated features, MCP spec 2026-07-28)
อ่านบทนี้ต่อไปได้ตามปกติ เพราะสิ่งที่บทนี้สอนคือ ใครเป็นเจ้าของความสามารถ ไม่ใช่ชื่อ method · ข้อสรุปของบทไม่ได้เปลี่ยน และหัวข้อถัดจากนี้อธิบายว่าทำไมมันถึงไม่เปลี่ยน
Elicitation: server ขอ input มีโครงสร้างจากผู้ใช้ผ่าน client
หัวข้อที่มีชื่อว่า “Elicitation: server ขอ input มีโครงสร้างจากผู้ใช้ผ่าน client”ElicitationElicitationกลไกที่ Server ขอข้อมูลเพิ่มจากผู้ใช้กลางทางผ่าน Client เช่น ถามยืนยันก่อนลบข้อมูล หรือขอ parameter ที่ยังไม่ครบ — เป็นความสามารถฝั่ง Client เหมือน Sampling ทำให้ Server ไม่ต้องเดาหรือปฏิเสธ request เปล่า ๆ เมื่อข้อมูลไม่พอArchitecture คือพี่น้องของ sampling — แทนที่จะขอ “สมอง” ของ model มันขอ input จากผู้ใช้ spec นิยามมันเป็นกลไกที่ server ร้องขอข้อมูลเพิ่มจากผู้ใช้กลางทาง ผ่าน client โดยมี schema บอกว่าอยากได้อะไรกลับ (elicitation, MCP spec 2025-11-25) แทนที่ server จะต้องเดาหรือปฏิเสธคำขอเปล่าๆ เมื่อข้อมูลไม่ครบ มันหยุดแล้ว “ยกมือถาม” — เช่น ถาม ops ยืนยันก่อนยิง refund หรือขอเลขออเดอร์ที่ยังไม่ได้ระบุ ฉบับ 2025-11-25 ยังขยาย elicitation ให้รองรับโหมด URL (ให้ client พาผู้ใช้ไปทำบางอย่างบนหน้าเว็บ) ด้วย
สังเกตว่ารูปแบบมันเหมือน sampling เป๊ะ: server เป็นฝ่ายบอกว่ายังขาดอะไร แต่ client เป็นฝ่ายเดินเรื่องให้ทั้งหมด — ต่างกันแค่ปลายทางเป็น LLM (sampling) หรือเป็นผู้ใช้ (elicitation) ทั้งคู่จึงเป็นสมาชิกของครอบครัวเดียวกัน: “server ขอ X จากฝั่ง client”
ประโยคข้างบนจงใจไม่พูดว่า ใครเปิดคำขอบนสาย เพราะนั่นคือรายละเอียดที่ฉบับ 2026-07-28 เปลี่ยน ส่วนประโยคนี้ไม่เปลี่ยน
ทั้งคู่เป็นความสามารถฝั่ง client ไม่ใช่ primitive ของ server
หัวข้อที่มีชื่อว่า “ทั้งคู่เป็นความสามารถฝั่ง client ไม่ใช่ primitive ของ server”นี่คือประโยคที่ต้องจำให้แม่นที่สุดของบท: sampling และ elicitation ไม่ใช่ primitive ของ server primitive ของ server มีสามแบบเท่านั้น — Tool, Resource, Prompt (บทที่ 2) ส่วน sampling/elicitation เป็น capability ที่ client ประกาศว่ารองรับ แล้ว server ค่อยใช้ประโยชน์จากมันได้ (sampling, MCP spec 2025-11-25 · elicitation, MCP spec 2025-11-25)
ทำไมเส้นแบ่งนี้ถึงสำคัญ? เพราะ triad “ใครควบคุม” ของบทที่ 2 จะเบลอทันทีถ้าเอา sampling/elicitation ไปปนเป็น primitive แบบที่สี่/5 primitive ตอบคำถาม “model/app/ผู้ใช้ ใครเป็นคนตัดสินว่าจะเรียกของที่ server เปิดไว้” ส่วน sampling/elicitation เป็นคนละแกน — มันคือ ช่องทางย้อนทิศ ที่ server ใช้ยืมความสามารถของ client กลับมา ไม่ใช่ของที่ server “เปิดให้เรียก” การแยกสองแกนนี้ให้ขาดคือสิ่งที่ทำให้แบบจำลอง MCP ในหัวไม่พังตอนออกแบบจริง
primitive ของ server คือ Tool/Resource/Prompt เท่านั้น sampling และ elicitation เป็น capability ฝั่ง client ที่ server ขอใช้ — คนละแกนกับ triad “ใครควบคุม” ถ้ารวมมันเข้าไปในรายการ primitive เส้นแบ่ง model/app/user-controlled จะพัง และการให้เหตุผลเรื่องความปลอดภัย (ใครกดสวิตช์ ใครเห็นอะไร) จะคลาดทันที
Composition: host รวมหลาย server เป็นระบบนิเวศเดียว
หัวข้อที่มีชื่อว่า “Composition: host รวมหลาย server เป็นระบบนิเวศเดียว”ย้อนไปบทที่ 1: host หนึ่งตัวถือ client ได้หลายตัว (ตัวละ server) และเป็นศูนย์กลางเดียวที่เห็นบทสนทนาทั้งหมด เมื่อประกอบ server ออเดอร์ + ครัว + การเงินเข้าด้วยกัน host คือคนที่รวมสิ่งที่แต่ละ server ยื่น (ทั้ง primitive และคำขอ sampling/elicitation ที่ย้อนกลับมา) เข้าเป็นบทสนทนาเดียว พร้อมรักษาการแยกส่วนไว้ — server ตัวหนึ่งยังมองไม่เห็น server เพื่อนบ้านและมองไม่เห็นบทสนทนาทั้งหมด นี่คือหัวใจของการประกอบ: พลังเพิ่มขึ้นเพราะ copilot ต่อได้หลายระบบ แต่ host ต้องเป็นด่านที่คุม consent และกันไม่ให้ข้อมูลข้าม server กันเอง
flowchart LR
subgraph HOST["Host — รวมหลาย server + คุม consent/แยกส่วน"]
LLM["LLM + ตัวประสานงาน"]
CA["Client A"]
CB["Client B"]
end
SO["Server: ออเดอร์"]
SF["Server: การเงิน"]
CA <-->|"tool/resource/prompt<br/>Host/Client → Server"| SO
CB <-->|"session 1:1"| SF
SO -.->|"sampling: ขอ completion จาก LLM ผ่าน client"| CA
SO -.->|"elicitation: ขอ input มีโครงสร้างจากผู้ใช้ ผ่าน client"| CA
CA -.->|"ส่งต่อคำขอ + มนุษย์รีวิว (SHOULD)"| LLM
classDef host fill:#c7d2fe,stroke:#3730a3,color:#1a1a1f;
classDef srv fill:#bbf7d0,stroke:#065f46,color:#1a1a1f;
class LLM,CA,CB host;
class SO,SF srv;
คำบรรยายภาพ (รูปนี้คือรูปแบบบนสาย ณ ฉบับ 2025-11-25 · ฉบับ 2026-07-28 กลับหัวเส้นประให้เป็นการตอบกลับแทนการเปิดคำขอ ดูหัวข้อถัดไป): เส้นทึบคือทิศปกติ (Host/Client → Server เรียก tool/resource/prompt) ส่วนเส้นประคือทิศย้อนกลับ — server ออเดอร์ยิง sampling (ขอ completion จาก LLM) และ elicitation (ขอ input จากผู้ใช้) โดยทั้งคู่ ไหลผ่าน client ไม่ได้ทะลุไปหา LLM หรือผู้ใช้เอง host (สีน้ำเงิน) ถือ client หลายตัวและรวม server ทั้งหมด (สีเขียว) เข้าเป็นบทสนทนาเดียว พร้อมรักษาการแยกส่วน — server การเงินมองไม่เห็น server ออเดอร์ และไม่มี server ตัวไหนเห็นบทสนทนาทั้งหมด
ฉบับ 2026-07-28 กลับหัวรูปแบบบนสาย แต่ข้อสรุปข้างบนไม่ขยับ
หัวข้อที่มีชื่อว่า “ฉบับ 2026-07-28 กลับหัวรูปแบบบนสาย แต่ข้อสรุปข้างบนไม่ขยับ”จนถึงฉบับ 2025-11-25 คำขอฝั่งนี้เป็น request ที่ server เปิดขึ้นไปเอง ผ่านสายที่เปิดค้างไว้
· ชื่อ method คือ sampling/createMessage กับ elicitation/create
ฉบับ 2026-07-28 เปลี่ยนรูปแบบนี้ทั้งครอบครัวด้วย Multi Round-Trip Requests (MRTR) ตาม SEP-2322
· server เปิดคำขอเองไม่ได้อีกแล้ว สิ่งที่มันทำได้คือ ตอบกลับ request เดิมด้วยผลที่ยังไม่จบ
| ณ 2025-11-25 | ณ 2026-07-28 | |
|---|---|---|
| ใครเปิดคำขอบนสาย | server | client เท่านั้น |
| server บอกว่ายังขาดอะไรด้วยอะไร | sampling/createMessage · elicitation/create | ผลที่มี resultType: "input_required" ห่อ inputRequests |
| ใครเดินเรื่องต่อ | client | client — ยิง request เดิมซ้ำพร้อม inputResponses |
| server ได้อะไรกลับ | ผลของ request ที่ตัวเองเปิด | ผลของ request เดิมที่ถูกยิงซ้ำ |
ข้อสรุปของบทนี้คือ sampling และ elicitation เป็น capability ฝั่ง client ไม่ใช่ primitive ของ server · MRTR ไม่ได้ทำให้ข้อสรุปนั้นสั่นคลอน มันยืนยันให้แรงขึ้น เพราะตอนนี้ server เปิด call เองไม่ได้เลย ทำได้แค่บอกว่ายังขาดอะไร แล้ว client เป็นคนตัดสินว่าจะเดินเรื่องต่อหรือไม่
ส่วน primitive ของ server ยังเป็น Tool, Resource, Prompt สามตัวเท่าเดิม ไม่มีตัวที่สี่
วัดดูว่าคอร์สนี้ล้าไปกี่ข้อ
หัวข้อที่มีชื่อว่า “วัดดูว่าคอร์สนี้ล้าไปกี่ข้อ”ฉบับ 2026-07-28 มีการเปลี่ยนใหญ่เก้าข้อ · คอร์สนี้ประกาศตั้งแต่บทที่ 1 ว่าจงใจสอน
ชั้นที่ทนต่อการเปลี่ยน version — ฉบับนี้คือครั้งแรกที่ข้ออ้างนั้นถูกวัด
เก้าข้อนั้นแยกเป็นสามกอง ไม่ใช่สองกอง — และการแยกให้ครบสามคือสิ่งที่ทำให้ตัวเลขนี้ซื่อสัตย์
| กอง | กี่ข้อ | คืออะไร |
|---|---|---|
| ต้องแก้ file | 4 | MRTR · การประกาศ Deprecated · การถอด resources/subscribe · สายใหม่ที่มาแทนมัน |
| คอร์สไม่เอ่ยถึงเลย | 4 | handshake ตอนเริ่มการเชื่อมต่อ · ping กับ logging/setLevel · server/discover · โครงสร้าง result ใหม่ |
| เอ่ยถึง แต่ไม่ต้องแก้ | 1 | การถอด session ระดับโพรโทคอล |
สองแถวแรกเคยเป็นคนละตัวเลข และการที่มันขยับคือส่วนที่ควรอ่านให้ดีที่สุด
ตอนวัดครั้งแรก คอร์สสอน resources/subscribe อยู่หลายจุดขณะที่ฉบับใหม่ถอด method นั้นทิ้ง
· ตอนนั้นมันไม่นับเป็นงานแก้ เพราะทุกจุดเขียนกำกับไว้ว่า “ณ spec 2025-11-25” — นั่นคือ
วินัยการอ้างอิงทำงาน ไม่ใช่การเลือกชั้นที่ทนต่อการเปลี่ยน version ทำงาน สองกลไกนี้ช่วย
คนละเรื่อง และควรให้เครดิตแยกกัน
แล้วรอบถัดมาก็แก้มันอยู่ดี และเหตุผลไม่ใช่เพราะของเดิมพัง ป้ายกำกับ version กันคอร์ส
ไม่ให้ผิดได้ แต่มันกันผู้อ่านไม่ให้เดินออกไปพร้อมชื่อ method ที่ถูกถอดไปแล้วไม่ได้
· บทที่ 4 จึงเรียกชื่อสายใหม่ subscriptions/listen ตรงๆ พร้อมบอกสามอย่างที่ไม่เปลี่ยน
· สองแถวบนของตารางจึงขยับจาก 2/5/2 มาเป็น 4/4/1 — ตัวเลขนี้เป็นสถานะปัจจุบันของคอร์ส
ไม่ใช่บันทึกของการวัดครั้งแรก และมีด่านค้ำไว้ทั้งสองแถว
ข้อกำกับข้อที่สอง: ประโยคบอกสถานะเน่าตามปฏิทินเสมอ ไม่มีชั้นไหนกันได้ ประโยคอย่าง “ฉบับปัจจุบันคือ…” ล้าสมัยในวันที่ฉบับใหม่ออก โดยไม่เกี่ยวกับว่าคอร์สสอนกลไกไหน · คอร์สนี้เคยพลาดตรงนี้จริง ทั้งในข้อสอบท้ายบทที่ 1 และในคำอธิบายศัพท์ และตอนนี้มีด่านของ CI คอยจับให้แล้ว
Versioning ของ contract: server surface คือสัญญาที่มี version
หัวข้อที่มีชื่อว่า “Versioning ของ contract: server surface คือสัญญาที่มี version”พอประกอบหลาย server เข้าด้วยกัน สิ่งที่แต่ละ server เปิดออกมา — ชื่อ tool, schema parameter, รูปแบบ resource, schema ที่ elicitation คาดหวัง — ทั้งหมดนี้กลายเป็น contract ที่ host/agent ฝั่งตรงข้ามพึ่งพา ร้อยกลับเข้าเลนส์ของคอร์สพี่ (Agent as Bounded Context): server surface คือ ภาษาที่เผยแพร่ (published language) ของ bounded context นั้น และภาษาที่เผยแพร่ก็มี version เสมอ
นั่นแปลว่าการเปลี่ยน surface ของ server ที่ถูกประกอบอยู่ = การเปลี่ยน contract ที่อาจ breaking ต่อ consumer เปลี่ยนชื่อ tool, เพิ่ม field บังคับ, หรือปรับ schema elicitation ล้วนกระทบ agent ที่พึ่งภาษาชุดเดิม — เหมือนการแก้ published language ของ bounded context ที่มี downstream พึ่งอยู่ วินัยเดิมทั้งหมดจึงกลับมาใช้ตรงๆ: tool ที่ตั้งชื่อดีและเป็น ACL ที่แคบ (บทที่ 3, 5) ไม่ใช่แค่เรื่องความปลอดภัย แต่คือ contract ที่ เสถียรและอธิบายตัวเองได้ พอที่จะประกอบกับ server อื่นได้โดยไม่พังเงียบๆ เมื่อฝั่งใดฝั่งหนึ่งขยับ version
การต่อ server หลายตัวเข้า agent เดียวเพิ่มพลัง แต่ก็ประกอบ lethal trifecta (บทที่ 6) ได้ง่ายขึ้น — ข้อมูลลับจาก server หนึ่ง + เนื้อหาที่ควบคุมไม่ได้จากอีก server + ช่องส่งออก sampling/elicitation ยิ่งเพิ่มทิศทางที่ข้อมูลไหลได้ host จึงต้องเป็นด่านเดียวที่รักษา consent และการแยกส่วน ไม่ใช่หวังพึ่งให้ server แต่ละตัวคุมกันเอง (server มองไม่เห็นกันอยู่แล้ว)
- sampling = server ขอ completion จาก LLM ผ่าน client ด้วย
sampling/createMessage— ไม่ต้องมี API key ฝั่ง server, เลือก model ด้วย cost/speed/intelligence priority ไม่ใช่ล็อกชื่อรุ่น, มนุษย์ควร (SHOULD) รีวิวทั้ง prompt และผล และ ณ spec 2025-11-25 เรียก tool ได้เองจนกลายเป็น nested loop · ณ spec 2026-07-28 มันเป็น Deprecated แล้ว (SEP-2577) - elicitation = server ขอ input มีโครงสร้างจากผู้ใช้ ผ่าน client — พี่น้องของ sampling ในครอบครัว “server ขอ X จากฝั่ง client”
- ทั้งคู่เป็น capability ฝั่ง client ไม่ใช่ primitive ของ server (primitive มีแค่ Tool/Resource/Prompt) — คนละแกนกับ triad “ใครควบคุม” · MRTR ของฉบับ 2026-07-28 ยืนยันข้อนี้ให้แรงขึ้น เพราะ server เปิดคำขอเองไม่ได้อีกแล้ว
- host เป็นตัวประกอบ หลาย server เข้าเป็นบทสนทนาเดียว พร้อมรักษาการแยกส่วน และ contract ที่แต่ละ server เปิดออกมามี version — เปลี่ยน surface = เปลี่ยนภาษาที่เผยแพร่ที่ downstream พึ่งอยู่
บทนี้อ้างอิงแหล่งปฐมภูมิโดยตรง (ยังไม่มีการ์ด DevIQ สำหรับหัวข้อ sampling/elicitation ของ MCP โดยเฉพาะ):
- sampling (MCP spec 2025-11-25) — server ขอ completion จาก LLM ผ่าน client โดยไม่ต้องมี API key ฝั่ง server และเลือก model ด้วย priority เชิงนามธรรม
- elicitation (MCP spec 2025-11-25) — server ขอ input มีโครงสร้างจากผู้ใช้ผ่าน client
- changelog (MCP spec 2025-11-25) — SEP-1577 เพิ่ม tool-calling ให้ sampling ทำให้กลายเป็น nested loop
- คอร์ส Agent as Bounded Context — เลนส์ DDD (server surface เป็น published language, tool เป็น ACL) ที่เรื่อง versioning ของ contract ต่อยอด
เช็กความเข้าใจ — บทที่ 7
ข้อ 1 / 3sampling (sampling/createMessage) ให้ server ขอ completion จากใคร และด้วยเงื่อนไขอะไร?