<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Retry on Code &amp; Community</title><link>https://neng-lab.com/tags/retry/</link><description>Recent content in Retry on Code &amp; Community</description><generator>Hugo -- gohugo.io</generator><language>th-th</language><managingEditor>jitaret@gmail.com (เหน่ง)</managingEditor><webMaster>jitaret@gmail.com (เหน่ง)</webMaster><lastBuildDate>Tue, 14 Apr 2026 12:00:00 +0700</lastBuildDate><atom:link href="https://neng-lab.com/tags/retry/index.xml" rel="self" type="application/rss+xml"/><item><title>Harness Engineering ตอนที่ 6: Recovery Paths - แผนสำรองเมื่อ AI พัง</title><link>https://neng-lab.com/posts/harness-part-6/</link><pubDate>Tue, 14 Apr 2026 12:00:00 +0700</pubDate><author>jitaret@gmail.com (เหน่ง)</author><guid>https://neng-lab.com/posts/harness-part-6/</guid><description>&lt;img src="https://neng-lab.com/" alt="Featured image of post Harness Engineering ตอนที่ 6: Recovery Paths - แผนสำรองเมื่อ AI พัง" /&gt;
 &lt;blockquote&gt;
 &lt;p&gt;⚠️ &lt;strong&gt;สถานะ:&lt;/strong&gt; เสร็จสมบูรณ์ - ผ่านการตรวจสอบแล้ว&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="บทนำ-ทำไมตองม-recovery-paths"&gt;&lt;a href="#%e0%b8%9a%e0%b8%97%e0%b8%99%e0%b8%b3-%e0%b8%97%e0%b8%b3%e0%b9%84%e0%b8%a1%e0%b8%95%e0%b8%ad%e0%b8%87%e0%b8%a1-recovery-paths" class="header-anchor"&gt;&lt;/a&gt;บทนำ: ทำไมต้องมี Recovery Paths?
&lt;/h2&gt;&lt;p&gt;สมมติว่าคุณกำลังสร้าง AI Agent สำหรับระบบ Customer Support ที่ทำงาน 24/7 วันหนึ่ง API ของ LLM ล่ม ระบบก็หยุดทันที ลูกค้าไม่ได้คำตอบ ธุรกิจเสียโอกาส&lt;/p&gt;
&lt;p&gt;นี่คือสิ่งที่เกิดขึ้นเมื่อเราไม่มี Recovery Paths&lt;/p&gt;
&lt;p&gt;AI Systems มีจุดล้มเหลวหลายจุดมากกว่าซอฟต์แวร์ทั่วไป:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Model API failures&lt;/strong&gt; — Rate limits, timeouts, outages&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool/Function calling errors&lt;/strong&gt; — External API ที่เราเรียกใช้พัง&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context window exceeded&lt;/strong&gt; — Prompt ยาวเกินไป&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Invalid output format&lt;/strong&gt; — AI สร้าง output ที่ไม่ตรงตาม schema (hallucinations)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependency failures&lt;/strong&gt; — Database, cache, หรือ services อื่นๆ ที่ระบบต้องการ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ถ้าเราออกแบบระบบโดยคิดว่าทุกอย่างจะทำงานได้ตลอดเวลา วันหนึ่งมันจะล้มเหลวในจุดที่เราไม่คาดคิด&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recovery Paths คืออะไร?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;คือ &amp;ldquo;แผนสำรอง&amp;rdquo; ที่เราวางไว้ล่วงหน้า เมื่อระบบหลักทำงานไม่ได้ แผนสำรองจะเข้ามาทำงานแทน ไม่ใช่เพื่อให้ระบบสมบูรณ์แบบ 100% แต่เพื่อให้ระบบ &amp;ldquo;ยังใช้งานได้&amp;rdquo; แม้จะลดความสามารถลงบ้าง&lt;/p&gt;
&lt;p&gt;จากหลักการ &lt;strong&gt;Graceful Degradation&lt;/strong&gt; — ลดความสามารถลงอย่างมีระดับ แทนที่จะล่มสิ้นเลย&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;Full AI Response → Simplified AI Response → Rule-Based Response → Human Handoff
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;บทความนี้จะพาคุณไปรู้จักกับ 4 เรื่องหลัก:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ประเภทของ Recovery (Auto vs Manual)&lt;/li&gt;
&lt;li&gt;Fallback Strategies&lt;/li&gt;
&lt;li&gt;Retry Logic&lt;/li&gt;
&lt;li&gt;Circuit Breaker Pattern&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="ประเภทของ-recovery-auto-vs-manual"&gt;&lt;a href="#%e0%b8%9b%e0%b8%a3%e0%b8%b0%e0%b9%80%e0%b8%a0%e0%b8%97%e0%b8%82%e0%b8%ad%e0%b8%87-recovery-auto-vs-manual" class="header-anchor"&gt;&lt;/a&gt;ประเภทของ Recovery: Auto vs Manual
&lt;/h2&gt;&lt;h3 id="auto-recovery-self-healing"&gt;&lt;a href="#auto-recovery-self-healing" class="header-anchor"&gt;&lt;/a&gt;Auto-Recovery (Self-Healing)
&lt;/h3&gt;&lt;p&gt;ลองนึกภาพ AI Agent ที่สามารถ &amp;ldquo;รู้ตัว&amp;rdquo; ว่าตัวเองทำผิด แล้วแก้ไขตัวเองได้ นี่คือ Self-Healing Agent Pattern&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;กระบวนการ 4 ขั้นตอน:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Stage&lt;/th&gt;
 &lt;th&gt;Action&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;1. Validation&lt;/td&gt;
 &lt;td&gt;ตรวจสอบว่า output ตรงตามที่ต้องการ&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2. Failure Detection&lt;/td&gt;
 &lt;td&gt;จำแนกประเภท failure&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3. Contextual Recovery&lt;/td&gt;
 &lt;td&gt;ใช้ recovery strategy ที่เหมาะสม&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;4. Learning Integration&lt;/td&gt;
 &lt;td&gt;บันทึกเพื่อปรับปรุงในอนาคต&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;ตัวอย่าง Failure Classification และ Recovery:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Failure Type&lt;/th&gt;
 &lt;th&gt;Recovery Action&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Input corruption&lt;/td&gt;
 &lt;td&gt;ขอข้อมูลใหม่หรือ clean data&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Context starvation&lt;/td&gt;
 &lt;td&gt;ขอข้อมูลเพิ่มเติม&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Tool failure&lt;/td&gt;
 &lt;td&gt;Retry หรือใช้ tool ทางเลือก&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Reasoning collapse&lt;/td&gt;
 &lt;td&gt;รีเซ็ตไปยัง state ล่าสุดที่ใช้ได้&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Output corruption&lt;/td&gt;
 &lt;td&gt;สร้างใหม่ด้วย parameter ต่างกัน&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Auto-Recovery เหมาะกับ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Transient errors (errors ที่เกิดชั่วคราวแล้วหายไป)&lt;/li&gt;
&lt;li&gt;Rate limits&lt;/li&gt;
&lt;li&gt;Timeout ที่เกิดจากภาระงานสูง&lt;/li&gt;
&lt;li&gt;Tool errors ที่มี fallback ชัดเจน&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="manual-recovery"&gt;&lt;a href="#manual-recovery" class="header-anchor"&gt;&lt;/a&gt;Manual Recovery
&lt;/h3&gt;&lt;p&gt;บางครั้งเราต้องให้คนเข้ามาช่วย&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;เมื่อไหร่ควรใช้ Manual Recovery:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Critical failures&lt;/strong&gt; — ที่ต้องการ human judgment เช่น ข้อมูลผิดพลาดร้ายแรง&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security/Compliance issues&lt;/strong&gt; — ปัญหาด้านความปลอดภัย&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;First-time failures&lt;/strong&gt; — ที่ยังไม่มี pattern ในการแก้ไขอัตโนมัติ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Business-critical decisions&lt;/strong&gt; — ที่ต้องมีคนตัดสินใจ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;กระบวนการ Manual Recovery:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;รับการแจ้งเตือน (alert)&lt;/li&gt;
&lt;li&gt;วิเคราะห์สาเหตุ (root cause analysis)&lt;/li&gt;
&lt;li&gt;ตัดสินใจแก้ไข&lt;/li&gt;
&lt;li&gt;ดำเนินการ recovery&lt;/li&gt;
&lt;li&gt;บันทึกบทเรียน&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="hybrid-approach--ทางเลอกทดทสด"&gt;&lt;a href="#hybrid-approach--%e0%b8%97%e0%b8%b2%e0%b8%87%e0%b9%80%e0%b8%a5%e0%b8%ad%e0%b8%81%e0%b8%97%e0%b8%94%e0%b8%97%e0%b8%aa%e0%b8%94" class="header-anchor"&gt;&lt;/a&gt;Hybrid Approach — ทางเลือกที่ดีที่สุด
&lt;/h3&gt;&lt;p&gt;ในความเป็นจริง ระบบส่วนใหญ่ควรใช้ &lt;strong&gt;Hybrid Approach&lt;/strong&gt; — ทำบางอย่างอัตโนมัติ บางอย่างให้คนตัดสินใจ&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;สิ่งที่ควรทำอัตโนมัติ:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Transient error retries&lt;/li&gt;
&lt;li&gt;Fallback ไปยัง secondary models&lt;/li&gt;
&lt;li&gt;Circuit breaker activation&lt;/li&gt;
&lt;li&gt;State recovery จาก checkpoints&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;สิ่งที่ควรให้คนตัดสินใจ:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Data corruption issues&lt;/li&gt;
&lt;li&gt;Security breaches&lt;/li&gt;
&lt;li&gt;Ethical concerns&lt;/li&gt;
&lt;li&gt;Business-critical decisions&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="fallback-strategies"&gt;&lt;a href="#fallback-strategies" class="header-anchor"&gt;&lt;/a&gt;Fallback Strategies
&lt;/h2&gt;&lt;p&gt;Fallback คือ &amp;ldquo;เส้นทางสำรอง&amp;rdquo; เมื่อเส้นทางหลักใช้ไม่ได้ ลองนึกภาพถนนหลักปิด เราก็ต้องมีถนนอ้อมไปถึงจุดหมาย&lt;/p&gt;
&lt;h3 id="ประเภทของ-fallback"&gt;&lt;a href="#%e0%b8%9b%e0%b8%a3%e0%b8%b0%e0%b9%80%e0%b8%a0%e0%b8%97%e0%b8%82%e0%b8%ad%e0%b8%87-fallback" class="header-anchor"&gt;&lt;/a&gt;ประเภทของ Fallback
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;1. Model-Level Fallback:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;Primary: GPT-4 → Fallback: GPT-3.5-turbo → Fallback: Local model
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;เวลา GPT-4 ใช้ไม่ได้ ก็ไปใช้ GPT-3.5 ถ้ายังไม่ได้อีก ก็ใช้ local model (อาจจะแย่กว่า แต่ยังใช้งานได้)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Provider-Level Fallback:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;OpenAI → Anthropic → Google → Local
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;กรณีที่ provider ใหญ่ล่มพร้อมกันหลายตัว ก็ต้องมีทางเลือก&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Capability-Level Fallback:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;AI-generated response → Cached response → Rule-based response → Human handoff
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;นี่คือการลดความสามารถลงอย่างมีระดับ (Graceful Degradation)&lt;/p&gt;
&lt;h3 id="fallback-hierarchy--ทำไมถงสำคญ"&gt;&lt;a href="#fallback-hierarchy--%e0%b8%97%e0%b8%b3%e0%b9%84%e0%b8%a1%e0%b8%96%e0%b8%87%e0%b8%aa%e0%b8%b3%e0%b8%84%e0%b8%8d" class="header-anchor"&gt;&lt;/a&gt;Fallback Hierarchy — ทำไมถึงสำคัญ
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;ไม่มี Fallback:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Uptime: 97-98% (7-14 ชั่วโมง down/month) &lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Recovery: Manual (1-4 ชั่วโมง)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;มี Automatic Fallback:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Uptime: 99.9%+ (&amp;lt; 45 นาที down/month) &lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Recovery: Automatic (&amp;lt; 30 วินาที)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ต่างกันมากเลย!&lt;/p&gt;
&lt;h3 id="fallback-router-pattern"&gt;&lt;a href="#fallback-router-pattern" class="header-anchor"&gt;&lt;/a&gt;Fallback Router Pattern
&lt;/h3&gt;&lt;p&gt;ลองดูตัวอย่างโค้ด:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FallbackRouter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;circuit_breaker&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;primary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;secondary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secondary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;breaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;circuit_breaker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;breaker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allow_request&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;breaker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_success&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;result&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;provider&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;primary&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;breaker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_failure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Fallback to secondary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;secondary&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;result&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;provider&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;secondary&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;หลักการสำคัญ:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ลอง primary ก่อน&lt;/li&gt;
&lt;li&gt;ถ้า fail → บอก circuit breaker&lt;/li&gt;
&lt;li&gt;แล้วไปใช้ secondary&lt;/li&gt;
&lt;li&gt;ติด tag ว่าใช้ provider ไหน (เพื่อ monitor)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="retry-logic--circuit-breaker"&gt;&lt;a href="#retry-logic--circuit-breaker" class="header-anchor"&gt;&lt;/a&gt;Retry Logic + Circuit Breaker
&lt;/h2&gt;&lt;h3 id="retry-logic"&gt;&lt;a href="#retry-logic" class="header-anchor"&gt;&lt;/a&gt;Retry Logic
&lt;/h3&gt;&lt;p&gt;การ retry ดูเหมือนเรื่องง่าย แต่ถ้าทำไม่ดี จะกลายเป็นปัญหาใหญ่&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ปัญหาที่เกิดได้:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retry ทันที → เพิ่มภาระให้ service ที่กำลังมีปัญหาอยู่แล้ว&lt;/li&gt;
&lt;li&gt;Retry ไม่จำกัด → ระบบค้างไปเรื่อยๆ&lt;/li&gt;
&lt;li&gt;Retry เหมือนเดิมทุกครั้ง → ได้ผลลัพธ์เหมือนเดิม&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Tiered Retry Recipe:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Attempt&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Original&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;standard&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Attempt&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Prompt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reduced&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Attempt&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Simplified&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;smaller&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tighter&lt;/span&gt; &lt;span class="n"&gt;constraints&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Route&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;human&lt;/span&gt; &lt;span class="n"&gt;review&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;degrade&lt;/span&gt; &lt;span class="n"&gt;gracefully&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;แต่ attempt ที่ต่างกัน ควรใช้ strategy ต่างกันด้วย&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exponential Backoff with Jitter:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;tenacity&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop_after_attempt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wait_exponential&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stop_after_attempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;wait_exponential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiplier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Exponential backoff&lt;/strong&gt; — รอนานขึ้นเรื่อยๆ ก่อน retry (2, 4, 8 วินาที)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jitter&lt;/strong&gt; — สุ่มเวลารอเล็กน้อย เพื่อไม่ให้ทุก request มาในเวลาเดียวกัน&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Max attempts&lt;/strong&gt; — จำกัดจำนวนครั้ง ไม่ให้ retry ตลอดไป&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="circuit-breaker-pattern"&gt;&lt;a href="#circuit-breaker-pattern" class="header-anchor"&gt;&lt;/a&gt;Circuit Breaker Pattern
&lt;/h3&gt;&lt;p&gt;Circuit Breaker เหมือนฟิวส์ไฟฟ้า — ถ้ามีกระแสไฟฟ้าลัดวงจรบ่อยๆ ฟิวส์ก็จะตัด เพื่อป้องกันความเสียหาย&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;สามสถานะ:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Closed&lt;/strong&gt; — ทำงานปกติ requests ผ่านได้&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open&lt;/strong&gt; — บล็อก requests ให้ fail เร็ว ไม่เพิ่มภาระ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Half-Open&lt;/strong&gt; — ทดสอบว่าฟื้นตัวหรือยัง ก่อนกลับไป Closed&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Configuration ที่ต้องตั้ง:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Failure threshold&lt;/strong&gt; — จำนวน/เปอร์เซ็นต์ failures ก่อนเปิด circuit&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timeout period&lt;/strong&gt; — รอนานแค่ไหนก่อนเข้า half-open&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Success threshold&lt;/strong&gt; — จำนวน success ที่ต้องการเพื่อปิด circuit&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rolling window&lt;/strong&gt; — ช่วงเวลาคำนวณ failure rate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;ทำไมต้องมี Circuit Breaker?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;จาก &lt;a class="link" href="https://portkey.ai/docs" target="_blank" rel="noopener"
 &gt;Portkey.ai&lt;/a&gt; &lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&amp;ldquo;Circuit breakers prevent cascading failures by stopping traffic to failing services early. Without them, retries pile up on already degraded services.&amp;rdquo;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;สมมติ service A มีปัญหา requests เริ่ม fail → เราก็ retry → ยิ่งเพิ่มภาระให้ service A → fail มากขึ้น → retry มากขึ้น → วงจรนี้เรียกว่า &amp;ldquo;cascading failure&amp;rdquo; จนระบบล่มทั้งหมด&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Circuit Breaker ช่วยหยุดวงจรนี้ได้&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="rollback-strategy"&gt;&lt;a href="#rollback-strategy" class="header-anchor"&gt;&lt;/a&gt;Rollback Strategy
&lt;/h2&gt;&lt;p&gt;นอกจาก Retry, Fallback และ Circuit Breaker แล้ว อีกสิ่งสำคัญที่ต้องมีคือ &lt;strong&gt;Rollback Strategy&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="checkpointing--จดบนทกสถานะ"&gt;&lt;a href="#checkpointing--%e0%b8%88%e0%b8%94%e0%b8%9a%e0%b8%99%e0%b8%97%e0%b8%81%e0%b8%aa%e0%b8%96%e0%b8%b2%e0%b8%99%e0%b8%b0" class="header-anchor"&gt;&lt;/a&gt;Checkpointing — จุดบันทึกสถานะ
&lt;/h3&gt;&lt;p&gt;ลองนึกภาพคุณกำลังทำ workflow ยาว 10 ขั้นตอน มาถึงขั้นตอนที่ 8 แล้วเกิดปัญหา ถ้าไม่มี checkpoint คุณต้องเริ่มต้นใหม่ตั้งแต่ขั้นตอนที่ 1&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Checkpointing ช่วยแก้ปัญหานี้:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;บันทึก state ทุกขั้นตอน&lt;/li&gt;
&lt;li&gt;สามารถย้อนกลับไปยังจุดใดก็ได้&lt;/li&gt;
&lt;li&gt;ใช้สำหรับ long-running workflows&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CheckpointManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_checkpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workflow_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# บันทึก state ปัจจุบัน&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;checkpoint/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;workflow_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rollback_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workflow_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checkpoint_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ย้อนกลับไปยัง checkpoint ที่ระบุ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;checkpoint/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;workflow_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;checkpoint_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;ตัวอย่างการใช้งานจริง:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;สมมติคุณมี workflow ประมวลผลคำสั่งซื้อ:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ตรวจสอบสินค้าคงคลัง ✓ (checkpoint)&lt;/li&gt;
&lt;li&gt;ตัด stock ✓ (checkpoint)&lt;/li&gt;
&lt;li&gt;คำนวณราคา ✓ (checkpoint)&lt;/li&gt;
&lt;li&gt;เรียก Payment API → &lt;strong&gt;FAIL&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;ถ้าไม่มี checkpoint → ต้องคืน stock เอง, ยกเลิกทุกอย่าง&lt;/li&gt;
&lt;li&gt;ถ้ามี checkpoint → rollback ไปขั้นตอนที่ 3 ระบบจัดการให้อัตโนมัติ&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="idempotent-operations--ปลอดภยตอการ-retry"&gt;&lt;a href="#idempotent-operations--%e0%b8%9b%e0%b8%a5%e0%b8%ad%e0%b8%94%e0%b8%a0%e0%b8%a2%e0%b8%95%e0%b8%ad%e0%b8%81%e0%b8%b2%e0%b8%a3-retry" class="header-anchor"&gt;&lt;/a&gt;Idempotent Operations — ปลอดภัยต่อการ Retry
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Idempotent&lt;/strong&gt; คือการที่เราเรียก operation เดิมหลายครั้ง แต่ผลลัพธ์เหมือนกัน&lt;/p&gt;
&lt;p&gt;ลองเปรียบเทียบ:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ไม่ Idempotent (อันตราย):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;POST /api/orders (สร้าง order ใหม่)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;→ Retry 3 ครั้ง → สร้าง order 3 ใบ!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Idempotent (ปลอดภัย):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;POST /api/orders? idempotency_key=abc123
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;→ Retry 3 ครั้ง → สร้าง order 1 ใบ
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;หลักการสำคัญสำหรับ AI Systems:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ใช้ idempotency key สำหรับทุก API call ที่เปลี่ยนแปลง state&lt;/li&gt;
&lt;li&gt;ออกแบบ prompts ให้ได้ผลลัพธ์คล้ายกันเมื่อ retry&lt;/li&gt;
&lt;li&gt;หลีกเลี่ยง side effects ที่สะสม (เช่น ส่ง email ซ้ำ)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="ตวอยางจรงจาก-openclaw"&gt;&lt;a href="#%e0%b8%95%e0%b8%a7%e0%b8%ad%e0%b8%a2%e0%b8%b2%e0%b8%87%e0%b8%88%e0%b8%a3%e0%b8%87%e0%b8%88%e0%b8%b2%e0%b8%81-openclaw" class="header-anchor"&gt;&lt;/a&gt;ตัวอย่างจริงจาก OpenClaw
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;OpenClaw&lt;/strong&gt; มีระบบ Fallback 3 ชั้นที่น่าสนใจ:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;Layer 1: Auth Profile Rotation
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; - สลับระหว่าง credentials ต่างๆ (OpenAI, Anthropic)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;Layer 2: Thinking Level Fallback (per profile)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; - high → medium → low → off
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; - reset เมื่อ switch profile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;Layer 3: Model Fallback
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; - claude-opus → gpt-4o → gemini-2.0-flash → default
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; - trigger หลัง Layer 1 &amp;amp; 2 ใช้ไม่ได้
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;การจำแนกประเภท Error:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Error Type&lt;/th&gt;
 &lt;th&gt;วิธีจัดการ&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Billing failures&lt;/td&gt;
 &lt;td&gt;ไม่ retry (เป็นปัญหาที่ account)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Rate limits&lt;/td&gt;
 &lt;td&gt;Retry with backoff (ชั่วคราว)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Model errors&lt;/td&gt;
 &lt;td&gt;Fallback ไปยัง alternative models&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;ปัญหาที่พบ (Issue #6230):&lt;/strong&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&amp;ldquo;When primary model fails and agent falls back to lower-priority model, it stays on fallback permanently until manually restarted. No automatic recovery path.&amp;rdquo;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;นี่คือปัญหาที่พบในระบบจริง — เมื่อระบบ fallback ไปใช้ model ที่ต่ำกว่าแล้ว มันไม่ยอมกลับไปใช้ model หลักเมื่อ model หลักฟื้นตัว&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best Practices จาก OpenClaw:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ใช้ &lt;code&gt;clawbot doctor --fix&lt;/code&gt; สำหรับ auto-repair&lt;/li&gt;
&lt;li&gt;สร้าง backup ก่อนแก้ไข configuration&lt;/li&gt;
&lt;li&gt;ใช้ systemd service สำหรับ auto-restart&lt;/li&gt;
&lt;li&gt;แยกแยะ error types ต่างกัน (billing vs rate limit)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="ตวอยางจรงจาก-langchain--autogen"&gt;&lt;a href="#%e0%b8%95%e0%b8%a7%e0%b8%ad%e0%b8%a2%e0%b8%b2%e0%b8%87%e0%b8%88%e0%b8%a3%e0%b8%87%e0%b8%88%e0%b8%b2%e0%b8%81-langchain--autogen" class="header-anchor"&gt;&lt;/a&gt;ตัวอย่างจริงจาก LangChain + AutoGen
&lt;/h2&gt;&lt;h3 id="langchain"&gt;&lt;a href="#langchain" class="header-anchor"&gt;&lt;/a&gt;LangChain
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://python.langchain.com/docs" target="_blank" rel="noopener"
 &gt;LangChain&lt;/a&gt; &lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt; มี built-in retry mechanisms และ fallback support:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;langchain_groq&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatGroq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ChatGroq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;mixtral-8x7b-32768&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;max_retries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# Default retry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;RunnableWithFallbacks:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;langchain_core.runnables&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RunnableWithFallbacks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;chain_with_fallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RunnableWithFallbacks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;primary_chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;fallbacks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;backup_chain1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;backup_chain2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Tool Error Handling:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Enable handle_tool_error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SomeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;handle_tool_error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt; &lt;span class="c1"&gt;# หรือใส่ custom function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# หรือใช้ try-except&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stop_after_attempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;wait_exponential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiplier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;safe_tool_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;TransientError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="c1"&gt;# ให้ retry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;PermanentError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fallback_response&lt;/span&gt; &lt;span class="c1"&gt;# ไม่ retry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;LangGraph Error Handling:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;langchain.memory&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ConversationBufferMemory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;langchain.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AgentExecutor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConversationBufferMemory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;memory_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;chat_history&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;return_messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AgentExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Error handling with state tracking&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;error_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ErrorHandlerNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retry_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;error_handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retry_limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;switch_to_alternative_path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="autogen-microsoft"&gt;&lt;a href="#autogen-microsoft" class="header-anchor"&gt;&lt;/a&gt;AutoGen (Microsoft)
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://microsoft.github.io/autogen/" target="_blank" rel="noopener"
 &gt;AutoGen&lt;/a&gt; &lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt; v0.4 มี resilience features ที่ออกแบบมาสำหรับ production:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Robustness:&lt;/strong&gt; ถ้า agent หนึ่งล้ม ระบบสามารถ re-route task ไปยัง agent อื่น&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fault Tolerance:&lt;/strong&gt; ออกแบบสำหรับ production environments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; Scale agents ตาม demand&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Checkpointing &amp;amp; Recovery:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Checkpointing สำหรับ resume workflows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;checkpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;resume_from_checkpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;checkpoint_id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Multi-Agent Failure Recovery:&lt;/strong&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&amp;ldquo;Traditional circuit breakers assume stateless services. AI agents violate these assumptions due to stateful nature, learning capabilities, and context maintenance.&amp;rdquo;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;สำหรับ Multi-Agent Systems ต้องมี:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Shared Circuit Breaker State&lt;/strong&gt; — Agents แชร์สถานะ circuit breaker&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Progressive Traffic Restoration&lt;/strong&gt; — ค่อยๆ กลับมาใช้งาน&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State Synchronization&lt;/strong&gt; — จัดการ state หลัง recovery&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conflict Resolution&lt;/strong&gt; — แก้ไขข้อขัดแย้งใน views&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="best-practices--monitoring"&gt;&lt;a href="#best-practices--monitoring" class="header-anchor"&gt;&lt;/a&gt;Best Practices + Monitoring
&lt;/h2&gt;&lt;h3 id="design-principles--หลกการออกแบบ"&gt;&lt;a href="#design-principles--%e0%b8%ab%e0%b8%a5%e0%b8%81%e0%b8%81%e0%b8%b2%e0%b8%a3%e0%b8%ad%e0%b8%ad%e0%b8%81%e0%b9%81%e0%b8%9a%e0%b8%9a" class="header-anchor"&gt;&lt;/a&gt;Design Principles — หลักการออกแบบ
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Design for Failure&lt;/strong&gt; — สมมติว่าทุกอย่างจะล้ม&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fail Fast&lt;/strong&gt; — แจ้ง failure เร็วที่สุด&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Graceful Degradation&lt;/strong&gt; — ลดความสามารถลงอย่างมีระดับ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability&lt;/strong&gt; — มองเห็นทุกอย่างที่เกิดขึ้น&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Idempotency&lt;/strong&gt; — ปลอดภัยต่อการ retry&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="implementation-checklist"&gt;&lt;a href="#implementation-checklist" class="header-anchor"&gt;&lt;/a&gt;Implementation Checklist
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Retry Logic:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Exponential backoff with jitter&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Max retry limits&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Different strategies ตาม error types&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Timeout per attempt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Circuit Breaker:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Failure threshold configuration&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Half-open state testing&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Metrics &amp;amp; monitoring&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Integration with fallback&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fallback:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Define fallback hierarchy&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Test fallback paths&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Monitor fallback usage&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Human handoff procedure&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Recovery:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Checkpointing strategy&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; State persistence&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Rollback capability&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Recovery testing&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="metrics-ทควรตดตาม"&gt;&lt;a href="#metrics-%e0%b8%97%e0%b8%84%e0%b8%a7%e0%b8%a3%e0%b8%95%e0%b8%94%e0%b8%95%e0%b8%b2%e0%b8%a1" class="header-anchor"&gt;&lt;/a&gt;Metrics ที่ควรติดตาม
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Metric&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;th&gt;Alert Threshold&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Error Rate&lt;/td&gt;
 &lt;td&gt;% ของ requests ที่ fail&lt;/td&gt;
 &lt;td&gt;&amp;gt; 5%&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Retry Rate&lt;/td&gt;
 &lt;td&gt;% ของ requests ที่ต้อง retry&lt;/td&gt;
 &lt;td&gt;&amp;gt; 20%&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Circuit Breaker State&lt;/td&gt;
 &lt;td&gt;Open/Closed/Half-open&lt;/td&gt;
 &lt;td&gt;ติด Open &amp;gt; 5 นาที&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Fallback Rate&lt;/td&gt;
 &lt;td&gt;% ที่ใช้ fallback&lt;/td&gt;
 &lt;td&gt;&amp;gt; 10%&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Recovery Time&lt;/td&gt;
 &lt;td&gt;เวลาที่ใช้ในการกู้ตัว&lt;/td&gt;
 &lt;td&gt;&amp;gt; 30 วินาที&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;MTTR&lt;/td&gt;
 &lt;td&gt;Mean Time To Recovery&lt;/td&gt;
 &lt;td&gt;&amp;gt; 5 นาที&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="สรป"&gt;&lt;a href="#%e0%b8%aa%e0%b8%a3%e0%b8%9b" class="header-anchor"&gt;&lt;/a&gt;สรุป
&lt;/h2&gt;&lt;p&gt;วันนี้เราได้เรียนรู้การออกแบบ Recovery Paths ครบถ้วน:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ส่วนที่ 1:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ทำไมต้องมี Recovery Paths&lt;/li&gt;
&lt;li&gt;Auto vs Manual Recovery&lt;/li&gt;
&lt;li&gt;Fallback Strategies (Model → Provider → Capability)&lt;/li&gt;
&lt;li&gt;Retry Logic + Circuit Breaker&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;ส่วนที่ 2:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rollback Strategy&lt;/strong&gt; — Checkpointing และ Idempotent Operations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ตัวอย่างจาก OpenClaw&lt;/strong&gt; — ระบบ 3 Layer Fallback&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ตัวอย่างจาก LangChain + AutoGen&lt;/strong&gt; — Built-in mechanisms&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best Practices&lt;/strong&gt; — หลักการออกแบบ + Metrics ที่ต้องติดตาม&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;บทเรียนสำคัญ:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ออกแบบระบบโดยคิดว่าทุกอย่างจะล้ม&lt;/li&gt;
&lt;li&gt;มี Fallback หลายระดับ (Model → Provider → Capability)&lt;/li&gt;
&lt;li&gt;ใช้ Circuit Breaker ป้องกัน Cascading Failures&lt;/li&gt;
&lt;li&gt;Checkpoint เพื่อให้ Rollback ได้&lt;/li&gt;
&lt;li&gt;ทำทุกอย่างให้ Idempotent&lt;/li&gt;
&lt;li&gt;ติดตาม Metrics อย่างต่อเนื่อง&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;AI Systems ต้องการการดูแลมากกว่าซอฟต์แวร์ทั่วไป เพราะมีจุดล้มเหลวหลายจุด แต่ถ้าเราออกแบบมาดี ระบบก็สามารถ &amp;ldquo;รู้จักแก้ตัว&amp;rdquo; ได้ด้วยตัวเอง&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="อางอง"&gt;&lt;a href="#%e0%b8%ad%e0%b8%b2%e0%b8%87%e0%b8%ad%e0%b8%87" class="header-anchor"&gt;&lt;/a&gt;อ้างอิง
&lt;/h2&gt;&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Reviewer 2 — Complete&lt;/em&gt;
&lt;em&gt;Status: ตรวจสอบและแก้ไขแล้ว&lt;/em&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a class="link" href="https://uptimeinstitute.com/resources/research-and-reports/annual-data-center-survey" target="_blank" rel="noopener"
 &gt;Uptime Institute Annual Report 2024&lt;/a&gt; - สถิติ uptime ของระบบที่ไม่มี fallback mechanism&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a class="link" href="https://sre.google/sre-book/availability-table/" target="_blank" rel="noopener"
 &gt;Google SRE Book - Reliability Targets&lt;/a&gt; - เปรียบเทียบ uptime ระหว่างระบบที่มีและไม่มี automatic recovery&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a class="link" href="https://portkey.ai/docs" target="_blank" rel="noopener"
 &gt;Portkey.ai Documentation - Circuit Breakers&lt;/a&gt; - Best practices สำหรับ circuit breaker pattern ใน AI systems&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a class="link" href="https://python.langchain.com/docs/how_to/fallbacks/" target="_blank" rel="noopener"
 &gt;LangChain Documentation - Retry and Fallback&lt;/a&gt; - Built-in retry mechanisms และ fallback support&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;&lt;a class="link" href="https://microsoft.github.io/autogen/stable/" target="_blank" rel="noopener"
 &gt;Microsoft AutoGen Documentation&lt;/a&gt; - Resilience features สำหรับ multi-agent systems&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item></channel></rss>