ทุกคนกำลังถามว่า "วายทีเอฟคือลูป?" แต่มีคำถามหนึ่งที่ไม่มีใครถาม: อะไรคือสิ่งที่ขับเคลื่อนลูป?
การสนทนาเกี่ยวกับ AI ได้สรุปลงที่ลูปในฐานะพื้นฐานหลักของระบบ agentic Matt Van Horn (@mvanhorn) ได้สืบหา ที่มาของ agent loops ตั้งแต่ ReAct ไปจนถึงการใช้งานเครื่องมือ ไปจนถึงลูปสำหรับการประสานงาน ไปจนถึงลูปที่ดูแลลูปอื่นๆ Addy Osmani (@addyosmani) ได้แยกย่อย องค์ประกอบภายในลูป ออกเป็น: ระบบอัตโนมัติ, worktrees, ทักษะ, ตัวเชื่อมต่อ, และ sub-agents Van Horn ลงเอยที่ ความทนทาน (durability) โดยโต้แย้งว่าลูปที่ไม่สามารถอยู่รอดได้หลังการรีสตาร์ทนั้นไม่ใช่ลูป จุดหลักของ Osmani คือ การประสานงาน (orchestration) : ออกแบบระบบที่ไปกระตุ้น agent แทนที่จะให้คุณทำเอง
ผมอยากจะต่อยอดแนวคิดของพวกเขาให้ไกลขึ้นไปอีก ความทนทานไม่ได้เป็นเพียงคุณสมบัติของลูปเท่านั้น แต่เป็นเลเยอร์การประมวลผลทั้งหมดที่อยู่ข้างใต้มัน ข้อเท็จจริงที่สำคัญคือ การประสานงานที่ทนทานนั้นเป็นพื้นฐานสำหรับการสร้างสถาปัตยกรรม agent loop ของคุณ มาวิเคราะห์สถาปัตยกรรมนั้นกันเลย
จุดที่ลูปพัง
รูปแบบ /loop และ /goal จัดการงานแบบ agent เดียวและเซสชันเดียวได้ดี ตัว agent จะวนลูปไปเรื่อยๆ จนกว่างานจะเสร็จ ซึ่งครอบคลุมหลายสิ่งหลายอย่าง แต่ในขั้นตอนถัดไป (Stage 5 ตามกรอบแนวคิดของ Van Horn) คือจุดที่มันเริ่มพัง:
- ลูปที่ดูแลลูปอื่นๆ
- ลูปที่ทำงานตามตารางเวลา ไม่ใช่แค่ถูกสั่งโดยมนุษย์
- ลูปที่สามารถอยู่รอดได้เมื่อกระบวนการถูกรีสตาร์ท ถูกดีพลอย หรือเกิดครา ช
- ลูปที่สร้าง sub-agents และรอผลลัพธ์ (บางครั้งอาจเป็นชั่วโมง)
- ลูปที่ต้องสามารถตรวจสอบย้อนหลังได้
นั่นไม่ใช่ปัญหาด้านการเขียน prompt แต่เป็นปัญหาโครงสร้างพื้นฐาน
Van Horn อ้างถึง @runes_leo: "สิ่งที่มีค่าใช้จ่ายสูงที่สุดในการเขียนโค้ด AI ไม่ใช่การเขียนโค้ดอีกต่อไป แต่คือการจัดการ agent loop" การใช้ while True ใน terminal ไม่ได้ให้สิ่งเหล่านี้แก่คุณเลย แม้แต่กระบวนการที่รันยาวนานบน VM หรือ sandbox ก็ไม่ได้ให้เช่นกัน
ลองคิดถึงสิ่งที่เกิดขึ้นเมื่อคุณรัน agent loop บนเซิร์ฟเวอร์ กระบวนการจะตายหรือถูกรีสตาร์ท ไม่ว่าจะเป็นการดีพลอย, OOM, หรือการเรียกคืน spot instance ลูปจะเริ่มต้นใหม่ แต่สิ่งที่มันกำลังทำอยู่คืออะไร? มันอยู่ที่ขั้นตอนไหน? มันส่งข้อความ Slack ไปแล้วหรือยัง? มันเรียกใช้ sub-agent ไปแล้วหรือยัง?
คุณไม่รู้ มันเริ่มต้นใหม่ ดึงข้อมูลที่เคยมีแล้วอีกครั้ง เรียก LLM เพื่อตัดสินใจในสิ่งที่เคยตัดสินไปแล้ว ส่งการแจ้งเตือนซ้ำ สร้าง sub-agent ซ้ำ คุณตื่นขึ้นมาเจอข้อความ Slack ที่เหมือนกันสามข้อความและทีมที่สับสน
วิธีแก้ไขไม่ใช่ "การจัดการข้อผิดพลาดที่ดีขึ้น" — แต่เป็นโมเดลการประมวลผลที่แต่ละขั้นตอนถูกบันทึกไว้ (checkpointed) การตัดสินใจแต่ละครั้งถูกจัดเก็บไว้อย่างถาวร (persisted) และการกู้คืนหมายถึงการกลับมาทำงานต่อจากขั้นตอนที่สำเร็จล่าสุด
สถาปัตยกรรม agent loop ในสามเลเยอร์
สามเลเยอร์ แต่ละเลเยอร์จับคู่กับพื้นฐานเชิงรูปธรรมหนึ่งอย่าง
เลเยอร์ 1: ลูป (The Loop)
ลูปก็คือ cron บวกกับตัวตัดสินใจ มันทำงานตามตารางเวลา (หรือตามทริกเกอร์) ประเมินสถานะ และตัดสินใจว่าจะทำอะไรต่อไป
นี่คือคำจำกัดความของ Van Horn ที่ทำให้เป็นรูปธรรม: สิ่งที่ cron ไม่เคยมีคือการตัดสินใจที่อยู่ตรงกลาง ตัว agent เป็นผู้ตัดสินใจ ไม่ใช่คุณ cron คือจังหวะการเต้นของหัวใจ LLM คือตัวตัดสินใจ ส่วนขั้นตอนต่างๆ คือการประมวลผลที่ทนทานซึ่งบันทึกความคืบหน้า
1export const infraHealthCheck = inngest.createFunction(2 { id: "infra-health-check" },3 { cron: "*/30 * * * *" }, // ทุก 30 นาที4 async ({ step }) => {5 const metrics = await step.run("fetch-service-metrics", async () => {6 return await fetchServiceMetrics(); // อัตราข้อผิดพลาด, ความหน่วง, หน่วยความจำ, CPU7 });89 const assessment = await step.run("assess-health", async () => {10 return await callLLM({11 prompt: `จากเมตริกของบริการเหล่านี้ ให้จำแนกสถานะสุขภาพโดยรวมของระบบ12 ว่าเป็น "ปกติ" "เสื่อมประสิทธิภาพ" หรือ "วิกฤต" พร้อมอธิบายเหตุผล13 เมตริก: ${JSON.stringify(metrics)}`,14 });15 });1617 if (assessment.status === "degraded" || assessment.status === "critical") {18 await step.invoke("triage-incident", {19 function: incidentTriage,20 data: { metrics, assessment, services: assessment.affectedServices },21 });22 }23 }24);
ทุกวันจันทร์เวลา 9 โมงเช้า ลูปจะทำงาน มันดึงข้อมูล ถาม LLM ว่ารายงานสมควรถูกสร้างหรือไม่ และเรียกใช้ทักษะถ้าคำตอบคือใช่ ถ้ากระบวนการถูกรีสตาร์ทระหว่างขั้นตอน ขั้นตอนที่เสร็จแล้วจะไม่ถูกประมวลผลซ้ำ นั่นคือลูป ไม่ใช่ LLM แต่เป็นลูปที่ อยู่รอบๆ LLM
เลเยอร์ 2: ทักษะ (The Skill)
ในบริบทนี้ ทักษะไม่ใช่ prompt มันคือเวิร์กโฟลว์ที่ทนทาน มีหลายขั้นตอน สามารถลองใหม่ได้ (retryable) สามารถประกอบรวมกันได้ (composable) และสามารถดีพลอยได้อย่างอิสระ
Van Horn: "ลูปคือระบบท่อ สินทรัพย์ที่แท้จริงคือทักษะที่มันเรียกใช้" นี่คือส่วนที่ทวีคูณผล ทักษะใหม่แต่ละอย่างที่ระบบเรียนรู้จะทำให้ทุกลูปมีความสามารถมากขึ้น
1export const incidentTriage = inngest.createFunction(2 { id: "incident-triage", retries: 3 },3 { event: "infra.incident.triage" },4 async ({ event, step }) => {5 const details = await step.run("fetch-detailed-metrics", async () => {6 return await fetchDetailedMetrics({ services: event.data.services });7 });89 const deploys = await step.run("fetch-deploy-history", async () => {10 return await fetchRecentDeploys({ since: hoursAgo(2) });11 });1213 const analysis = await step.run("correlate-incident", async () => {14 return await callLLM({15 prompt: `เชื่อมโยงเมตริกบริการเหล่านี้กับการดีพลอยล่าสุด16 ระบุสาเหตุที่เป็นไปได้และระดับความรุนแรง17 เมตริก: ${JSON.stringify(details)}18 การดีพลอยล่าสุด: ${JSON.stringify(deploys)}`,19 });20 });2122 await step.run("post-triage-summary", async () => {23 await slack.postMessage({24 channel: "#incidents",25 text: formatTriageSummary({26 analysis,27 affectedServices: event.data.services,28 recommendedActions: analysis.recommendations,29 }),30 });31 });3233 return analysis;34 }35);
ทักษะนี้ทำการดึงข้อมูล จำแนกประเภท และจัดเส้นทาง มันคือหน่วยของงานที่มีความทนทานต่อข้อผิดพลาดในตัว ทักษะสามารถเป็นเวิร์กโฟลว์ AI ที่มี LLM อยู่ตรงกลาง หรือเป็นโค้ดที่กำหนดตายตัวก็ได้
เลเยอร์ 3: ตัวประสานงาน (The Orchestrator)
ตัวประสานงานคือเอนจินที่รันทุกอย่าง: จัดตาราง cron, ประมวลผลขั้นตอน, จัดการการลองใหม่, บังคับใช้ขีดจำกัดการทำงานพร้อมกัน (concurrency limits), จัดเก็บประวัติการรัน, และดีพลอยฟังก์ชัน/เวิร์กโฟลว์ใหม่แบบ hot-deploy โดยไม่รบกวนการทำงานที่กำลังรันอยู่
นี่คือเลเยอร์ที่ไม่มีใครพูดถึง เพราะมันควรจะมองไม่เห็น แต่มันเป็นพื้นฐาน
คนส่วนใหญ่มักคิดถึง agents ในรูปแบบ "LLM + เครื่องมือ" สถาปัตยกรรม agent loop ให้กรอบแนวคิดใหม่ว่า agents คือ "ลูป + ทักษะ + การประสานงาน" โดย LLM + เครื่องมือจะอยู่ภายในลูป LLM และเครื่องมือสามารถสลับหรือปรับแต่งได้ในขณะที่สถาปัตยกรรมยังคงอยู่ การประสานงานทำให้สถาปัตยกรรมเป็นไปได้
สิ่งที่เกิดขึ้นเมื่อสิ่งต่างๆ พัง
เส้นทางที่ราบรื่นนั้นง่ายดาย แต่นี่คือซอฟต์แวร์ที่ทำงานในโปรดักชัน สิ่งต่างๆ จะเป็นไปตามแผนเสมอหรือไม่?
ทักษะ incident triage ของคุณทำงานและ API ของเมตริกก็หมดเวลา การอ่านต้องไปที่ดิสก์และแคชในหน่วยความจำไม่มีข้อมูลนั้น ขั้นตอนที่เรียก API นี้จะลองใหม่และเรียก API อีกครั้ง ข้อมูลถูกแคชไว้บางส่วนแล้วและ API ก็ทำงานสำเร็จ ทักษะดำเนินต่อไปยังขั้นตอนถัดไปราวกับว่าไม่มีอะไรเกิดขึ้น
บางครั้ง มันอาจไม่ง่ายอย่างนั้น จะเกิดอะไรขึ้นถ้าคีย์ API หมดอายุ หรือผู้ให้บริการโฮสติ้งของคุณดับไป 30 นาที? การลองใหม่ทั้งหมดของคุณก็หมดลง แล้วตอนนี้จะเกิดอะไรขึ้น? คุณต้องจัดการกับความล้มเหลวด้วย
1export const incidentTriage = inngest.createFunction(2 {3 id: "incident-triage",4 retries: 3,5 onFailure: async ({ error, event, step }) => {6 // ฟังก์ชันล้มเหลวหลังจากลองจนหมด7 // เรายังคงมีข้อมูลอีเวนต์ต้นฉบับ ไม่มีอะไรสูญหาย8 await step.run("notify-failure", async () => {9 await slack.postMessage({10 channel: "#agent-ops",11 text: `⚠️ การคัดแยกเหตุการณ์ล้มเหลว: ${error.message}. ` +12 `จะลองใหม่ในรอบการตรวจสอบสุขภาพครั้งถัดไป ` +13 `บริการที่ได้รับผลกระทบ: ${event.data.services.join(", ")}`,14 });15 });16 },17 },18 { event: "infra.incident.triage" },19 async ({ event, step }) => {20 /* ตรรกะเดียวกันกับทักษะด้านบน */21 }22);
ตัวจัดการ \onFailure\ จะทำงานหลังจากลองจนหมดแล้ว มันจะโพสต์ไปยังช่อง ops เพื่อให้มีคนรับรู้ อีเวนต์ถูกเก็บรักษาไว้ ไม่มีอะไรสูญหาย การรันตามกำหนดการครั้งถัดไปจะมาทำงานต่อจากจุดที่การรันที่ล้มเหลวไปไม่ถึง
การประสานงานที่ทนทานต้องให้คุณมี การลองใหม่ระดับขั้นตอน สำหรับข้อผิดพลาดชั่วคราว และ ตัวจัดการความล้มเหลว สำหรับข้อผิดพลาดที่ไม่สามารถกู้คืนได้ หากไม่มีสิ่งนี้ สิ่งต่างๆ ก็จะพัง (ซึ่งก็เป็นเช่นนั้น) และคุณจะรู้ตัวอีกทีหลายชั่วโมงหรือหลายวันต่อมา
ข้อผิดพลาดชั่วคราวก็มีค่าใช้จ่ายสูงเช่นกัน ถ้าทักษะหรือ agent ของคุณลองใหม่ตั้งแต่ต้น คุณจะเรียก LLM หลายครั้งและเผา token โดยไม่จำเป็น การเรียก LLM สามารถถูกบันทึกเป็น checkpoint ได้ ทีนี้ลองคูณด้วย 10 หรือ 30 agents ทั่วทั้งระบบของคุณดู นั่นแพงมาก
การตั้ง checkpoint ระดับขั้นตอนไม่ใช่แค่คุณสมบัติด้านความถูกต้อง มันคือตัวช่วยประหยัดเงิน
The agent ที่สร้างทักษะของตัวเอง
นี่คือจุดที่เริ่มน่าสนใจมากขึ้น ระบบไม่ได้หยุดนิ่ง แต่ถูกออกแบบมาให้พัฒนาและขยายขีดความสามารถของตัวเองได้
agent ไม่ได้แค่ทำงานภายในลูป — มันสร้างลูปใหม่และลงทะเบียนลูปเหล่านั้นกับเอนจินการประสานงาน ฟังก์ชันที่ถูกดีพลอยแต่ละตัวคือทักษะที่ทนทานซึ่งทำงานได้อย่างอิสระ สามารถถูกเรียกจากลูป หรือ agent หรือทำงานตามตารางเวลา โดยมีตรรกะการลองใหม่ของตัวเอง ทักษะต่างๆ ทวีคูณผลซึ่งกันและกัน
มันคือ agent ที่ตระหนักรู้ถึงการประสานงาน (orchestration-aware agent)
นี่คือวิธีการทำงาน agent AI สามารถเข้าถึง SDK การประสานงานในฐานะเครื่องมือ มันสามารถเขียนฟังก์ชันใหม่ ลงทะเบียนกับเอนจิน และฟังก์ชันเหล่านั้นจะเริ่มทำงานทันที กระบวนการ agent โหลดฟังก์ชันใหม่แบบ hot-reload โดยไม่ต้องรีสตาร์ทหรือรบกวนการทำงานที่กำลังดำเนินอยู่
ลองดูตัวอย่างที่เป็นรูปธรรม:
1. มนุษย์แสดงความต้องการ วิศวกรพูดว่า: "บริการของเรามีปัญหาความหน่วงสูงในช่วงกลางคืนและไม่มีใครสังเกตจนกระทั่งเช้า" นี่คือทริกเกอร์ agent ไม่จำเป็นต้องเดารูปแบบจากข้อมูลรอบข้าง มันมีคำแนะนำที่ชัดเจน
2. Agent เขียนทักษะ ฟังก์ชันสองแบบที่มีหลายขั้นตอน: ลูปตรวจสอบสุขภาพที่ทำงานทุก 30 นาที ดึงอัตราข้อผิดพลาด ความหน่วง และการใช้ทรัพยากร โดยให้ LLM จำแนกสถานะสุขภาพของระบบเป็นปกติ เสื่อมประสิทธิภาพ หรือวิกฤต และทักษะการคัดแยกเหตุการณ์ที่ดึงเมตริกโดยละเอียดและประวัติการดีพลอยล่าสุด เชื่อมโยงสาเหตุที่แท้จริงกับ LLM และโพสต์สรุปการคัดแยกไปยัง Slack พร้อมการดำเนินการที่แนะนำ การจัดการข้อผิดพลาด: ถ้า API เมตริกดับ ให้ถอยและลองใหม่ ถ้า LLM ล้มเหลว ให้ใช้การจำแนกความรุนแรงตามกฎเป็นตัวสำรอง
3. Agent ดีพลอยทักษะ agent เขียนโค้ดฟังก์ชันที่ถูกดึงขึ้นมาโดยกระบวนการ sidecar ฟังก์ชันใหม่จะถูกลงทะเบียนโดยอัตโนมัติ ฟังก์ชันเหล่านี้จะทำงานทันที โดยไม่มีไปป์ไลน์การดีพลอย ไม่มี PR
4. ทักษะทำงานอัตโนมัติ ทุก 30 นาที เอนจินจะทริกเกอร์การตรวจสอบสุขภาพ ถ้ามีอะไรผิดปกติ มันจะเรียกใช้ทักษะการคัดแยก ไม่มีมนุษย์อยู่ในลูป ทนทานอย่างเต็มที่
5. Agent ปรับปรุงจากสัญญาณ นี่คือส่วนที่คนมักมองข้าม ดังนั้นให้ผมเจาะจงว่าการ "ปรับปรุง" หมายถึงอะไร agent ไม่ได้สังเกตเห็นรูปแบบได้อย่างน่าอัศจรรย์ มันมีลูปการตรวจสอบแยกต่างหาก: ฟังก์ชันที่ถูกทริกเกอร์ด้วย cron ซึ่งทำงานทุกสัปดาห์ อ่านประวัติการรันจากตัวประสานงาน และประเมินประสิทธิภาพ:
1export const reviewSkillPerformance = inngest.createFunction(2 { id: "review-skill-performance" },3 { cron: "0 10 * * 5" }, // ทุกวันศุกร์เวลา 10.00 น.4 async ({ step }) => {5 const runs = await step.run("fetch-run-history", async () => {6 return await getInngestRuns({7 functionId: "incident-triage",8 since: daysAgo(7),9 });10 });1112 const analysis = await step.run("analyze-performance", async () => {13 const successRate = runs.filter(r => r.status === "completed").length / runs.length;14 const avgDuration = average(runs.map(r => r.duration));15 const incidents = await fetchIncidentOutcomes(); // เหตุการณ์สัมพันธ์กับการหยุดทำงานจริงหรือไม่?1617 return await callLLM({18 prompt: `ตรวจสอบประสิทธิภาพของทักษะนี้ในสัปดาห์ที่ผ่านมา19 อัตราความสำเร็จ: ${successRate}20 ระยะเวลาเฉลี่ย: ${avgDuration}ms21 เหตุการณ์ที่สัมพันธ์กับการหยุดทำงานจริง: ${incidents.confirmed}/${incidents.total}22 ผลบวกลวง: ${incidents.falsePositives}23 ทีมดำเนินการกับการแจ้งเตือน: ${incidents.actedOn}/${incidents.total}2425 เราควรปรับเกณฑ์หรือการจำแนกประเภทหรือไม่? ควรเปลี่ยนแปลงอะไรเป็นพิเศษ?`,26 });27 });2829 if (analysis.shouldModify) {30 await step.invoke("update-skill", {31 function: coreAgent,32 data: { prompt: `อัปเดตทักษะการคัดแยกเหตุการณ์ตามการเปลี่ยนแปลงที่เสนอดังต่อไปนี้: ${analysis.proposedChanges}` },33 });34 }35 }36);
"การตรวจสอบ" ก็คือฟังก์ชันหนึ่ง มันอ่านประวัติการรัน ตรวจสอบว่าเหตุการณ์ต่างๆ สัมพันธ์กับการหยุดทำงานจริงหรือไม่ และป้อนสัญญาณนั้นให้ LLM ถ้าการตรวจสอบสุขภาพยังคงแจ้งเตือนว่าบริการหนึ่งมีประสิทธิภาพเสื่อมถอย แต่ทีมเมินเฉยเพราะเกณฑ์ไวเกินไป ลูปตรวจสอบจะจับได้และทักษะจะถูกอัปเดตเพื่อปรับการจำแนกประเภท ไม่ใช่เรื่องมหัศจรรย์ เป็น cron job ที่มี LLM อยู่ในตำแหน่งการตัดสินใจ
แล้วการตรวจสอบความถูกต้องล่ะ? agent ที่เขียนโค้ดจะดีได้เท่ากับกรอบป้องกันที่อยู่รอบๆ มันเท่านั้น โค้ดสามารถตรวจสอบชนิดได้ (type checked) agent สามารถเรียกใช้ฟังก์ชันด้วยตัวเองเพื่อทดสอบมัน เนื่องจากมันสามารถโต้ตอบกับเอนจินการประสานงานได้เอง แม้จะไม่ใช่สิ่งที่ป้องกันได้ร้อยเปอร์เซ็นต์ แต่คุณกำลังให้ agent หลักมีความสามารถในการดีบักทักษะที่มันเขียนขึ้นภายในระบบที่มันทำงานอยู่ได้อย่างเป็นธรรมชาติ ลูปตรวจสอบจะจับปัญหาที่ไม่ถูกจับได้ในการดีบักครั้งแรก
เมื่อขยายความต่อไปอีก agent สามารถใช้ onFailure hooks เพื่อทริกเกอร์ตัวเองให้ประเมินความล้มเหลวที่กำหนดได้ด้วยตัวเอง มันคือลูปป้อนกลับที่พัฒนาขึ้นเรื่อยๆ
แล้วความขัดแย้งล่ะ? การควบคุมโฟลว์ โดยเฉพาะอย่างยิ่ง การควบคุมการทำงานพร้อมกัน หรือ singletons จัดการกรณีทั่วไป (concurrency: \{ limit: 1, key: "[event.data.service" }]) หมายความว่ามีการคัดแยกเหตุการณ์เพียงครั้งเดียวต่อหนึ่งบริการในเวลาใดเวลาหนึ่ง แต่คำถามที่ลึกซึ้งกว่าคือ: จะเกิดอะไรขึ้นถ้าการตรวจสอบสุขภาพสองครั้งตรวจพบปัญหาบนบริการเดียวกันพร้อมกัน? ตัวประสานงานจะจัดคิวไว้ การคัดแยกครั้งที่สองจะรอจนกว่าครั้งแรกจะเสร็จสิ้น ไม่มีการแจ้งเตือนซ้ำ ไม่มี race condition นี่ไม่ใช่เรื่องเชิงทฤษฎี มันเป็นหลักการพื้นฐานเดียวกันกับที่คุณใช้ในคิวงานใดๆ
agent ไม่ได้แค่ทำงานตามภารกิจเท่านั้น มันกำลังสร้างโครงสร้างพื้นฐานให้กับตัวเอง ทักษะแต่ละอย่างคงอยู่เกินกว่าการสนทนาที่สร้างมันขึ้นมา ฆ่ากระบวนการ agent แล้วรีสตาร์ทมัน ทักษะยังคงทำงานต่อไป สลับโมเดลพื้นฐาน ทักษะยังคงทำงานต่อไป agent เป็นสิ่งชั่วคราว — แต่สิ่งที่มันสร้างขึ้นนั้นทนทาน

ภาพรวมระบบสถาปัตยกรรม Agent Loop
มุมมองของนักพัฒนา
เรื่องนี้สำคัญเพราะถ้านักพัฒนาไม่สามารถมองเห็นสิ่งที่ agent ดีพลอย ดีบักสิ่งที่พัง และตรวจสอบสิ่งที่ทำงานตอนตี 3 ได้ สถาปัตยกรรมทั้งหมดก็เป็นความเสี่ยงครั้งใหญ่
เอนจินการประสานงานจะจัดเก็บทุกการรัน ทุกขั้นตอน ทุกอินพุต ทุกเอาต์พุต ทุกการลองใหม่ ทักษะที่ agent ดีพลอยเมื่อวันอังคารที่แล้วซึ่งล้มเหลวตอนตี 4? คุณสามารถเห็นได้อย่างชัดเจนว่าขั้นตอนไหนล้มเหลว อินพุตคืออะไร เกิดข้อผิดพลาดอะไร และลองใหม่กี่ครั้งก่อนที่จะยอมแพ้ การติดตามอย่างสมบูรณ์ลงไปจนถึงระดับขั้นตอนคือผลลัพธ์ของเอนจินการประสานงานเอง
นี่ไม่ใช่แดชบอร์ดที่ถูกติดตั้งภายหลัง มันมีอยู่ในตัวของการประมวลผลที่ทนทาน ทุก step.run() คือ checkpoint ทุก checkpoint สามารถสังเกตได้ เมื่อสิ่งที่เขียนโค้ดไม่ใช่มนุษย์ การสังเกตได้ (observability) ไม่ใช่สิ่งที่ดีถ้ามี — มันคือเลเยอร์ของความไว้วางใจ
ในชีวิตประจำวัน เวิร์กโฟลว์ของนักพัฒนาจะเป็นแบบนี้: ตรวจสอบแดชบอร์ดการรันในตอนเช้า ดูว่าทักษะไหนทำงานข้ามคืนบ้าง อันไหนสำเร็จ อันไหนล้มเหลว ถ้าทักษะที่ agent เขียนมีพฤติกรรมที่ไม่ดี คุณสามารถอ่านโค้ดได้โดยตรง แก้ไข ลบ หรือบอกให้ agent แก้ไขมัน agent เป็นผู้สร้างมัน แต่คุณเป็นเจ้าของมัน agent และทักษะของมันก็ยังคงเป็นสวนที่คุณควรดูแล
ทำไมความทนทานจึงเป็นพื้นฐาน
Van Horn: "สิ่งเหล่านี้ต้องอยู่รอดได้หลังการรีสตาร์ท"
นี่คือความหมายของความทนทานในทางปฏิบัติ:
ข้อกำหนด
ความหมาย
สาเหตุที่ while loop พื้นฐานล้มเหลว
การลองใหม่เฉพาะขั้นตอน (Independent step retry)
ถ้าขั้นตอนที่ 3 จาก 5 ล้มเหลว ให้ลองใหม่เฉพาะขั้นตอนที่ 3 ไม่ใช่ขั้นตอนที่ 1 และ 2
การรีสตาร์ทลูปจะรันทุกอย่างใหม่ตั้งแต่ต้น
วงจรชีวิตของ sub-agent (Sub-agent lifecycle)
สร้างงานลูก รอให้มันเสร็จ (อาจเป็นชั่วโมง) ยกเลิกถ้างานแม่ถูกยกเลิก
ไม่มีการจัดการวงจรชีวิตแม่-ลูกในตัว
การส่งอีเวนต์ที่รับประกัน (Guaranteed event delivery)
ถ้าอีเวนต์เกิดขึ้นขณะที่ agent หยุดทำงาน อีเวนต์นั้นควรยังถูกประมวลผล
อีเวนต์จะสูญหายถ้ากระบวนการไม่ได้ทำงาน
การสังเกตได้ภายหลัง (Post-hoc observability)
ดูว่าเกิดอะไรขึ้นหลังจากนั้น: ทุกขั้นตอน ทุกการตัดสินใจ ทุกการลองใหม่
log เป็นตัวเลือกเดียวของคุณ และมันเป็นสิ่งชั่วคราว
Hot-deploy โดยไม่หยุดทำงาน
ดีพลอยฟังก์ชันเวอร์ชันใหม่โดยไม่ฆ่าการทำงานที่กำลังดำเนินอยู่
การรีสตาร์ทกระบวนการจะฆ่าทุกอย่าง
การควบคุมการทำงานพร้อมกัน (Concurrency control)
ให้รันทักษะเพียง N ตัวอย่างในเวลาเดียวกัน
ไม่มีพื้นฐานการทำงานพร้อมกันในตัว
"แค่รันมันใน container" จะทำให้คุณได้ uptime แต่มันไม่ได้ทำให้คุณได้ความถูกต้อง Container ที่รีสตาร์ทหลังจากครา ชจะนำกระบวนการกลับมา แต่ทุกลูปที่กำลังดำเนินอยู่จะเริ่มต้นใหม่ ทุกขั้นตอนถูกประมวลผลซ้ำ ทุกการเรียก LLM ถูกทำซ้ำ ลูปดูเหมือนจะทำงาน แต่มันกำลังทำงานแบบไม่มีข้อมูล
เปรียบเทียบกับเครื่องมือที่มีอยู่แล้ว
เครื่องมือบางอย่างอาจเสนอวิธีแก้ปัญหาที่ "สวยงาม" แบบครบวงจรสำหรับระบบประเภทนี้ หรือคุณอาจเลือกที่จะประกอบเครื่องมือระดับล่างบางอย่างเข้าด้วยกันและสร้างระบบของคุณเอง ไม่มีทางเลือกไหนที่ ผิด แต่เลเยอร์สถาปัตยกรรมที่ถูกต้องควรช่วยให้คุณ และ agent ของคุณ สามารถพัฒนาไปตามกาลเวลาได้ ยืดหยุ่น ปรับเปลี่ยนได้ และทนทาน
พื้นฐานการประมวลผลที่ทนทานที่เข้ากับ agent ได้ดี ที่ agent สามารถเขียนได้ง่าย รวมถึงการสังเกตได้และ API เพื่อสังเกตและทำให้ตัว agent เองตระหนักรู้ถึงการประสานงาน
ตัวอย่างที่ใช้งานได้จริง
เรากำลังทดสอบรูปแบบเหล่านี้ภายในองค์กรที่ Inngest และคุณสามารถดูแนวคิดนี้ได้ในโปรเจกต์ "utah" ที่นี่: https://github.com/inngest/utah มันคือ agent harness ที่สร้างขึ้นบนการประสานงานที่ทนทานของ Inngest ซึ่งนอกจากจะทนทานแล้วยังตระหนักรู้ถึงการประสานงานด้วย
ระบบมีกระบวนการ sidecar ที่ทำให้ agent หลักสามารถเขียนและแก้ไขฟังก์ชัน Inngest ในพื้นที่ทำงานของมันเอง โดยขยายขีดความสามารถของตัวเองด้วย "ทักษะ" (ในบริบทของบทความนี้) ในเร็วๆ นี้ เราวางแผนที่จะให้ระบบทั้งหมดพร้อมตัวอย่างลูปเริ่มต้น แต่แนวคิดที่มีอยู่สามารถแสดงให้เห็นแนวคิดในบทความนี้ได้ชัดเจนยิ่งขึ้น
ลูปที่ทวีคูณผล
โพสต์ล่าสุดของ Satya Nadella Satya Nadella ได้ตั้งชื่อสิ่งที่วงการได้รู้สึกกันอยู่: กำแพงป้องกัน (moat) ไม่ใช่โมเดล — มันคือลูป
กรอบแนวคิดของเขา: มีทุนอยู่สองประเภท ทุนมนุษย์ (Human capital) ความรู้และการตัดสินใจที่ทีมของคุณสร้างขึ้นในช่วงหลายปี และสิ่งที่เขาเรียกว่า ทุนโทเคน (token capital) ซึ่งก็คือเวิร์กโฟลว์ AI รูปแบบการตัดสินใจ และทักษะที่เรียนรู้ซึ่งบริษัทสร้างขึ้นบนพื้นฐานของ foundation models
แนวคิดหลัก: สิ่งเหล่านี้ทวีคูณผลซึ่งกันและกัน เวิร์กโฟลว์ที่ดีขึ้นทุกอย่างสร้างสัญญาณที่ดีขึ้น สัญญาณที่ดีขึ้นสร้างพฤติกรรม AI ที่เฉียบคมขึ้น พฤติกรรมที่เฉียบคมขึ้นช่วยปลดปล่อยความสนใจของมนุษย์สำหรับงานที่ต้องใช้การตัดสินใจสูงขึ้น มันคือเครื่องจักรไต่เขา (hill climbing machine)
นี่คือสิ่งที่สถาปัตยกรรม agent loop ทำให้เป็นจริงได้อย่างเป็นรูปธรรม:
- ทุกทักษะที่ทนทานที่ agent ดีพลอยคือความรู้ของสถาบันที่ถูกเข้ารหัสเป็นโครงสร้างพื้นฐานที่ใช้งานได้จริง มันคงอยู่ มันทำงานไม่ว่ามนุษย์จะดูอยู่หรือไม่
- ลูปตรวจสอบที่ถูกทริกเกอร์ด้วย cron ซึ่งประเมินประสิทธิภาพของทักษะและปรับปรุงมัน นั่นคือเครื่องจักรไต่เขาที่เกิดขึ้นจริง ไม่ใช่แผนภาพวงล้อในพรีเซนเทชั่น แต่เป็นฟังก์ชันที่มี tigger เป็น cron
- ถ้าทักษะของคุณตายเมื่อกระบวนการรีสตาร์ท การทวีคูณผลก็จะรีเซ็ตเป็นศูนย์ ความทนทานคือสิ่งที่ทำให้การลงทุนคงอยู่
ประเด็นสำคัญของ Nadella: "บริษัทควรจะสามารถเปลี่ยนโมเดล 'ทั่วไป' ได้โดยไม่สูญเสียความเชี่ยวชาญ 'ระดับ老兵ของบริษัท' ที่สร้างไว้ในระบบการเรียนรู้ของพวกเขา" นั่นคือรูปแบบคลังทักษะ ฟังก์ชันที่ทนทานไม่สนใจว่า LLM ตัวไหนเรียกมัน
สร้างตามนั้น
การสนทนาที่ผ่านมาเป็นเรื่องเกี่ยวกับสิ่งที่ agents ทำ: ลูป, เครื่องมือ, การใช้เหตุผล, วิศวกรรมบริบท การสนทนาครั้งถัดไป是关于什么运行代理的。
สามเลเยอร์: ลูป, ทักษะ, ตัวประสานงาน ลูปคือหน่วยของงาน ทักษะคือสินทรัพย์ เอนจินการประสานงานคือสิ่งที่ทำให้ทั้งสองอย่างทนทาน รูปแบบ sidecar คือโมเดล: agent เขียนทักษะที่ทนทานของตัวเอง ดีพลอยมัน ตรวจสอบว่ามันทำงานอย่างไร และปรับปรุงมัน ไม่ใช่การทดลองทางความคิด มันเป็นโมเดลที่ใช้งานได้จริง
เราสร้าง Inngest ขึ้นมาเพื่อเป็นเอนจินการประสานงานสำหรับสิ่งนี้: step.run(), step.invoke(), ทริกเกอร์ cron, การควบคุมโฟลว์ที่ขับเคลื่อนด้วยอีเวนต์, การควบคุมการทำงานพร้อมกัน และการสังเกตได้ในระดับขั้นตอนอย่างเต็มรูปแบบ แต่รูปแบบสถาปัตยกรรมนั้นใหญ่กว่าเครื่องมือใดๆ เพียงอย่างเดียว หากคุณกำลังสร้าง agent loops ในโปรดักชัน ให้กำหนดสามเลเยอร์นี้ให้ชัดเจน
พื้นฐานต่างๆ มีอยู่ในปัจจุบันแล้ว จงสร้างตามนั้น





