การประสานงาน Multi-agent: 5 รูปแบบ และเมื่อใดที่รูปแบบเดียวชนะ
ใบแจ้งหนี้เดียวกัน แก้ 4 แบบและคิดราคาในตารางเดียว: orchestrator แพงกว่า agent เดี่ยว 1.66 เท่า แต่ได้คำตัดสินเดียวกัน
ในหน้านี้
บทที่ 24 จบด้วยคำถามที่มันสมควรได้รับ: เมื่อ sub-agent ผิด parent มองเห็นอะไรกันแน่?
บทนี้ตอบด้วยบิล งานเดียว — ลูกค้าโต้แย้งใบแจ้งหนี้และต้องการคำตอบ — แก้ 4 วิธี ทั้งหมดรัน บทที่ 23 harness กับ provider แบบสคริปต์เดียวกัน ทั้งหมดนับ token เดียวกันด้วย encoder เดียวกัน ทั้งหมดคิดราคาตามอัตราที่ บทที่ 16 อ่านเมื่อ 6 กันยายน 2026
| การจัดวาง | model call | input token | output | ต้นทุน | wall clock | คำตัดสิน |
|---|---|---|---|---|---|---|
| prompt chaining | 4 | 900 | 165 | $0.003780 | 1,648 ms | ผิด |
| agent เดียว, 4 เครื่องมือ | 5 | 2,697 | 179 | $0.007542 | 2,224 ms | ถูก |
| parallel sections | 9 | 2,910 | 324 | $0.009708 | 2,165 ms | ถูก |
| orchestrator-workers | 12 | 3,628 | 438 | $0.012512 | 5,090 ms | ถูก และพิสูจน์เองไม่ได้ |
อ่านแถวแรกกับแถวสุดท้ายคู่กัน: ระหว่างสองแถวนั้นคือข้อถกเถียงทั้งหมดที่อุตสาหกรรมนี้กำลังมีอยู่ การจัดวางที่ถูกที่สุดยังเร็วที่สุด และสร้างคำตอบที่มั่นใจ ผิด และส่งให้ลูกค้าได้ แบบแพงที่สุดตอบถูก ใช้เงิน 3.3 เท่าและเวลา 3.1 เท่า แล้วจบด้วยการอ้างข้อสรุปของ worker ที่มันไม่มีทางตรวจได้
แถวที่ไม่มีใครใส่ในตารางเหล่านี้คือแถวที่สอง: agent เดียวที่มีเครื่องมือ 4 อย่างได้คำตัดสินเดียวกับ orchestrator โดยใช้เงิน 60% และ wall clock 44% นี่ไม่ใช่ความชอบในความเรียบง่าย แต่เป็นการวัด และส่วนที่เหลือของบทนี้ว่าด้วยว่าเมื่อใดมันจึงหยุดจริง
แสดงรายละเอียด
สิ่งที่บทนี้ต้องใช้จากบทก่อนหน้า
- บทที่ 18 สำหรับสัญญาของเครื่องมือ: schema ที่โมเดลเห็น endpoint ที่มันไม่เคยเห็น agent ทั้งตัวซ่อนอยู่หลัง interface นี้ได้ ซึ่งก็คือทั้งหมดของ multi-agent
- บทที่ 22 สำหรับนิยาม “agent” ที่เผยแพร่แล้วสองแบบซึ่งไม่ตรงกัน และสำหรับเลขคณิตที่ว่า chain ของ prompt คือ N call
- บทที่ 23 สำหรับ loop, ทางออก 5 แบบ, run state และ trace การจัดวางทุกแบบด้านล่างคือไฟล์นั้น แต่ถูกเรียกคนละแบบ
- บทที่ 24 สำหรับราคาของ window และสิ่งที่หลุดออกจากมัน sub-agent คือกลยุทธ์ที่สี่จากสี่กลยุทธ์ และเป็นแบบเดียวที่เป็น agent ตัวที่สอง ไม่ใช่ policy
ไม่มี tensor ทุกอย่างที่นี่คือ TypeScript ยกเว้นการวัดสองชุดที่ทำกับโมเดล local จริง
งาน และกับดักที่อยู่ข้างใน
ลิงก์ไปยังส่วน: งาน และกับดักที่อยู่ข้างในบริษัทโปรตุเกสเขียนมาเรื่องใบแจ้งหนี้ FT-2026-0918 อีเมลบอกว่า VAT ดูผิด และแนบใบแจ้งหนี้: ยอดสุทธิ EUR 248.00, คิด VAT 21%, EUR 52.08, รวม EUR 300.08
ข้อเท็จจริงที่ต้องใช้เพื่อตอบอยู่ในสามที่ และมีเพียงที่เดียวที่อยู่ในอีเมล:
| อยู่ที่ไหน | บอกว่าอะไร |
|---|---|
| ใบแจ้งหนี้ที่แนบมา | ผู้ขายอยู่สเปน, ใช้ VAT 21%, EUR 52.08 |
| บันทึกคำสั่งซื้อ | ผู้ซื้อจดทะเบียนในโปรตุเกส, มีเลข VAT ที่ถูกต้อง, business-to-business |
| ตารางภาษี | อัตราในประเทศสเปน 21%; intra-EU business-to-business ที่มีเลขถูกต้อง, reverse charge, 0% |
เอาทั้งสามอย่างมารวมกันแล้วใบแจ้งหนี้ผิด: ต้องใช้ reverse charge, VAT ควรเป็นศูนย์, ต้องออก credit note EUR 52.08 ถ้ามองแค่ใบแจ้งหนี้ มันสมบูรณ์ทางเลขคณิต — 248.00 บวก 52.08 เป็น 300.08 — แล้วคุณจะตอบแบบนั้น
อีเมลระบุจริงว่า “เราเป็นบริษัทโปรตุเกส” แต่นั่นคือคำกล่าวอ้าง ไม่ใช่ record และไม่มีระบบ billing ไหนออก credit note จากคำกล่าวอ้าง กับดักนี้ไม่ใช่ลูกเล่น: มันคือรูปทรงปกติของงานธุรกิจ ที่การตัดสินใจต้องใช้ข้อเท็จจริงที่ไม่มีใครคิดจะไปดึงมา
ทุกอย่างข้างต้นรันกับ provider แบบสคริปต์ในสไตล์ของบทที่ 23 โดยมีกฎเดียว:
คำตอบใช้ได้เฉพาะข้อเท็จจริงที่อยู่ใน prompt ของมันเท่านั้น
“โมเดล” ขอเครื่องมือแต่ละอย่างที่มันมีครั้งเดียว ตามลำดับ catalogue แล้วใช้กฎคงที่กับข้อความที่มันเห็น ไม่มีอะไรถูกสคริปต์แยกตามการจัดวาง ดังนั้นความแตกต่างในตารางเปิดบทจึงไม่ใช่คำกล่าวอ้างเรื่องความฉลาดของโมเดล: มันคือการ routing ข้อมูลที่วัดได้ โมเดลจริงเพิ่มความล้มเหลวของตัวเองทับลงไป ไม่ได้ลบสิ่งเหล่านี้ออก
รูปแบบทั้งห้า ในราวสี่สิบบรรทัด
ลิงก์ไปยังส่วน: รูปแบบทั้งห้า ในราวสี่สิบบรรทัดชื่อทั้งห้าด้านล่างเป็นของ Anthropic จาก Building effective agents ซึ่งเป็นที่ที่ศัพท์ชุดนี้ลงตัว1 ไม่มีแนวคิดไหนในห้านี้ใหม่ และการบอกว่าบ้านไหนตั้งชื่ออะไร — และแนวคิดไหนเก่ากว่า — คือครึ่งหนึ่งของคุณค่าจากการรู้จักมัน
/* 1. Prompt chaining: a fixed pipeline. The control flow is yours. */
export async function chain(steps: Step[], first: string) {
let carry = first, all = first;
for (const s of steps) {
const r = await step(s.role, s.system, s.accumulate ? all : carry);
carry = r.text;
all = `${all}\n${r.text}`;
}
return carry;
}
/* 2. Routing: one cheap call picks the branch. The fallback is not a model. */
export async function route<T>(input: string, classify: Classifier,
routes: Record<string, Branch<T>>, fallback: Branch<T>) {
let label: string | undefined;
try { label = await classify(input); } catch { label = undefined; }
return ((label && routes[label]) || fallback)(input);
}
/* 3. Parallelisation. The pattern IS this line. */
export const parallel = <T>(workers: Branch<T>[], input: string) =>
Promise.all(workers.map((w) => w(input)));
/* 4. Orchestrator-workers: an agent behind a tool. Chapter 18's interface, unchanged. */
export function agentTool(o: WorkerSpec): Tool {
return {
name: o.name, description: o.description, readOnly: true,
parameters: { type: "object", properties: { question: { type: "string" } } },
async run(args: { question: string }) {
const child = newRun(o.system, args.question); // its own window
await runTracked(child, o.tools, o.usage); // its own limits
const conclusion = child.output ?? "no result";
if (!o.carryFindings) return conclusion;
return `${conclusion}\nFINDINGS ${evidence(child)}`;
},
};
}
/* 5. Evaluator-optimiser: make, judge, remake. Rounds are calls. */
export async function refine(make: Make, judge: Judge, maxRounds: number) {
let draft = "", feedback: string | undefined;
for (let r = 1; r <= maxRounds; r++) {
draft = (await make(feedback)).text;
const j = await judge(draft);
if (j.ok) return { draft, rounds: r };
feedback = j.note;
}
return { draft, rounds: maxRounds };
}นี่คือ toolkit ทั้งหมด: 5 ฟังก์ชัน ไม่มี framework และแบบ parallel คือบรรทัดเดียว — ซึ่งเป็นเหตุผลที่เขียนออกมาแทนที่จะวาด ตอนนี้ดูทีละแบบ พร้อมที่มา ราคา และกรณีที่มันผิด
Chaining และการตัดสินใจที่มันทำแทนคุณ
ลิงก์ไปยังส่วน: Chaining และการตัดสินใจที่มันทำแทนคุณPrompt chaining “แยกงานออกเป็นลำดับขั้น โดยแต่ละ LLM call ประมวลผล output ของ call ก่อนหน้า”1 แนวคิดนี้มาก่อนโมเดลภาษา: มันคือ pipeline พร้อม trade-off ของ pipeline — ความชัดเจน แลกกับ control flow ที่ถูกกำหนดไว้ก่อนข้อมูลจะมาถึง
สี่ขั้นสำหรับงานของเรา: ดึงฟิลด์ใบแจ้งหนี้, ตรวจเลขคณิต, ตัดสินว่าค้างอะไร, เขียนคำตอบ ที่นี่มันล้มเหลวสองแบบ ซึ่งสอนมากกว่าล้มเหลวครั้งเดียว
--- relay: each step sees only the previous step's output
extract: FIELDS invoice_id=FT-2026-0918 net=248.00 vat_rate_applied=21 vat_amount=52.08 ...
check: ARITHMETIC ok 248.00+52.08=300.08
decide: VERDICT=unknown reason=no_invoice_in_context
draft: "we are looking into invoice FT-2026-0918 and will come back to you."
--- accumulating: each step sees the email and everything produced so far
extract: FIELDS invoice_id=FT-2026-0918 net=248.00 vat_rate_applied=21 ...
check: ARITHMETIC ok 248.00+52.08=300.08
decide: VERDICT=invoice_correct reason=net_248.00_plus_21pct_vat_52.08_equals_300.08
draft: "we have checked FT-2026-0918 and it is correct... Nothing is owed back."relay chain มีต้นทุน $0.001940 และทำฟิลด์ใบแจ้งหนี้หายไประหว่างขั้นสองกับสาม เพราะขั้นสามได้รับเพียงประโยคเกี่ยวกับเลขคณิตและไม่มีอย่างอื่น มันสร้างข้อความพักเรื่องไว้: ไร้ประโยชน์ และเห็นชัดว่าไร้ประโยชน์
accumulating chain — แถวในตารางเปิดบท — มีต้นทุน $0.003780 ซึ่งแพงขึ้น 95% สำหรับ call เหมือนกัน 4 ครั้ง เพราะทุกขั้นตอนตอนนี้พกทุกอย่างก่อนหน้ามาด้วย มันสร้าง output อันตราย ลื่นไหล อ้างเลขคณิตของตัวเอง ถูกในทุกตัวเลขที่พูดถึง และบอกลูกค้าว่าไม่ค้างอะไรทั้งที่ค้าง EUR 52.08
ความต่างระหว่างสองแบบคือ ternary เดียว chain ที่พกข้อมูลน้อยกว่าให้คำตอบที่เห็นชัดว่าไม่ครบ; chain ที่พกทุกอย่างให้คำตอบที่ผิดอย่างมั่นใจ — และมีแต่แบบหลังที่ถูกส่งออกไป
ทั้งคู่ไม่ใช่ความล้มเหลวจริง ความล้มเหลวจริงคือ pipeline ตัดสินใจก่อนอ่านอะไรเลยว่างานนี้คือ 4 ขั้นบนเนื้อหาอีเมล ในโครงสร้างนั้นไม่มีที่ให้พูดว่า “ประเทศจดทะเบียนไม่ได้อยู่ในอีเมลนี้ ไปเอามา” Chaining ถูกต้องเมื่อ decomposition รู้ล่วงหน้าและเสถียร ที่นี่มันคือการเดา และการเดาถูกส่งออกไป
Routing แบบเก่าที่สุด และ plan B ที่ไม่มีใครเขียน
ลิงก์ไปยังส่วน: Routing แบบเก่าที่สุด และ plan B ที่ไม่มีใครเขียนRouting “จัดประเภท input และส่งมันไปยังงาน follow-up เฉพาะทาง”1 ชื่อใหม่ แต่กลไกคือ dispatcher ซึ่งเก่ากว่าแทบทุกอย่างในหนังสือนี้ สิ่งที่ใหม่คือ classifier เป็นโมเดลได้ — และนั่นทำให้มันล้มเหลวในแบบที่ switch ไม่เคยเป็น
const answer = await route(email,
(q) => classifyWithSmallModel(q), // cheap model, one call
{ billing: billingAgent, tax: taxAgent, dunning: dunningAgent },
taxAgent, // deterministic, chosen in advance
);สองเรื่องเกี่ยวกับ argument สุดท้ายนั้น มันไม่ใช่ error handling; มันคือ pattern router ที่ใช้โมเดลมี failure mode ที่ dispatcher ไม่มี: มันอาจคืน label ที่ไม่มีอยู่, timeout, หรือ — แบบแพง — คืน label ที่ดูสมเหตุสมผลแต่ผิดโดยไม่มีสัญญาณว่าผิด ทั้งสามต้องไปลงที่ไหนสักแห่ง และที่นั่นเป็น model call อีกครั้งไม่ได้ เพราะคุณอยู่ใน branch ที่ model call ล้มเหลวอยู่แล้ว
เรื่องที่สองคือ prompt ของ router เองไม่ได้ฟรี ในการเลือกโมเดล router ต้องมี catalogue ของโมเดลให้เลือก และทุก entry ในนั้นคือ input ที่ router ต้องจ่าย ก่อนที่มันจะได้อ่านคำถามของผู้ใช้ ที่อัตรา input ที่คอร์สนี้ใช้คิดราคา catalogue ขนาดราว 3,800 token ก็มีต้นทุนเท่ากับ agent run ห้า call ทั้งรอบในตารางเปิดบทแล้ว ในทางปฏิบัติ routing call รันบนโมเดลราคาถูก ซึ่งเป็นเหตุผลทั้งหมดที่ routing คุ้มทุน; แต่ควรคิดเลขในทิศทางนั้นให้จริง แทนที่จะสันนิษฐานเอา routing เป็นทางเลือกที่ผิดก็ต่อเมื่องานที่ถูก route มีราคาถูกกว่าการตัดสินใจ route เอง
Parallelisation: section และ voting ซึ่งคือ self-consistency
ลิงก์ไปยังส่วน: Parallelisation: section และ voting ซึ่งคือ self-consistencyAnthropic แยกข้อนี้เป็นสองอย่าง: sectioning — “แบ่งงานเป็น subtask อิสระที่รัน parallel” — และ voting — “รันงานเดียวกันหลายครั้งเพื่อให้ได้ output หลากหลาย”1 ทั้งคู่ใช้ภาพเดียวกัน แต่แทบไม่มีอะไรเหมือนกัน
Sectioning คือชัยชนะราคาถูก และเป็นบรรทัดจาก patterns.ts: specialist สามตัว — billing, tax, policy — แต่ละตัวมี window และเครื่องมือของตัวเอง บน email เดียวกัน แล้วมี synthesis call หนึ่งครั้งตอนท้าย งานเหมือนกัน เรียงสองแบบ:
| model calls | input | output | cost | wall clock | |
|---|---|---|---|---|---|
| worker สามตัว ทีละตัว | 9 | 2,910 | 324 | $0.009708 | 3,894 ms |
สามตัวเดิม, Promise.all | 9 | 2,910 | 324 | $0.009708 | 2,165 ms |
token ต่อ token เหมือนเดิม เร็วขึ้น 1.8 เท่า นั่นคือเหตุผลที่ pattern นี้สมควรมีชื่อของตัวเอง: มันเป็นแบบเดียวในห้าแบบที่ปรับปรุงบางอย่างโดยไม่เพิ่มต้นทุน ข้อแม้คือ section ต้องเป็นอิสระจริง ๆ — ให้ section B ใช้ข้อเท็จจริงที่ section A สร้าง แล้ว Promise.all จะรันทั้งคู่กับ state ที่ยังไม่มีอยู่ for loop ซ่อน bug นั้น; one-liner เปิดโปงมัน
Voting เป็นสัตว์อีกตัวที่ใส่ภาพเดียวกัน การรันคำถามเดียวกัน k ครั้งแล้วใช้เสียงข้างมากคือ self-consistency ซึ่ง Wang และคณะเผยแพร่ในเดือนมีนาคม 2022 ในฐานะ decoding strategy เกือบสามปีก่อนมีใครเรียกมันว่า orchestration pattern บทคัดย่อของงานนั้นชัดเจนทั้งกลไก — “sample ชุด reasoning path ที่หลากหลายก่อน แทนที่จะเอา greedy เพียงทางเดียว แล้วเลือกคำตอบที่สอดคล้องที่สุดด้วยการ marginalize reasoning path ที่ sample มา” — และผลลัพธ์: +17.9 จุดบน GSM8K2
มีสองอย่างตามมาที่ภาพไม่ได้บอก อย่างแรก voting ต้องใช้ sampling จาก บทที่ 17: ที่ temperature ศูนย์ sample ทั้ง k คือ sample เดียวกัน และเสียงข้างมากคือคำตอบเดียวที่จ่ายเงิน k ครั้ง อย่างที่สอง มันใช้ได้เฉพาะที่เสียงข้างมากมีความหมาย — สำหรับคำตอบใบแจ้งหนี้ด้านบนไม่มีอะไรให้นับ เพราะ draft 5 ฉบับคือประโยคต่างกัน 5 แบบ Voting เหมาะกับงานที่มีคำตอบสั้นและเทียบกันได้ ซึ่งตรงกับ benchmark ของ Wang พอดี และแทบไม่ตรงกับสิ่งที่ agent-facing customer ทำ
วัดที่นี่บนโจทย์คำ 3 ขั้น 20 ข้อ ซึ่งคำตอบคำนวณ ไม่ได้ตัดสิน โดยใช้โมเดล local ของบทที่ 23 reasoning ทีละขั้น:
| model calls | input | output | cost สำหรับ 20 ข้อ | correct | 95% interval | |
|---|---|---|---|---|---|---|
| one greedy chain | 20 | 1,330 | 2,649 | $0.034448 | 9/20 | 26–66% |
| majority of 5, temperature 0.8 | 100 | 6,650 | 13,245 | $0.172240 | 9/20 | 26–66% |
call มากขึ้น 5 เท่า, token มากขึ้น 5 เท่า, บิลมากขึ้นตรง ๆ 5 เท่า และไม่มีคำตอบถูกเพิ่มแม้แต่ข้อเดียว Voting คือการเดิมพัน ไม่ใช่การปรับปรุง และรอบนี้มันแพ้
ข้อควรระวังสองข้อ ก่อนใครจะยกสิ่งนี้ไปหักล้าง Wang การทดลอง 20 ครั้งแยก 45% ออกจาก 60% ไม่ได้ — interval กว้างเท่าข้ออ้าง ซึ่งคือวินัยของ บทที่ 4 ที่หันกลับมาใช้กับผลลัพธ์ของผมเอง และผลลัพธ์ที่ตีพิมพ์มาจากโมเดลที่ใหญ่กว่าหลาย order of magnitude ซึ่ง reasoning path หลากหลายที่ voting marginalize ทับนั้นหลากหลายจริง สิ่งที่ถ่ายโอนมาไม่ใช่ตัวเลข แต่คือ ตัวคูณนั้นแน่นอนและรู้ล่วงหน้า ส่วน gain ไม่ใช่
Orchestrator-workers และสิ่งที่ summary ไม่ใช่
ลิงก์ไปยังส่วน: Orchestrator-workers และสิ่งที่ summary ไม่ใช่ใน workflow orchestrator-workers “LLM ส่วนกลางจะแยกงานแบบ dynamic, มอบหมายให้ worker LLM, และสังเคราะห์ผลลัพธ์” และความต่างจาก sectioning คือ “subtask ไม่ได้ถูกกำหนดไว้ล่วงหน้า แต่ถูกกำหนดโดย orchestrator”1 ที่มาของแนวคิดนี้ไม่ได้มาจากโมเดลภาษาเลย: มันคือ master-worker และเวอร์ชันที่ worker เขียน finding ลงพื้นที่ร่วมให้ controller อ่านคือ blackboard architecture จากงานวิจัย speech understanding ในทศวรรษ 1970 สิ่งที่ใหม่ในปี 2026 คือ controller เป็นโมเดล ดังนั้น decomposition จึงตัดสินใจต่อ input ได้ — ซึ่งคือทั้งความยืดหยุ่นและต้นทุนในประโยคเดียว
มันใช้ 12 model call เทียบกับ agent เดี่ยว 5 call และได้คำตัดสินเดียวกัน แล้วมันทำบางอย่างที่ควรดูใกล้ ๆ:
orchestrator final: VERDICT=credit_note_due amount=52.08 source=worker_unverified
| PO_MISMATCH=yes source=worker_unverified
single agent: VERDICT=credit_note_due amount=52.08 reason=reverse_charge_should_have_applied
| PO_MISMATCH=yes invoice_says=PO-4417 order_says=PO-4471ทั้งคู่ถูก มีเพียงตัวเดียวที่รู้ว่าทำไม tax worker มีใบแจ้งหนี้, order และตารางภาษีใน window ของตัวเอง สรุปได้ และยังสังเกต — ทั้งที่ไม่มีใครถาม — ว่าเลข purchase order บนใบแจ้งหนี้ไม่ตรงกับ order แล้วมันคืน summary orchestrator ทำซ้ำทั้งสอง statement ได้แต่ตรวจไม่ได้สักอัน เพราะ evidence อยู่ใน window ที่มันไม่เคยเห็น นั่นคือคำถามปิดท้ายของบทที่ 24 ที่ได้คำตอบแล้ว: parent ได้ดูเท่าที่ child เลือกเขียนลงมา
วิธีแก้คือ flag และมันมีราคา:
| สิ่งที่ worker คืน | orchestrator input tokens | cost | parent ทำอะไรได้ |
|---|---|---|---|
| ข้อสรุปของมัน | 3,628 | $0.012512 | พูดซ้ำ |
| ข้อสรุปและ evidence | 4,065 | $0.013554 | derive ใหม่ และไม่เห็นด้วย |
input token มากขึ้น 12%, เงินมากขึ้น 8.3%, และวลี source=worker_unverified หายไปจากคำตอบ นี่คือ trade-off ในทุก multi-agent system และแทบไม่เคยถูกพูดตรง ๆ: clean window ของ child มีค่า, ความสามารถของ parent ในการ audit มันก็คุ้มที่จะจ่าย และคุณมีทั้งคู่ฟรีไม่ได้
ดังนั้น orchestrator-workers ผิดเมื่อไร? ที่นี่ ในงานนี้ มันซื้อคำตอบที่ถูกซึ่ง agent เดียวกับเครื่องมือ 4 อย่างเดียวกันก็ไปถึง ด้วยต้นทุน 1.66 เท่าและ wall clock 2.3 เท่า และทำให้คำตอบนั้นปกป้องยากขึ้น คำแนะนำของ Anthropic เองพูดไว้ก่อนเริ่ม pattern: หา “วิธีที่ง่ายที่สุดเท่าที่เป็นไปได้ และเพิ่มความซับซ้อนเมื่อจำเป็นเท่านั้น” เพราะ “agentic systems มักแลก latency และ cost กับ task performance ที่ดีขึ้น”1 ตารางด้านบนคือประโยคนั้นที่ใส่ตัวเลขไว้ข้างใต้
Evaluator-optimiser และผู้ตัดสินที่เขียนข้อสอบเอง
ลิงก์ไปยังส่วน: Evaluator-optimiser และผู้ตัดสินที่เขียนข้อสอบเองcall หนึ่ง generate, อีก call evaluate แล้ว loop ซ้ำจน evaluation ผ่าน1 บรรพบุรุษที่ตีพิมพ์คือ Self-Refine — โมเดลเดียวกันเป็น “generator, refiner, and feedback provider” รายงานการปรับปรุงแบบ absolute เฉลี่ยราว 20 จุดใน 7 งาน3 — และ Reflexion ซึ่งเก็บ critique ไว้ใน episodic buffer ข้าม attempt และรายงาน pass@1 91% บน HumanEval ขณะที่ baseline ได้ 80%4
cost model เป็นแบบที่ง่ายที่สุดในห้าแบบ: สอง call ต่อรอบ และจำนวนรอบไม่ใช่ของคุณ refinement 3 รอบบนงานที่เดิมใช้ call เดียวคือ 6 call ดังนั้น floor ของ pattern คือ 6× และ ceiling คือ cap ใดก็ตามที่คุณตั้ง — ทำให้ budget exit ของบทที่ 23 เป็นสิ่งบังคับ ไม่ใช่แค่ทำให้เรียบร้อย
ceiling ละเอียดกว่า และวัดได้ บนโจทย์ 20 ข้อเดิม โมเดล local ตอบถูก 9 ข้อ จากนั้นเอาคำตอบเหล่านั้นให้มันดูและถามว่าถูกไหม — โดยไม่บอกว่าคำตอบเป็นของมันเอง ซึ่งตัด confound เรื่องการเยินยอออกและเหลือเรื่อง capability:
| คำตอบของโมเดลเอง | มันตอบ “yes” | มันตอบ “no” |
|---|---|---|
| 9 ข้อที่ถูก | 9 | 0 |
| 11 ข้อที่ผิด | 3 | 8 |
นั่นเป็น judge ที่ดีกว่าชื่อ section บอกไว้ และการพูดแบบนั้นคือประเด็นของการวัดแทนการยืนยัน: มันไม่บล็อกสิ่งที่ถูกเลย และจับความผิดพลาดได้ 8 จาก 11 ในฐานะ filter มันคุ้มค่า call
ในฐานะ stopping rule ซึ่งเป็นสิ่งที่ evaluator-optimiser loop ใช้จริง ๆ การอนุมัติ 3 ครั้งนั้นคือเรื่องทั้งหมด: มันจบ loop พร้อมคำตอบผิดในมือ และจำนวนรอบเพิ่มแค่ไหนก็ไม่มีทางไปถึงพวกมัน refinement loop ไม่อาจถูกต้องกว่า judge ของมัน ซื้อรอบเพิ่มคือซื้อ attempt ต่อ error ที่ judge มองเห็นในราคาเต็ม และไม่ได้อะไรเลยกับ error ที่มันมองไม่เห็น
ดังนั้นกฎคือ: evaluator คุ้มค่า call เฉพาะเมื่อมันมีบางอย่างที่ generator ไม่มี compiler, test suite, schema validator, โมเดลคนละตัว, มนุษย์ ผลลัพธ์ของ Self-Refine เองวัดกับ human preference และ task metric ไม่ใช่ความเห็นของโมเดลต่อตัวเอง ถ้าข้อได้เปรียบเดียวของ evaluator คือ prompt ต่างกัน คุณกำลังจ่ายสองเท่าเพื่อความเห็นพ้อง บทที่ 29 สร้างเวอร์ชันที่มีข้อได้เปรียบจริง: golden set พร้อมคำตอบที่เขียนไว้ล่วงหน้า
Loop ไม่ใช่ pattern
ลิงก์ไปยังส่วน: Loop ไม่ใช่ patternห้าแบบข้างต้นคือรูปร่างของโค้ด ของคุณ ใต้พวกมันมีตระกูลที่สองซึ่งมักถูกจัดไว้ข้างกันแต่ไม่ควรเป็น: ReAct, Reflexion, plan-and-execute และ tree of thoughts คือ reasoning loop และต้นทุนของมันอยู่ใน request
บทที่ 12 ว่าด้วย reasoning ภายในโมเดล ซึ่งคุณจ่ายเป็น output token ใน call เดียว นี่คืออีกแบบหนึ่ง ความต่างสำคัญเมื่อบิลมาถึง: chain of thought ที่ยาวขึ้นทำให้ call เดียวแพงขึ้น และ reasoning loop ทำให้งานเดียวกลายเป็นหลาย call ซึ่งแต่ละ call ส่งทุกอย่างก่อนหน้าซ้ำ — quadratic ที่บทที่ 23 วัดไว้ในตาราง runaway
| loop | call ต่องาน | call เพิ่มซื้ออะไร |
|---|---|---|
| ReAct | หนึ่งต่อขั้น จนกว่าจะหยุด | โมเดล react ต่อสิ่งที่เครื่องมือคืนมา5 |
| plan-and-execute | หนึ่งเพื่อ plan แล้วหนึ่งต่อขั้น | plan ถูก fix ก่อนขั้นแรกจะรัน6 |
| Reflexion | attempts × (act + reflect) | critique อยู่รอดไป attempt ถัดไป4 |
| tree of thoughts | branching factor × depth, บวก evaluation หนึ่งต่อ node | search พร้อม backtracking7 |
paper tree-of-thoughts เผยแพร่ตารางต้นทุนของตัวเอง ซึ่งหายากกว่าที่ควร บน Game of 24 ด้วย GPT-4: input/output prompting best-of-100 แก้ได้ 33% ที่ $0.13 ต่อเคส, chain of thought best-of-100 แก้ได้ 49% ที่ $0.47, และ tree of thoughts แก้ได้ 74% ที่ $0.74 โดยผู้เขียนระบุว่า “อาจต้องใช้ generated tokens มากกว่า CoT 5-100 เท่า”7
ราคาเกือบ 6 เท่าของวิธีถูกเพื่อ success rate มากกว่าสองเท่าเล็กน้อย นั่นคุ้มหรือไม่ขึ้นอยู่กับว่าเคสที่ล้มเหลวมีต้นทุนต่อคุณเท่าไร — คำถามที่ต้องถามก่อนรับสี่แบบนี้ไปใช้
คอร์สนี้ไม่ reimplement พวกมัน ทั้งสี่มี reference implementation โดยผู้เขียนเองใน Python และคุณค่าของมันคือการเป็นแหล่งต้นทาง ไม่ใช่คำแปล: ysymyth/ReAct, noahshinn/reflexion, princeton-nlp/tree-of-thought-llm และ AGI-Edgerunners/Plan-and-Solve-Prompting อ่าน prompt ใน repository เหล่านั้น; prompt คือ paper
สอง topology และหนึ่งในนั้นไม่กลับมา
ลิงก์ไปยังส่วน: สอง topology และหนึ่งในนั้นไม่กลับมาตอนนี้เข้าสู่ multi-agent จริง ที่ซึ่งความสับสนส่วนใหญ่อยู่ มีสองวิธีที่ agent หนึ่งทำให้อีก agent เข้ามาเกี่ยวข้อง พวกมันไม่ใช่ variant และความต่างคือ หลังจากนั้นใครคุมอยู่
Agent เป็นเครื่องมือ parent เรียกมัน ได้คำตอบ แล้วทำต่อ มันคือ tool interface ของบทที่ 18 ที่มี agent ทั้งตัวอยู่ข้างหลัง และ parent ไม่เคยเสียการควบคุม นี่คือสิ่งที่ orchestrator ด้านบนทำ
Handoff parent โอนบทสนทนาและไม่ได้คืน guide ของ OpenAI พูดชัดที่สุด: handoffs คือ “การโอนทางเดียวที่อนุญาตให้ agent มอบหมายให้อีก agent... ถ้า agent เรียก handoff function เราจะเริ่ม execution ทันทีบน agent ใหม่ที่ถูก handoff ไป พร้อมโอน conversation state ล่าสุดด้วย”8
คำเตือนเรื่องศัพท์ เพราะเรื่องนี้ทำคนสะดุดเสมอ: “handoff” เป็นคำของ SDK หนึ่ง ไม่ใช่มาตรฐาน มันคือ terminology จาก OpenAI Agents SDK และ guide นั้น ซึ่งยังเรียกสองการจัดวางว่า “manager” และ “decentralized” และระบุว่าใน manager pattern “edge แทน tool call ส่วนใน decentralized pattern edge แทน handoff”8 ในพื้นที่นี้ มี มาตรฐานเปิด — A2A เวอร์ชัน 1.0.0 ภายใต้ลิขสิทธิ์ของ Linux Foundation มีประวัติ release ที่ versioned และรายการ breaking changes ที่ documented หลักการที่ระบุไว้คือ opaque execution: agents “collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations”9 นั่นไม่ใช่ handoff และการเปรียบเทียบอยู่ใน บทที่ 26 สิ่งสำคัญตรงนี้คือคำหนึ่งเป็น API ของ library และอีกคำเป็น specification ที่มี governance
ความแตกต่างคือ data structure ไม่ใช่ diagram:
export type EdgeKind = "tool" | "handoff";
export interface AgentEdge { from: string; to: string; kind: EdgeKind }
export interface AgentGraph { root: string; agents: Record<string, AgentSpec>; edges: AgentEdge[] }
/** One agent may not be both a tool of X and a handoff target of X. */
export function conflicts(g: AgentGraph): AgentEdge[] {
const seen = new Map<string, EdgeKind>();
const bad: AgentEdge[] = [];
for (const e of g.edges) {
const key = `${e.from}->${e.to}`;
const other = seen.get(key);
if (other && other !== e.kind) bad.push(e);
else seen.set(key, e.kind);
}
return bad;
}
/** Every agent reachable from the root, and at what depth. */
export function reachable(g: AgentGraph): Map<string, number> {
const depth = new Map([[g.root, 0]]);
const queue = [g.root];
while (queue.length) {
const id = queue.shift()!;
for (const e of g.edges.filter((x) => x.from === id)) {
if (depth.has(e.to)) continue;
depth.set(e.to, depth.get(id)! + 1);
queue.push(e.to);
}
}
return depth;
}ยี่สิบบรรทัด bug สองตัวที่ไม่อย่างนั้นคุณจะไปเจอใน production reachable หา agent ที่ไม่มีใครเข้าถึงได้ — configured, paid for, never called conflicts ปฏิเสธ edge ที่เป็นทั้งสองชนิดพร้อมกัน ซึ่งฟังดูจู้จี้จนกว่าคุณจะอ่านออกเสียง: parent ทั้งคุมต่อและปล่อยมือ รันบนระบบ 5 agent ที่มี orphan หนึ่งตัวและ double edge หนึ่งอัน:
reachable: lead@0 billing@1 tax@1 dunning@1
orphans: ghost
conflicts: lead->taxอะไรข้าม boundary จริง ๆ
ลิงก์ไปยังส่วน: อะไรข้าม boundary จริง ๆตอนนี้คือการวัดที่ section นี้มีไว้ และเป็นการวัดเดียวในบทที่ทำกับโมเดลจริง ไม่ใช่แบบสคริปต์
ลูกค้าระบุ constraint ในข้อความแรก — บัญชีของเราจดทะเบียนในโปรตุเกส ไม่ใช่สเปน; ทุกอย่างเกี่ยวกับภาษีต้องใช้โปรตุเกส — คุยเรื่องอื่น แล้วถามคำถามที่ billing ต้องตอบ เคสถูกโอน 24 trials ประเทศและบริษัทต่างกันทุกครั้ง payload การโอน 4 แบบ และ agent ผู้รับถูกถามคำถามเดียว: บัญชีของลูกค้ารายนี้จดทะเบียนในประเทศใด?
| สิ่งที่ถูกโอน | payload เฉลี่ย | constraint อยู่ในนั้น | specialist จำได้ | 95% interval |
|---|---|---|---|---|
| บทสนทนาทั้งหมด | 173 tokens | 24/24 | 20/24 — 83% | 64–93% |
| summary ที่ sending agent เขียน | 62 tokens | 1/24 | 0/24 — 0% | 0–14% |
| เฉพาะข้อความล่าสุดของผู้ใช้ | 61 tokens | 0/24 | 0/24 — 0% | 0–14% |
| typed record | 69 tokens | 24/24 | 24/24 — 100% | 86–100% |
แถวที่สามคือ control และทำตัวเหมือน control: fact ไม่อยู่ จึงจำไม่ได้ อีกสามแถวคือ finding
transcript เต็มมี 173 tokens และใช้ได้ 83% ของเวลา ความล้มเหลวสี่ครั้งเป็นเรื่องของบทที่ 24 ไม่ใช่บทนี้ typed record คือ 69 tokens — มากกว่า summary เจ็ด token — และใช้ได้ทุกครั้ง เพราะ constraint อยู่ใน field ที่มีชื่อ แทนที่จะเป็นประโยค
และ summary คือแถวที่ต้องจ้อง มันล้มเหลว 24 จาก 24 ครั้ง และเหตุผลไม่ใช่ว่าผู้อ่านพลาด constraint ปรากฏใน summary เพียง 1 จาก 24 ครั้งเท่านั้น receiving agent ไม่ได้สะเพร่า; มันได้รับข้อความที่ไม่มีคำตอบ summary คือ compaction ที่คุณไม่ได้เขียน ผลิตโดยโมเดลที่คุณมองไม่เห็น window ของมัน ปรับให้เหมือน summary เวลาอ่าน — และ “ลูกค้าบอกว่า record ของเรามีประเทศผิด” คือ clause แบบที่ summariser ทิ้งเป็น procedural noise พอดี
ขีดจำกัดที่ซื่อสัตย์ของตัวเลขนั้น: summariser เป็นโมเดลครึ่งพันล้าน parameter และโมเดลใหญ่กว่าน่าจะเก็บได้มากกว่า สิ่งที่ไม่ดีขึ้นตามขนาดคือรูปทรงของความเสี่ยง — sending agent ตัดสินใจต่อ handoff ต่อ phrasing แบบที่สังเกตไม่ได้ ว่า fact ไหนรอด typed record ไม่ขึ้นกับ judgment นั้นเลย ซึ่งเป็นเหตุผลที่มันชนะโดยโครงสร้าง ไม่ใช่โดย intelligence อะไรก็ตามที่ต้องรอดจากการโอนควรเป็น field ไม่ใช่ประโยค
เหตุผลเดียวกันใช้กลับทิศได้กับ topology agent-as-tool และตารางก่อนหน้าก็ตีราคาไว้แล้ว: สิ่งที่กลับจาก worker ก็เป็น summary เช่นกัน และการจ่ายเพิ่ม 8.3% เพื่อรับ evidence มาด้วยคือวิธีแก้เดียวกันที่มองจากฝั่ง parent
เมื่อ agent เดียวชนะ
ลิงก์ไปยังส่วน: เมื่อ agent เดียวชนะข้อเท็จจริงปิดท้ายสามข้อ ทั้งหมดมาจากตารางด้านบน
multi-agent system คูณจำนวน call และ call เป็น quadratic ตาม context orchestrator ทำ 12 model call ขณะที่ agent เดี่ยวทำ 5 และแต่ละตัวพก transcript ที่โตขึ้นของตัวเอง — 3,628 input token เทียบกับ 2,697 ช่องว่างนี้จะกว้างขึ้นตามความยาวของงาน
ทุก boundary คือ channel ที่สูญเสียข้อมูล agent สองตัวหมายถึง summary หนึ่งอัน agent สี่ตัวใน chain หมายถึงสามอันที่ประกอบกัน แต่ละอันเขียนโดยโมเดลที่ optimize เพื่อสิ่งอื่นนอกเหนือจากการตัดสินใจของคุณ
agent เดี่ยวพบสิ่งที่ไม่มีใครถามหา ความไม่ตรงกันของ purchase-order โผล่ขึ้นมาเพราะ window หนึ่งมีทั้ง invoice และ order พร้อมกัน การแบ่งงานให้ specialist ยังแบ่งความสามารถในการสังเกตว่า fact สองอย่างขัดกันด้วย
ทั้งหมดนี้ไม่ได้โต้แย้ง framework multi-agent ที่ตีพิมพ์แล้ว ซึ่งควรอ่านเป็น primary source มากกว่าผ่าน tutorial10 มันโต้แย้งเพื่อให้ agent ตัวที่สองต้องพิสูจน์ว่าคู่ควร
ดังนั้นเป็น test ไม่ใช่ preference เพิ่ม agent ตัวที่สองเมื่ออย่างน้อยหนึ่งข้อนี้จริง: sub-task ต้องใช้ clean window ที่ parent ต้องไม่ inherit (บทที่ 24); sub-task เป็น อิสระ จริง ๆ และ wall clock สำคัญ ซึ่งคือ 1.8× ด้านบน; sub-task ต้องใช้ permission ต่างกัน หรือโมเดลคนละตัว ซึ่ง บทที่ 30 เปลี่ยนเป็น argument ด้าน security; หรือ sub-task เป็นของคนอื่น ซึ่งเป็นจุดที่ protocol จริงเริ่มสำคัญ ถ้าคำตอบคือ “เพื่อให้แต่ละ agent มี prompt ชัดขึ้น” ให้ agent เดียวมี prompt ที่ชัดขึ้น มันฟรี
ต่อไปจะไปที่ไหน
ลิงก์ไปยังส่วน: ต่อไปจะไปที่ไหนตอนนี้คุณตั้งชื่อ pattern ทั้งห้าได้ ตีราคาเทียบกันบนงานเดียว แยก orchestrator ออกจาก sectioner และ tool call ออกจาก handoff และปกป้อง agent เดี่ยวด้วยตารางแทน preference ได้แล้ว
การจัดวางทั้งหมดที่นี่มีความสะดวกเหมือนกันอย่างหนึ่งซึ่งจะไม่รอดเมื่อเจอของจริง: เครื่องมือทั้งหมดเป็นของเรา Invoice, order, tax table, worker หลัง orchestrator — repository เดียวกัน, deploy เดียวกัน, type เดียวกัน, คนกลุ่มเดียวกัน
ตอนนี้เอาหนึ่งในนั้นไปไว้ข้ามเส้นแบ่งบริษัท ตารางภาษีเป็นของ accounting vendor, order record เป็นของ warehouse system และทั้งคู่ไม่เคยอ่าน interface Tool ของคุณ คุณต้องมีวิธีให้โมเดลที่คุณไม่ได้เขียนค้นพบ อธิบาย และเรียก capability ที่คนอื่น operate — พร้อม authentication (ซึ่งเป็นครึ่งหนึ่งของ บทที่ 27), versioning, และการรับประกันว่า server อ่านบทสนทนาที่เหลือของคุณไม่ได้ นั่นคือปัญหา protocol มันมี specification พร้อม normative schema และแทบทุกอย่างที่ indexed เกี่ยวกับมันอธิบาย revision ที่ไม่มีอยู่แล้ว
บทที่ 26 อ่าน specification นั้นแทนการ summarize และเริ่มด้วยการพิมพ์ JSON-RPC ลง terminal ด้วยมือ
แหล่งที่มาและวิธีการ
ลิงก์ไปยังส่วน: แหล่งที่มาและวิธีการต้นทุนและจำนวน token ทั้งหมดด้านบนมาจาก provider แบบสคริปต์ที่อธิบายใน section ที่สอง บน Node 22 ผ่าน loopback interface นับด้วย encoding o200k_base และคิดราคาตามอัตราที่บทที่ 16 อ่านเมื่อ 6 กันยายน 2026 — $2.00 ต่อ input token หนึ่งล้าน และ $12.00 ต่อ output หนึ่งล้าน ตัวเลข wall-clock มาจาก run เดียวกัน โดยตั้ง latency ของ provider เป็น 400 ms ต่อ call และเครื่องมือเป็น 50 ms จึงวัดการจัดวาง ไม่ใช่ provider ใด ๆ การวัดด้วยโมเดลจริงสองชุด — ตาราง handoff และตาราง voting-and-judging — ใช้ Qwen/Qwen2.5-0.5B-Instruct ใน float32 บน CPU หลัง endpoint รูปทรงเดียวกัน เป็น greedy ยกเว้นตรงที่ระบุ temperature โดย interval คำนวณด้วยวิธี Wilson จากบทที่ 4 ไม่มี request ใดในบทนี้ไปยัง paid endpoint และไม่มีตัวเลขใดเป็นการประมาณ
รายการอ้างอิง
ลิงก์ไปยังส่วน: รายการอ้างอิง-
Anthropic, Building effective agents, 19 ธันวาคม 2024,
anthropic.com/engineering/building-effective-agents, อ่าน 7 กันยายน 2026 แหล่งที่มาของชื่อ workflow ทั้งห้าที่ใช้ด้านบน และของทุกวลีที่อ้างจากงานนั้น — prompt chaining, routing, parallelisation พร้อม variant sectioning และ voting, orchestrator-workers, evaluator-optimiser — รวมถึงคำแนะนำให้หา “the simplest solution possible, and only increasing complexity when needed” และข้อสังเกตว่า “agentic systems often trade latency and cost for better task performance” บทที่ 22 และ 23 อ้างนิยาม agent ของงานนี้ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 -
Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A. and Zhou, D. Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171 (มีนาคม 2022) ต้นกำเนิดของ voting pattern ซึ่งอธิบายที่นั่นเป็น decoding strategy ไม่ใช่ architecture: sample reasoning path ที่หลากหลาย แล้ว “select the most consistent answer by marginalizing out the sampled reasoning paths” พร้อมรายงาน gain +17.9 บน GSM8K, +11.0 บน SVAMP, +12.2 บน AQuA, +6.4 บน StrategyQA และ +3.9 บน ARC-challenge ↩
-
Madaan, A. et al. Self-Refine: Iterative Refinement with Self-Feedback. arXiv:2303.17651 (2023) evaluator-optimiser loop ที่ใช้โมเดลเดียวในทั้งสาม role — “generator, refiner, and feedback provider” — ปรับปรุง “by ~20% absolute on average in task performance” ใน 7 งาน วัดด้วย human preference และ automatic metrics ไม่ใช่ verdict ของโมเดลเอง ↩
-
Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K. and Yao, S. Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366 (2023) เพิ่ม episodic memory ของ self-critique ข้าม attempt — “reinforce language agents not by updating weights, but through linguistic feedback” — รายงาน pass@1 91% บน HumanEval เทียบกับ 80% สำหรับ GPT-4 baseline สังเกต requirement ที่ผลลัพธ์พึ่งพา: signal จริงจาก environment เช่น test ที่ fail ไม่ใช่ความเห็นของโมเดลต่อตัวเอง ↩ ↩2
-
Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. and Cao, Y. ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629 (2022) reasoning trace และ action แบบ interleaved; บทที่ 23 สร้าง loop นี้ อ้างที่นี่เพื่อรูปทรงต้นทุน ไม่ใช่ผลลัพธ์: model call หนึ่งครั้งต่อขั้น พร้อมส่ง transcript ทั้งหมดซ้ำทุกครั้ง ↩
-
Wang, L., Xu, W., Lan, Y., Hu, Z., Lan, Y., Lee, R. K.-W. and Lim, E.-P. Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models. arXiv:2305.04091 (2023) “First, devising a plan to divide the entire task into smaller subtasks, and then carrying out the subtasks according to the plan” — รูปทรง plan-then-execute และแหล่งที่มาของ trade-off ที่บทนี้สนใจ: plan ถูก fix ก่อน observation แรกจะมาถึง ซึ่งคือ prompt chaining ที่ decomposition เขียนโดยโมเดลแทนที่จะเป็นคุณ ↩
-
Yao, S., Yu, D., Zhao, J., Shafran, I., Griffiths, T. L., Cao, Y. and Narasimhan, K. Tree of Thoughts: Deliberate Problem Solving with Large Language Models. arXiv:2305.10601 (2023) search บน “thoughts” ระหว่างทาง พร้อม self-evaluation และ backtracking; ได้ 74% บน Game of 24 เทียบกับ 4% สำหรับ chain-of-thought prompting ตัวเลขต้นทุนที่อ้างด้านบนเป็นของ paper เอง จาก Appendix B.3, Table 7: ต่อเคส input/output prompting best-of-100 ที่ $0.13 สำหรับ 33%, chain of thought best-of-100 ที่ $0.47 สำหรับ 49%, และ tree of thoughts ที่ $0.74 สำหรับ 74% พร้อม note ของผู้เขียนว่า ToT “could require 5-100 times more generated tokens than CoT” ↩ ↩2
-
OpenAI, A practical guide to building agents (PDF), อ่าน 7 กันยายน 2026 การแบ่ง manager-versus-decentralised, framing แบบ graph ที่อ้างด้านบน (“in the manager pattern, edges represent tool calls whereas in the decentralized pattern, edges represent handoffs”), และนิยามของ handoff ว่า “a one way transfer... we immediately start execution on that new agent that was handed off to while also transferring the latest conversation state” สังเกตว่า clause สุดท้ายนั้นตัดสินอะไร: ใน SDK นี้ conversation state เดินทางไปด้วย ซึ่งเป็น design decision ของ library นั้น ไม่ใช่ property ของ handoff โดยทั่วไป ↩ ↩2
-
Agent2Agent (A2A) Protocol Specification, เวอร์ชัน release ล่าสุด 1.0.0,
a2a-protocol.org/latest/specification/, อ่าน 7 กันยายน 2026; ลิขสิทธิ์ Linux Foundation, Apache-2.0 อ้างด้านบน: “open standard designed to facilitate communication and interoperability between independent, potentially opaque AI agent systems” และหลักการ opaque execution — agents “collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations” หน้านี้มี release history (0.1.0, 0.2.6, 0.3.0, 1.0.0), appendix ของ breaking changes และ appendix เรื่องความสัมพันธ์กับ MCP บทที่ 26 ทำการเปรียบเทียบนั้น ↩ -
framework multi-agent ที่บทนี้ไม่ได้สอน สำหรับผู้อ่านที่ต้องการ primary source แทน tutorial: Wu, Q. et al., AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation, arXiv:2308.08155 (2023), ที่ agents เป็น “customizable, conversable” และ conversation เองคือ programming model; Hong, S. et al., MetaGPT: Meta Programming for a Multi-Agent Collaborative Framework, arXiv:2308.00352 (2023), ซึ่ง encode standard operating procedures ลงใน role prompts และระบุชัดว่า “solutions to more complex tasks are complicated through logic inconsistencies due to cascading hallucinations caused by naively chaining LLMs” — chain ที่ผิดอย่างมั่นใจซึ่งวัดไว้ตอนต้นบทนี้ ถูกตั้งชื่อไว้ใน abstract; และ Park, J. S. et al., Generative Agents: Interactive Simulacra of Human Behavior, arXiv:2304.03442 (2023), agent 25 ตัวพร้อม memory, reflection และ planning ซึ่งเป็นคำตอบที่ตีพิมพ์ขนาดใหญ่ที่สุดต่อคำถาม “จะเกิดอะไรขึ้นถ้าคุณเพิ่ม agent ต่อไปเรื่อย ๆ” ↩