แยก context ด้วย sub-agent
หกบทที่ผ่านมาคุณ รักษา หน้าต่างของ agent Order ให้แน่นจากภายใน — retrieval ดึงเฉพาะที่เกี่ยวข้อง (บทที่ 2), memory ย้ายของออกไปนอกหน้าต่าง (บทที่ 3), การวัดงบ token (บทที่ 4), compaction สรุปประวัติที่ยาว (บทที่ 5) และการจัดระเบียบผลของ tool (บทที่ 6) บทนี้เพิ่มเครื่องมือ ชิ้นสุดท้าย เข้ากล่อง — และเป็นชิ้นที่ต้องเปิดคำเตือนตัวใหญ่ที่สุดกำกับ เพราะมันคาบเกี่ยวกับเรื่องสถาปัตยกรรมที่คอร์ส #12 ปักธงไว้แล้ว: การแยกงานบางส่วนไปให้ agent อีกตัวทำในหน้าต่างของมันเอง
บทนี้ต่อยอด agent Order ตัวเดิม (repo kaen-food-ordering, กำลังจัดทำ) เป็นบทกึ่งแนวคิด — code ที่แสดงคือ โครงบางๆ ของการเรียก sub-agent ไม่ใช่ระบบ multi-agent เต็มรูป (นั่นเป็นเรื่องของคอร์ส #12) เป้าหมายที่นี่แคบและชัด: มอง sub-agent ในฐานะ เทคนิคจัดการ context หนึ่งอย่าง ที่มีต้นทุนสูงและใช้เป็นทางเลือกสุดท้าย ทุก invariant ฝั่งแชตจากคอร์ส #15 (x-api-key, anthropic-version: 2023-06-01, ไม่ส่ง temperature, id claude-opus-4-8, อ่านคำตอบจาก content[]) ยังคงเดิมทั้งหมด
sub-agent คือขอบเขต context — ไม่ใช่การอัปเกรดสถาปัตยกรรม
หัวข้อที่มีชื่อว่า “sub-agent คือขอบเขต context — ไม่ใช่การอัปเกรดสถาปัตยกรรม”ก่อนอื่นต้องปักหมุดกรอบให้ถูก Sub-agentSub-agentการแยก subtask ออกไปให้ agent อีกตัวทำในหน้าต่างสะอาดของมันเอง แล้วคืนกลับมาแค่บทสรุปสั้น ๆ — เป็นเทคนิค Context Isolation ที่ใช้ 'อย่างประหยัด เป็นทางเลือกสุดท้าย' ไม่ใช่การอัปเกรดสถาปัตยกรรม สอดคล้องกับ #12 ที่ตั้ง single-agent เป็นค่าเริ่มต้น: Anthropic เองเตือนว่า multi-agent กิน token ~15 เท่า ต้องคุ้มค่างานจริงถึงจะคุ้ม — อย่าอ่านว่า 'หลาย agent ดีกว่า'Architecture ไม่ใช่ “ทีมของ agent หลายตัว” ที่คุณกระจายงานให้เพื่อความเท่ แต่คือ เทคนิคหนึ่ง สำหรับสิ่งเดียวที่คอร์สนี้สนใจมาตลอด — Context IsolationContext Isolationการกันความรกของ context งานหนึ่งไม่ให้ปนเข้าหน้าต่างของอีกงาน — sub-agent สำรวจเยอะ (ใช้ token นับหมื่น) แต่คืนแค่บทสรุปกลั่นมาแล้ว (~1–2 พัน token) จึงทำหน้าที่เป็น 'ขอบเขต compaction ที่บังคับเชิงโครงสร้าง' ไปในตัว เหมาะเมื่องานเป็นอิสระต่อกันและ tool result ดิบจะทำให้หน้าต่างล้น ต้นทุน coordination ตกอยู่ที่หน้าต่างของ agent แม่ที่เรากำลังรักษาArchitecture การกันความรกของงานหนึ่งไม่ให้ปนเข้าหน้าต่างของอีกงาน Anthropic อธิบายหลักการนี้ตรงๆ ว่า “Rather than one agent attempting to maintain state across an entire project, specialized sub-agents can handle focused tasks with clean context windows.” — แทนที่จะให้ agent ตัวเดียวแบกสถานะทั้ง project ก็ให้ sub-agent เฉพาะทางรับงานที่โฟกัสไปทำในหน้าต่างที่สะอาดของมัน
หัวใจอยู่ที่คำว่า isolated — “the detailed search context remains isolated within sub-agents, while the lead agent focuses on synthesizing and analyzing the results.” บริบทดิบๆ ที่เต็มไปด้วยรายละเอียดของงานค้นหาถูกกักไว้ ภายใน sub-agent ส่วน agent หลักเห็นแค่ผลลัพธ์ที่กลั่นแล้ว มองแบบวิศวกร context นี่คือ boundary ชนิดหนึ่ง: ความรกอยู่ข้างในกำแพง มีแต่ของสำคัญที่ข้ามกำแพงออกมา
และนี่คือมุมที่ทำให้ sub-agent เข้าล็อกกับบทที่ 5 พอดี — มันคือ compaction ที่คุณบังคับด้วยโครงสร้าง Anthropic ให้ตัวเลขไว้ชัด: “Each subagent might explore extensively, using tens of thousands of tokens or more, but returns only a condensed, distilled summary of its work (often 1,000-2,000 tokens).” — sub-agent อาจเผา token ไปหลายหมื่นในหน้าต่างของมัน แต่สิ่งที่คืนกลับเข้าหน้าต่างของ agent หลักมีแค่บทสรุปหลักพัน token แทนที่จะหวังพึ่งการสรุปตอนหลัง (บทที่ 5) คุณ ออกแบบ ให้รายละเอียดดิบไม่มีทางไหลข้ามกำแพงมาตั้งแต่แรก
flowchart TB
subgraph MONO["❌ agent เดียวแบกทุกอย่าง"]
direction TB
W1["หน้าต่างเดียว — บวมจนล้น<br/>ผลดิบออเดอร์ 40 รายการ<br/>+ ประวัติ + policy + งานหลัก"]
end
subgraph ISO["✅ แยกด้วย sub-agent"]
direction TB
LEAD["agent หลัก<br/>หน้าต่างสะอาด"]
SUB["sub-agent<br/>หน้าต่างของมันเอง<br/>เผาหลายหมื่น token"]
LEAD -->|"มอบงานค้น 40 ออเดอร์"| SUB
SUB -->|"คืนบทสรุป ~1–2 พัน token"| LEAD
end
MONO -.->|"ต้นทุน: ~15 เท่าของแชต<br/>ใช้เมื่อคุ้มค่างานเท่านั้น"| ISO
classDef bad fill:#7f1d1d,stroke:#450a0a,color:#fef2f2;
classDef good fill:#0891b2,stroke:#064e5b,color:#f8fafc;
class W1 bad;
class LEAD,SUB good;
คำบรรยายภาพ: ซ้าย/บนคือหน้าต่างเดียวที่บวมเพราะผลดิบของงานค้น 40 ออเดอร์ปนกับงานหลัก ขวา/ล่างคือการแยก: agent หลักมอบงานค้นให้ sub-agent ไปเผา token หลายหมื่นในหน้าต่างของมันเอง แล้วคืนกลับมาแค่บทสรุปหลักพัน token — หน้าต่างของ agent หลักจึงยังสะอาด แต่เส้นประเตือนว่าราคาของ isolation นี้คือ token ราว 15 เท่าของแชตธรรมดา ใช้เมื่อคุ้มค่างานเท่านั้น
สะพานเชื่อมกับคอร์ส #12: ค่าเริ่มต้นยังเป็น agent เดียว
หัวข้อที่มีชื่อว่า “สะพานเชื่อมกับคอร์ส #12: ค่าเริ่มต้นยังเป็น agent เดียว”ถ้าคุณผ่านคอร์ส #12 (agent เป็น bounded context) มาแล้ว คุณรู้จุดยืนนี้ดี — ตั้ง agent เดียวเป็น ค่าเริ่มต้น และถือ multi-agent เป็น ข้อยกเว้นที่ต้องมีเหตุผลรองรับ บทนี้ไม่ได้มาพลิกจุดยืนนั้น ตรงกันข้าม — มันคือการหยิบ เหตุผลรูปเดียว ที่ context engineering ให้สิทธิ์คุณแตกค่าเริ่มต้นได้มาวางบนโต๊ะ แล้วกำกับด้วยราคาของมันทันที
พูดเป็นประโยคเดียวให้จำ: ในคอร์ส #12 เราตั้งค่าเริ่มต้นไว้ที่ agent เดียว บทนี้เราเจอเหตุผลรูปเดียวที่ควรแตกค่านั้น — การแยก subtask อิสระที่จะท่วมหน้าต่างออกไป — และตัวเลขของ Anthropic เอง (15 เท่าของ token, ต้องคุ้มค่างาน) บอกให้จ่ายมันอย่างประหยัด
รากของจุดยืนนี้คือหลักเดียวกับที่คอร์ส #12 และ #15 ยึด — เริ่มจากสิ่งที่ง่ายที่สุดเสมอ Anthropic เขียนไว้ใน Building Effective Agents ว่าให้ “finding the simplest solution possible, and only increasing complexity when needed.” sub-agent คือการ เพิ่มความซับซ้อน อย่างชัดเจน: อีกหนึ่งหน้าต่าง อีกชุด prompt อีกช่องทางที่ผิดพลาดได้ ภาระพิสูจน์จึงอยู่ที่คุณว่างานนี้ จำเป็น ต้องใช้จริง ไม่ใช่อยู่ที่การหาข้ออ้างว่าทำไมไม่ใช้
ทั้งบทนี้พูดถึง sub-agent ในฐานะ ทางเลือกสุดท้าย ไม่ใช่ทางลัดสู่ระบบที่ดีกว่า ตัวเลข 15 เท่าและเงื่อนไข “ต้องคุ้มค่างาน” ที่คุณจะเห็นข้างล่างมีไว้เพื่อ จำกัดขอบเขต ของเทคนิคนี้ ไม่ใช่เพื่อโปรโมต ถ้างานของคุณไหลเป็นเส้นตรง (เช่นเคสคืนเงินทีละออเดอร์) คำตอบที่ถูกคือ agent เดียว จบ
เมื่อไรที่ isolation ช่วยจริง — และเมื่อไรที่มันแค่เผาเงิน
หัวข้อที่มีชื่อว่า “เมื่อไรที่ isolation ช่วยจริง — และเมื่อไรที่มันแค่เผาเงิน”Anthropic ระบุจุดที่ sub-agent เปล่งประกายไว้แคบมาก และแคบโดยตั้งใจ — “Multi-agent systems excel at valuable tasks that involve heavy parallelization, information that exceeds single context windows, and interfacing with numerous complex tools.” สามเงื่อนไข: งานที่ขนานกันหนักๆ, ข้อมูลที่เกินหน้าต่างเดียว, และการต่อกับ tool ซับซ้อนจำนวนมาก สังเกตว่าทั้งสามข้อล้วนเป็นปัญหา เรื่อง context — ปริมาณข้อมูลเกินงบ ไม่ใช่ปัญหาเรื่องตรรกะธุรกิจ
เหตุผลเชิงกลไกที่ isolation ได้ผลคือ sub-agent ทำงานขนานกันในหน้าต่างแยกของแต่ละตัว — “Subagents facilitate compression by operating in parallel with their own context windows, exploring different aspects of the question simultaneously.” และแต่ละตัวได้ “separation of concerns—distinct tools, prompts, and exploration trajectories—which reduces path dependency and enables thorough, independent investigations.” การแยกหน้าต่าง คือการแยก concern ในเชิง context โดยตรง
เทียบสองเคสบน agent Order ให้เห็นเส้นแบ่ง:
- ไม่ควรใช้ sub-agent — เคสคืนเงินทีละออเดอร์: ลูกค้าถามถึงออเดอร์เดียว →
getOrder→ เช็ก policy →issueRefundงานไหลเป็นเส้นตรง หน้าต่างไม่ท่วม การแตกไปอีก agent มีแต่เพิ่มต้นทุนและความหน่วงเปล่าๆ agent เดียวคือคำตอบ - isolation ช่วยจริง — เคส fan-out หลายสิบออเดอร์: ลูกค้าองค์กรถามว่า “ออเดอร์ 40 รายการเดือนที่แล้วรายการไหนส่งช้าเกิน SLA บ้าง” ถ้า agent หลักดึงผลดิบของทั้ง 40 ออเดอร์เข้าหน้าต่างเดียว มันบวมทันที การมอบงาน ค้นและกรอง 40 ออเดอร์ ให้ sub-agent ไปเผา token ในหน้าต่างของมัน แล้วคืนกลับมาแค่ “รายการที่ช้าเกิน SLA: #10432, #10871” คือการใช้ isolation ตรงจุด — ข้อมูลเกินหน้าต่างเดียวจริง และงานค้นแยกออกจากงานตอบลูกค้าได้สะอาด
ราคาที่ต้องจ่าย: ~15 เท่าของ token
หัวข้อที่มีชื่อว่า “ราคาที่ต้องจ่าย: ~15 เท่าของ token”นี่คือใบเสร็จที่ทำให้ทุกอย่างข้างบนกลายเป็น ทางเลือกสุดท้าย ไม่ใช่ค่าเริ่มต้น Anthropic วัดมาเอง — “agents typically use about 4× more tokens than chat interactions, and multi-agent systems use about 15× more tokens than chats.” agent ธรรมดากินราว 4 เท่าของแชต ส่วนระบบ multi-agent กินราว 15 เท่า และเงื่อนไขที่ตามมาคือกฎเหล็ก: “For economic viability, multi-agent systems require tasks where the value of the task is high enough to pay for the increased performance.” — มันจะคุ้มก็ต่อเมื่อมูลค่าของงานสูงพอจะจ่ายค่า token ที่เพิ่มขึ้นนั้น
15 เท่า และ 4 เท่า มาจากระบบวิจัย multi-agent ของ Anthropic (2025-06-13) เป็นค่าที่วัดจากงานแบบหนึ่งในช่วงเวลาหนึ่ง อย่าท่องเป็นสัจธรรมข้ามทุกงาน — สิ่งที่ ไม่ เปลี่ยนคือ ทิศทาง: การแตกไป sub-agent แพงกว่า agent เดียวอย่างมีนัยสำคัญเสมอ ดังนั้นภาระพิสูจน์ความคุ้มค่าตกอยู่ที่คนที่จะแตก
เอาสองด้านมาชนกัน: ด้าน1 isolation ประหยัดหน้าต่างของ agent หลัก (คืนแค่ 1–2 พัน token แทนหลายหมื่น) อีกด้าน ระบบทั้งระบบ กลับกิน token รวมมากขึ้นราว 15 เท่า เพราะ sub-agent ต้องเผา token ในหน้าต่างของมันเอง บวกค่าประสานงานที่ตกกลับมาที่ agent หลัก การประหยัด เฉพาะจุด กับต้นทุน รวมทั้งระบบ จึงเป็นคนละเรื่อง — และนี่แหละเหตุผลที่คุณกันเทคนิคนี้ไว้ใช้เฉพาะงานที่หน้าต่างเดียวรับไม่ไหวจริงๆ
โครง code บางๆ: sub-agent คือ IChatClient อีกตัวที่คืนแค่ string สรุป
หัวข้อที่มีชื่อว่า “โครง code บางๆ: sub-agent คือ IChatClient อีกตัวที่คืนแค่ string สรุป”ในทาง code sub-agent ไม่ใช่ framework วิเศษ — มันคือการเรียก IChatClient (จากคอร์ส #15) อีกครั้งหนึ่งในหน้าต่างของมันเอง โดยมีกติกาเหล็กข้อเดียว: สิ่งเดียวที่คืนกลับเข้า agent หลักคือ string สรุปสั้นๆ ผลดิบทั้งหมดต้องตายอยู่ในหน้าต่างของ sub-agent
using Microsoft.Extensions.AI;
// sub-agent = IChatClient อีกตัว ในหน้าต่าง (List<ChatMessage>) ของมันเอง// invariant ฝั่งแชตทั้งหมดจาก #15 คงเดิม: x-api-key, anthropic-version 2023-06-01,// "claude-opus-4-8", ไม่ส่ง temperature, อ่านคำตอบจาก content[]async Task<string> SearchLateOrdersAsync( string customerId, IChatClient subAgentChat, IList<AITool> orderTools){ // หน้าต่างสด ๆ — ไม่ share ประวัติกับ agent หลักเลย นี่คือ isolation List<ChatMessage> isolated = [ new(ChatRole.System, "You search a customer's orders and report ONLY the order ids that missed SLA. " + "Do the heavy lookups here. Return a short list, nothing else."), new(ChatRole.User, $"Customer {customerId}: which of last month's orders missed delivery SLA?") ];
var options = new ChatOptions { Tools = orderTools }; // getOrder/getDeliveryStatus เผาในหน้าต่างนี้ var reply = await subAgentChat.GetResponseAsync(isolated, options); // ไม่มี temperature (invariant #3)
// คืนเฉพาะบทสรุปกลั่นแล้ว ~1–2 พัน token — ผลดิบ 40 ออเดอร์ตายอยู่ใน isolated return reply.Text; // content[] อยู่ใต้ .Text ตามเดิม (invariant #5)}จุดที่ต้องเห็นให้ชัด: isolated เป็น List<ChatMessage> คนละก้อน กับประวัติของ agent หลัก — ผลของ getOrder/getDeliveryStatus ทั้ง 40 รอบพอกอยู่ในนั้นและถูกทิ้งไปพร้อมกับมัน สิ่งเดียวที่ agent หลักรับกลับคือ reply.Text ที่เป็นบทสรุป และค่าใช้จ่ายในการประสานงาน (system prompt ของ sub-agent, การส่งงานเข้า–รับสรุปออก) คือ token ที่ตกลงมาในหน้าต่างของ agent หลัก — งบก้อนเดียวกับที่คุณอุตส่าห์รักษามาหกบท ทุก token ที่ประสานงานมีราคา จึงต้องคุ้มกับงานที่หน้าต่างเดียวทำไม่ได้จริงๆ
สรุปบทที่ 7
หัวข้อที่มีชื่อว่า “สรุปบทที่ 7”sub-agent คือเทคนิค context isolation หนึ่งอย่าง ไม่ใช่การอัปเกรดสถาปัตยกรรม มันให้ subtask อิสระที่จะท่วมหน้าต่างไปทำในหน้าต่างสะอาดของมันเอง แล้วคืนแค่บทสรุปหลักพัน token — เป็น compaction ที่คุณบังคับด้วยโครงสร้าง มันช่วยจริงเฉพาะงานที่ขนานหนัก/ข้อมูลเกินหน้าต่างเดียว/ต่อ tool ซับซ้อนจำนวนมาก และราคาคือ token ราว 15 เท่าของแชต ที่คุ้มก็ต่อเมื่อมูลค่างานสูงพอ ค่าเริ่มต้นจากคอร์ส #12 ยังเป็น agent เดียวเสมอ บทนี้แค่เพิ่มเหตุผลรูปเดียวที่ให้สิทธิ์แตกค่านั้น — พร้อมใบเสร็จที่บอกให้จ่ายอย่างประหยัด บทหน้าเราร้อยทั้งหกชั้น (retrieval, memory, งบ token, compaction, จัดระเบียบ tool result และ isolation) เข้าเป็น context layer ตัวเต็มคร่อม agent Order
บทนี้อิงต้นทางที่ลงวันที่กำกับ อ่านต่อได้โดยตรง:
- Anthropic, “Effective context engineering for AI agents” (2025-09-29) — sub-agent ให้หน้าต่างสะอาดแยกกัน, บริบทค้นหาถูกกักไว้ภายใน sub-agent, และการคืนบทสรุปกลั่นแล้ว 1,000–2,000 token ในฐานะ compaction เชิงโครงสร้าง
- Anthropic, “How we built our multi-agent research system” (2025-06-13) — จุดที่ multi-agent เปล่งประกาย (งานขนานหนัก/ข้อมูลเกินหน้าต่างเดียว/tool ซับซ้อนจำนวนมาก), separation of concerns และใบเสร็จต้นทุน ~4 เท่า/~15 เท่า พร้อมเงื่อนไข “ต้องคุ้มค่างาน”
- Anthropic, “Building Effective Agents” (2024-12-19) — หลัก single-agent เป็นค่าเริ่มต้น: หาทางออกที่ง่ายที่สุดก่อน เพิ่มความซับซ้อนเมื่อจำเป็นเท่านั้น (ต่อเนื่องจากคอร์ส #12/#15)
เช็กความเข้าใจ — บทที่ 7
ข้อ 1 / 3sub-agent ถูกวางกรอบว่าเป็นอะไร?