Mở đầu: Khi các agent chờ nhau mãi mãi

Bài 11 cho thấy 2 agent ghi ĐÈ lên nhau gây mất dữ liệu. Có một lớp lỗi phối hợp khác, tinh vi hơn: 2 agent không ghi đè gì cả — chúng chỉ đơn giản chờ nhau mãi mãi, và cả hệ thống đứng hình dù không có exception nào được ném ra. Đây là bài cuối cùng của Track B, khép lại bằng việc so sánh 2 kiến trúc multi-agent phổ biến nhất hiện nay.

File dùng chung aisys-orchestrator.js được mở rộng lần cuối trong Track B với LockManager, detectDeadlock, và checkLivelock.


📚 Điều kiện tiên quyết
Nên đọc Bài 11 trước — bài này dùng lại aisys-orchestrator.js và giả định bạn đã quen khái niệm nhiều agent cùng truy cập tài nguyên chung.

1. Deadlock Giữa Agent

Deadlock xảy ra khi AgentX giữ tài nguyên A và chờ tài nguyên B (đang bị AgentY giữ), trong khi AgentY giữ tài nguyên B và chờ tài nguyên A (đang bị AgentX giữ) — một vòng chờ khép kín không agent nào có thể tự thoát ra:

wait-for-graph.js
// waitForGraph: agent -> agent nó đang CHỜ (vì tài nguyên nó cần đang bị agent kia giữ)
const waitForGraph = { AgentX: "AgentY", AgentY: "AgentX" };

function detectDeadlock(waitForGraph) {
  for (const start of Object.keys(waitForGraph)) {
    const path = [start];
    let current = start;
    while (waitForGraph[current]) {
      current = waitForGraph[current];
      if (current === start) return { deadlock: true, cycle: [...path, current] };
      if (path.includes(current)) break;
      path.push(current);
    }
  }
  return { deadlock: false };
}
// detectDeadlock(waitForGraph) => { deadlock: true, cycle: ["AgentX","AgentY","AgentX"] }

Kỹ thuật này gọi là wait-for graph cycle detection — một thuật toán kinh điển từ hệ điều hành (deadlock giữa các tiến trình tranh chấp tài nguyên), áp dụng nguyên vẹn cho multi-agent.

2. Livelock — Vòng Lặp "Nhường Nhau" Không Tiến Triển

Livelock tinh vi hơn deadlock: không agent nào thực sự bị "khoá cứng" — cả hai vẫn đang "hoạt động" (gửi message, phản hồi nhau) nhưng không ai THỰC SỰ tiến bộ, vì cả hai liên tục nhường lượt cho nhau (giống 2 người cùng né sang một bên trong hành lang hẹp, cả hai né CÙNG một hướng liên tục). Vì không có ai bị khoá, kỹ thuật dò CHU TRÌNH CHỜ ở mục 1 không phát hiện được livelock — cần một phương pháp hoàn toàn khác: theo dõi TIẾN ĐỘ thật qua thời gian.

progress-monitor.js
function checkLivelock(progressHistory, windowSize = 4) {
  if (progressHistory.length < windowSize) return false;
  const recent = progressHistory.slice(-windowSize);
  return recent.every((p) => p === recent[0]); // tiến độ ĐỨNG YÊN suốt cửa sổ gần nhất
}
💡 Mẹo: Deadlock dò bằng ĐỒ THỊ, livelock dò bằng TIẾN ĐỘ
Đây là điểm dễ nhầm nhất: nhiều người cố dùng chung 1 cơ chế phát hiện cho cả hai. Deadlock có cấu trúc tĩnh (ai chờ ai) nên dò bằng đồ thị là đủ. Livelock không có cấu trúc tĩnh nào để dò — thứ duy nhất phản bội nó là THỜI GIAN TRÔI QUA MÀ KHÔNG CÓ GÌ THAY ĐỔI, nên bắt buộc phải theo dõi lịch sử tiến độ qua nhiều bước, không thể phát hiện chỉ từ 1 snapshot trạng thái.

3. Timeout & Circuit-Breaker

🕳️ Cạm bẫy: Không có cơ chế phá vỡ, hệ thống treo vĩnh viễn
Cả deadlock lẫn livelock đều có điểm chung nguy hiểm: nếu không có can thiệp từ BÊN NGOÀI vòng lặp, hệ thống sẽ treo mãi mãi (deadlock) hoặc chạy vô ích tốn chi phí mãi mãi (livelock) — không agent nào bên trong có thể tự nhận ra và thoát ra, vì góc nhìn của từng agent quá hẹp để thấy toàn cảnh. Bắt buộc phải có 1 cơ chế giám sát TỪ BÊN NGOÀI với quyền cưỡng chế.

Circuit-breaker giải quyết cả hai: một cơ chế giám sát bên ngoài, sau N tick không tiến triển (hoặc phát hiện chu trình chờ), CƯỠNG CHẾ phá vỡ tình huống — giải phóng lock của 1 agent (deadlock) hoặc buộc 1 agent phải hành động thay vì tiếp tục nhường (livelock):

circuit-breaker.js
class LockManager {
  // ... request()/release() như Bài 11 ...
  forceRelease(resource) {
    this.locks.delete(resource); // cưỡng chế phá khoá — phá vỡ vòng chờ chéo
  }
}

4. AutoGen (Group Chat) vs CrewAI (Hierarchical Crew)

Hai framework agent phổ biến chọn 2 kiến trúc điều phối khác hẳn nhau, mỗi bên đánh đổi rủi ro deadlock/livelock khác nhau:

Tiêu chí AutoGen (Group Chat) CrewAI (Hierarchical Crew)
Mô hình điều phối Phi tập trung hơn — mọi agent thấy chung 1 lịch sử hội thoại, tự quyết định lượt nói tiếp theo Tập trung hơn — 1 "manager" agent phân việc xuống các agent cấp dưới theo cây phân cấp
Rủi ro đặc trưng Livelock — nhiều agent cùng "nhường" lượt nói, không ai chốt hành động Deadlock/SPOF — nếu manager chờ phản hồi 1 agent con bị treo, toàn bộ cây con dừng theo
Cơ chế phá vỡ phù hợp Theo dõi tiến độ hội thoại, ép chốt sau N lượt không quyết định Timeout theo tầng cây, circuit-breaker cưỡng chế manager bỏ qua agent con bị treo

5. Thực hành tương tác: Deadlock & Circuit Breaker Simulator

Chọn kịch bản Deadlock hoặc Livelock, bấm "Bước tiếp theo" nhiều lần để thấy tình huống hình thành, rồi bấm "Kích hoạt Circuit Breaker" để phá vỡ nó:

⛓️ Deadlock & Circuit Breaker Simulator
aisys-deadlock-lab.js (trích)
import { LockManager, detectDeadlock, checkLivelock } from "./aisys-orchestrator.js";
const reqX = lockManager.request("AgentX", "Cache_Lock"); // bị chặn vì AgentY đang giữ
const reqY = lockManager.request("AgentY", "DB_Lock");    // bị chặn vì AgentX đang giữ
detectDeadlock({ AgentX: "AgentY", AgentY: "AgentX" }); // => { deadlock: true }

Track B đã hoàn chỉnh: Message Passing (Bài 10) + Blackboard (Bài 11) + Deadlock/Livelock/Circuit-Breaker (bài này). Bài 13 — Capstone — sẽ ghép TOÀN BỘ series: pipeline (Track A) + framework agent (Track C) + orchestration (Track B) thành một "AI Ops Center" hoàn chỉnh.

Tải file code thực hành minh họa bài học

File JavaScript aisys-orchestrator.jsLockManager/detectDeadlock/checkLivelock vừa thêm ở bài này, cùng aisys-deadlock-lab.js wiring demo:

Tải về aisys-orchestrator.js

📖 Tài liệu tham khảo

Bài viết liên quan trong series

Bài 11: Blackboard Pattern & Shared State Bài 13: Dự Án — AI Ops Center Quay lại Lộ trình Kỹ Thuật Hệ Thống AI

Bình luận