เอนจินลูป Agent

เอนจินลูป Agent

ภาพรวม

เอนจินลูป Agent (Agent Loop) เป็นกลไกการทำงานหลักของโมดูล Work ในพื้นที่ทำงาน มันขับเคลื่อนให้ AI Agent ทำการวนลูปเชิงเหตุผล-การทำงานแบบอัตโนมัติ: วิเคราะห์งาน → เลือกเครื่องมือ → ทำการดำเนินการ → ประเมินผลลัพธ์ → ทำเหตุผลต่อ จนกว่างานจะเสร็จสิ้นหรือเข้าเงื่อนไขการออก

เอนจินใช้สถาปัตยกรรมแบบ provider-agnostic โดยรองรับผู้ให้บริการโมเดลหลายรายผ่านอินเทอร์เฟซ LLM Adapter ที่เป็นหนึ่งเดียว


สถาปัตยกรรม

LLM Adapter

AgentEngine │ ├── OpenAIAdapter │ ├── Responses API(增量状态管理) │ └── Chat Completions API(全量上下文) │ └── AnthropicAdapter └── Messages API(原生 streaming + thinking)
                      
                      AgentEngine
    │
    ├── OpenAIAdapter
    │   ├── Responses API(增量状态管理)
    │   └── Chat Completions API(全量上下文)
    │
    └── AnthropicAdapter
        └── Messages API(原生 streaming + thinking
                    
บล็อกโค้ดนี้ในหน้าต่างลอย

Adapter จะจัดการโดยอัตโนมัติ:

  • การแปลงรูปแบบข้อความ (OpenAI ↔ Anthropic)
  • การแปลงนิยามเครื่องมือ
  • การจัดการ Think Tag (ตัดแท็ก <think> ของโมเดลอย่าง DeepSeek ออกโดยอัตโนมัติ)

ขั้นตอนการวนลูป

┌─ 预检验证 ──────────────────────────────────────────────┐ │ 拒绝超过输入预算 60% 的提示词,防止静默截断 │ └──────────────────────────┬──────────────────────────────┘ ▼ ┌─ 主循环(Round 0 → maxTurns-1)─────────────────────────┐ │ │ │ ① 上下文管理 │ │ - 预防性工具结果截断(Layer 1) │ │ - 检查是否需要压实(shouldPreemptiveCompact) │ │ │ │ ② LLM 调用 │ │ - 流式推理(text_delta + thinking + tool_use) │ │ - 事件实时推送到 UI │ │ │ │ ③ 工具执行 │ │ - validateToolCalls → 验证合法性 │ │ - 并发分区 → 按 concurrency 元数据分组 │ │ - 并行执行 → 结果归一化 │ │ │ │ ④ 退出判断 │ │ - 无工具调用 → 退出(end_turn) │ │ - 达到限制 → 退出(max_rounds/max_budget/deadline) │ │ - 异常 → 退出(circuit_breaker/fatal_error) │ │ - 有工具调用 → 继续下一轮 │ │ │ └──────────────────────────────────────────────────────────┘
                      
                      ┌─ 预检验证 ──────────────────────────────────────────────┐
│ 拒绝超过输入预算 60% 的提示词,防止静默截断              │
└──────────────────────────┬──────────────────────────────┘
                           ▼
┌─ 主循环(Round 0 → maxTurns-1)─────────────────────────┐
│                                                          │
│  ① 上下文管理                                            │
│     - 预防性工具结果截断(Layer 1)                        │
│     - 检查是否需要压实(shouldPreemptiveCompact)          │
│                                                          │
│  ② LLM 调用                                              │
│     - 流式推理(text_delta + thinking + tool_use)        │
│     - 事件实时推送到 UI                                   │
│                                                          │
│  ③ 工具执行                                              │
│     - validateToolCalls → 验证合法性                      │
│     - 并发分区 → 按 concurrency 元数据分组                │
│     - 并行执行 → 结果归一化                               │
│                                                          │
│  ④ 退出判断                                              │
│     - 无工具调用 → 退出(end_turn)                       │
│     - 达到限制 → 退出(max_rounds/max_budget/deadline)   │
│     - 异常 → 退出(circuit_breaker/fatal_error)          │
│     - 有工具调用 → 继续下一轮                             │
│                                                          │
└──────────────────────────────────────────────────────────┘

                    
บล็อกโค้ดนี้ในหน้าต่างลอย

พารามิเตอร์การวนลูป

พารามิเตอร์ ค่าเริ่มต้น คำอธิบาย
maxTurns 25 จำนวนรอบการวนลูปสูงสุด
maxErrors เกณฑ์จำนวนข้อผิดพลาดของเครื่องมือที่เกิดต่อเนื่อง
maxBudgetInputTokens เพดานงบประมาณ token อินพุต
maxExecutionMs เพดานเวลาการทำงาน (มิลลิวินาที)
snapshotStrategy every_tool_round กลยุทธ์การบันทึกสแนปช็อต
resumeSessionId ID สำหรับกู้คืนเซสชันที่ถูกขัดจังหวะ

เงื่อนไขการออก 8 แบบ

เหตุผลการออก เงื่อนไขที่ทำให้เกิด
end_turn Agent ทำงานเสร็จสิ้น ไม่มีการเรียกเครื่องมือเพิ่มเติม
max_rounds ถึงเพดาน maxTurns (ค่าเริ่มต้น 25 รอบ)
circuit_breaker การเรียก LLM ล้มเหลวติดต่อกัน 5 ครั้ง
no_tool_calls ไม่มีคำขอเรียกเครื่องมือในการตอบกลับของ LLM
user_cancel ผู้ใช้ยกเลิกด้วยตนเอง
context_overflow คอนเท็กซ์ยังคงล้นแม้หลังการบีบอัด
fatal_error ข้อผิดพลาดที่กู้คืนไม่ได้ (การยืนยันตัวตนล้มเหลว, ปัญหาการเรียกเก็บเงิน ฯลฯ)
compaction_exhausted ใช้จำนวนครั้งการลองบีบอัดใหม่จนหมด (สูงสุด 5 ครั้ง)

กลไกเซอร์กิตเบรกเกอร์

ป้องกันไม่ให้ LLM ล้มเหลวต่อเนื่องจนเกิดการลองใหม่ไม่รู้จบ:

พารามิเตอร์ ค่า คำอธิบาย
CIRCUIT_OPEN_THRESHOLD 5 ล้มเหลวติดต่อกัน 5 ครั้งจะทำให้เซอร์กิตเบรกเกอร์ทำงาน
CIRCUIT_OPEN_WAIT_MS 60,000 หลังเซอร์กิตเบรกเกอร์เปิด จะระบายความร้อน 60 วินาที

การจำแนกข้อผิดพลาดและกลยุทธ์การลองใหม่:

ประเภทข้อผิดพลาด กลยุทธ์
rate_limit ถอยแบบเอ็กซ์โพเนนเชียล + ลองใหม่พร้อมสุ่มค่าหน่วง (jitter)
timeout / overloaded ลองใหม่ทันที
context_overflow เรียกใช้การบีบอัดคอนเท็กซ์
auth / billing / model_not_found โยนข้อผิดพลาดออกทันที (ไม่ลองใหม่)

อีเวนต์แบบสตรีม

กระบวนการทำงานของ Agent จะแจ้ง UI แบบเรียลไทม์ผ่านอีเวนต์แบบสตรีม:

ประเภทอีเวนต์ ข้อมูล คำอธิบาย
text_delta ชิ้นส่วนข้อความ การส่งข้อความเอาต์พุตของ Agent แบบเพิ่มทีละส่วน
thinking ชิ้นส่วนความคิด เนื้อหาห่วงโซ่ความคิด (chain of thought) แบบเนทีฟ (โมเดล thinking ของ Anthropic)
tool_use_start ชื่อเครื่องมือ + พารามิเตอร์ เริ่มการเรียกเครื่องมือ
tool_result ผลลัพธ์การทำงาน การทำงานของเครื่องมือเสร็จสิ้น
error ข้อมูลข้อผิดพลาด ข้อผิดพลาดระหว่างการทำงาน
done เหตุผลการออก การวนลูปรอบนี้สิ้นสุด

อีเวนต์ของ Sub-agent จะถูกส่งผ่านไปยังหน้าจอ UI ของ Agent แม่


การปรับเทียบ Token แบบ EMA

เอนจินใช้ค่าเฉลี่ยเคลื่อนที่แบบเอ็กซ์โพเนนเชียล (EMA) เพื่อปรับเทียบความแม่นยำในการประมาณ token แบบไดนามิก:

พารามิเตอร์ ค่า คำอธิบาย
ค่าเริ่มต้น 3.0 chars/token การประมาณแบบระมัดระวัง (เหมาะกับกรณีผสมภาษาจีน + โค้ด)
3 ครั้งแรก ค่าเฉลี่ยลู่เข้า เข้าใกล้ค่าจริงอย่างรวดเร็ว
หลังจากนั้น EMA α=0.15 ติดตามการใช้งานจริงอย่างราบรื่น
การกรอง 0.5 < observed < 8 ตัดค่าผิดปกติออก

หลังการเรียก LLM แต่ละครั้ง จะอัปเดตปัจจัยการปรับเทียบด้วยการใช้ token จริง เพื่อให้การประมาณงบประมาณคอนเท็กซ์แม่นยำยิ่งขึ้นเรื่อย ๆ


สแนปช็อตเซสชัน

รองรับการบันทึกสถานะเซสชันแบบถาวร เพื่อป้องกันการสูญเสียความคืบหน้าจากการขัดจังหวะที่ไม่คาดคิด:

กลยุทธ์ จังหวะที่ทำงาน
every_tool_round (ค่าเริ่มต้น) หลังการเรียกเครื่องมือแต่ละครั้งเสร็จสิ้น
every_round หลังการโต้ตอบ LLM แต่ละรอบ
manual ทำงานเมื่อเรียกด้วยตนเองเท่านั้น

สแนปช็อตถูกจัดเก็บเป็นไฟล์ JSON โดยใช้การเขียนแบบอะตอมมิก (.tmp + rename) เพื่อป้องกันไฟล์เสียหาย สามารถกู้คืนเซสชันที่ถูกขัดจังหวะได้ผ่าน resumeSessionId



สิ่งนี้มีความหมายอย่างไรต่อผู้ใช้

Agent Loop คือความสามารถที่ทำให้คุณสัมผัสได้ว่า "Agent กำลังทำงานอย่างต่อเนื่อง" เมื่อคุณพูดว่า "ช่วยปรับโครงสร้างโค้ดของโปรเจกต์นี้ให้หน่อย" Agent จะไม่ตอบเพียงคำแนะนำแล้วหยุด แต่มันจะเรียกดูไฟล์ วิเคราะห์โครงสร้าง แก้ไขทีละส่วน รันการทดสอบโดยอัตโนมัติ จนกว่าจะเสร็จสิ้น

ปรากฏการณ์ที่คุณสังเกตได้:

  • Agent เรียกใช้เครื่องมือหลายอย่างต่อเนื่อง (ลิสต์ไฟล์ → อ่านไฟล์ → แก้ไขไฟล์ → รันการทดสอบ) โดยการเรียกเครื่องมือจะปรากฏขึ้นตามลำดับบนหน้าจอ
  • หาก Agent ล้มเหลวติดต่อกัน 5 ครั้ง (เช่น API หมดเวลา) มันจะหยุดพัก 60 วินาทีแทนที่จะลองใหม่ไม่รู้จบ คุณจะเห็นช่วงรอสักครู่ก่อนที่ Agent จะบอกคุณว่าพบปัญหา
  • โดยค่าเริ่มต้นจะทำงานสูงสุด 25 รอบ งานที่ซับซ้อนมากอาจหยุดหลังจาก 25 รอบและบอกคุณว่า "ถึงจำนวนรอบสูงสุดแล้ว"

สิ่งที่คุณทำได้:

  • คลิกปุ่ม หยุด เพื่อยกเลิกการทำงานของ Agent ได้ทุกเมื่อ
  • หาก Agent ทำงานผิดทิศทาง ให้ยกเลิกแล้วให้คำสั่งที่ชัดเจนยิ่งขึ้น
  • สำหรับงานที่ซับซ้อนเป็นพิเศษ คุณสามารถให้ Agent วางแผนก่อนแล้วค่อยลงมือทำ ("วางแผนมาก่อน รอฉันยืนยันแล้วค่อยลงมือทำ")

เอกสารที่เกี่ยวข้อง