Deadlocks агентів: коли агенти блокують один одного

Deadlock виникає, коли кілька агентів чекають один на одного і система не може рухатися далі. Чому це трапляється у multi-agent системах і як цього уникнути.
На цій сторінці
  1. Проблема
  2. Чому це стається
  3. Які збої трапляються найчастіше
  4. Циклічне очікування (Circular wait)
  5. Блокування ресурсу без TTL (Lock without lease)
  6. Завислі стани очікування (Unbounded waiting)
  7. Retry-цикл між агентами (Cross-agent retry loop)
  8. Як виявляти ці проблеми
  9. Як відрізнити deadlock від справді довгої задачі
  10. Як зупиняти такі збої
  11. Де це реалізується в архітектурі
  12. Самоперевірка
  13. FAQ
  14. Пов'язані сторінки

Проблема

У трейсах одного run видно цикл очікування: Agent A → Agent B → Agent C → Agent A.

За 20 хвилин таких run'ів у статусі waiting може стати 40+. Черга росте, воркери зайняті, а корисної роботи майже немає.

Ззовні все виглядає "тихо": немає явної помилки, немає падіння сервісу. Але run не завершується, бо всі три агенти просто чекають один одного.

Система не падає.

Вона просто зависає і тихо спалює ресурси.

Аналогія: уяви трьох людей, які стоять у дверях і чемно пропускають один одного. Ніхто не свариться і не робить "помилку", але ніхто не проходить. Deadlock у multi-agent системах виглядає саме так.

Чому це стається

Deadlock виникає не тому, що агенти думають довго, а тому, що система не знає, хто має рухати стан далі.

У production зазвичай так:

  1. агенти обмінюються повідомленнями і залежать один від одного;
  2. одне очікування затримується (tool, approval, lock);
  3. інші агенти теж переходять у waiting;
  4. без timeout і власника стану workflow застрягає.

Проблема не в окремому агенті. Проблема в неконтрольованій координації між агентами.

Які збої трапляються найчастіше

Щоб не ускладнювати, у deadlocks найчастіше бачать чотири патерни.

Циклічне очікування (Circular wait)

Agent A чекає B, B чекає C, C чекає A. Усі "зайняті", але прогресу немає.

Типова причина: граф залежностей містить цикл, і немає єдиного оркестратора.

Блокування ресурсу без TTL (Lock without lease)

Агент взяв lock на документ/тікет і впав. Інші агенти чекають цей lock без кінця.

Типова причина: lock без lease/TTL і без механізму відновлення власника.

Завислі стани очікування (Unbounded waiting)

Є timeout на HTTP, але немає timeout на внутрішні agent waits. Workflow може чекати "вічно".

Типова причина: таймаути реалізовані на transport-рівні, але не на рівні orchestration-станів.

Retry-цикл між агентами (Cross-agent retry loop)

Агенти перенаправляють задачу один одному "ще раз перевір", і це перетворюється на нескінченний ping-pong.

Типова причина: немає ліміту повторів і stop reason для blocked-state сценаріїв.

Як виявляти ці проблеми

Deadlock добре видно по комбінації метрик workflow і runtime.

МетрикаСигнал deadlockЩо робити
waiting_runsкількість run'ів у waiting стабільно ростедодати wait-timeout і stop reason для blocked-state
wait_duration_p95очікування довше за нормуобмежити час очікування на кожному переході стану
blocked_transition_rateчасті блокування між тими ж агентамиперевірити граф залежностей на цикли
lease_conflict_rateчасті конфлікти або прострочені leasesдодати TTL, renew і recovery-політику
queue_backlogчерга росте при нормальному вхідному трафікускинути завислі run'и, ввести fallback-mode

Як відрізнити deadlock від справді довгої задачі

Не кожен довгий run — deadlock. Ключовий критерій: чи є переходи стану і корисний прогрес.

Нормально, якщо:

  • статус workflow змінюється очікувано;
  • після очікування з'являється новий артефакт або крок;
  • є чіткий owner поточного transition.

Небезпечно, якщо:

  • run довго стоїть у тому самому waiting стані;
  • кілька агентів одночасно "чекають" один одного;
  • немає зрозумілого stop reason, чому система не рухається.

Як зупиняти такі збої

Практично це виглядає так:

  1. вводиш одного власника transitions (orchestrator або leader);
  2. ставиш timeout на кожне waiting очікування;
  3. використовуєш lease/TTL для shared resources;
  4. при no-progress завершуєш run керовано: stop reason + fallback.

Мінімальний guard для wait-state:

PYTHON
import time


class WaitGuard:
    def __init__(self, wait_timeout_s: int = 30):
        self.wait_timeout_s = wait_timeout_s
        self.wait_started_at: dict[str, float] = {}

    def mark_wait_start(self, run_id: str):
        self.wait_started_at[run_id] = time.time()

    def check_wait(self, run_id: str):
        started = self.wait_started_at.get(run_id)
        if started is None:
            return None
        if time.time() - started > self.wait_timeout_s:
            return "deadlock_risk:wait_timeout"
        return None

У production mark_wait_start(...) зазвичай викликають під час переходу в waiting, а check_wait(...) — у scheduler або heartbeat loop, щоб вчасно завершити завислий run.

Де це реалізується в архітектурі

Deadlock-контроль у production зазвичай розкладений між кількома шарами.

Agent Runtime керує життєвим циклом run: таймаути, stop reasons, примусове завершення завислих станів і fallback-переходи. Саме тут зазвичай ставлять правила deadlock_risk:*.

Orchestration Topologies визначає, хто володіє state transitions і як агенти взаємодіють без циклічних очікувань. Якщо в топології немає чіткого owner-а стану, deadlock стає питанням часу.

Tool Execution Layer закриває технічну частину: lease/TTL для shared resources, єдина retry policy і контроль очікувань на рівні інструментів.

Самоперевірка

Швидка перевірка перед релізом. Відмічайте пункти і дивіться статус нижче.
Це короткий sanity-check, а не формальний аудит.

Прогрес: 0/9

⚠ Є сигнали ризику

Бракує базових контролів. Закрийте ключові пункти цього чекліста перед релізом.

FAQ

Q: Deadlocks бувають тільки у великих multi-agent системах?
A: Ні. Навіть 2-3 агенти можуть створити цикл очікувань, якщо немає явного owner-а стану.

Q: Чи достатньо просто додати таймаути?
A: Таймаути обмежують зависання, але не прибирають корінь проблеми. Потрібні ще оркестратор і чіткі state transitions.

Q: Leases повністю вирішують deadlock?
A: Ні. Leases закривають lock-проблеми після крешів, але не виправляють логічні цикли між агентами.

Q: Що робити, якщо run уже завис у waiting?
A: Примусово завершити run зі stop reason, звільнити lease, переключити workflow у fallback і розібрати ланцюг очікувань у трейсах.


Deadlock майже ніколи не виглядає як гучна аварія. Частіше це тиха зупинка прогресу, яка забирає воркери і бюджет. Тому production multi-agent системам потрібен не лише розподіл ролей, а й жорстка orchestration-дисципліна.

Пов'язані сторінки

Щоб глибше закрити цю проблему, подивись:

  • Чому AI агенти ламаються — загальна карта збоїв у production.
  • Multi-agent chaos — як неконтрольована взаємодія агентів руйнує стабільність.
  • Partial outage — як часткова деградація залежностей провокує waiting-стани.
  • Agent Runtime — де керувати stop reasons, timeout і lifecycle run'ів.
  • Orchestration Topologies — як проектувати керовану координацію між агентами.
⏱️ 5 хв читанняОновлено 12 березня 2026 р.Складність: ★★☆
Реалізувати в OnceOnly
Guardrails for loops, retries, and spend escalation.
Використати в OnceOnly
# onceonly guardrails (concept)
version: 1
budgets:
  max_steps: 25
  max_tool_calls: 12
  max_seconds: 60
  max_usd: 1.00
policy:
  tool_allowlist:
    - search.read
    - http.get
controls:
  loop_detection:
    enabled: true
    dedupe_by: [tool, args_hash]
  retries:
    max: 2
    backoff_ms: [200, 800]
stop_reasons:
  enabled: true
logging:
  tool_calls: { enabled: true, store_args: false, store_args_hash: true }
Інтегровано: продакшен-контрольOnceOnly
Додай guardrails до агентів з tool-calling
Зашип цей патерн з governance:
  • Бюджетами (кроки / ліміти витрат)
  • Kill switch та аварійна зупинка
  • Audit logs та трасування
  • Ідемпотентність і dedupe
  • Дозволами на інструменти (allowlist / blocklist)
Інтегрована згадка: OnceOnly — контрольний шар для продакшен агент-систем.
Приклад policy (концепт)
# Example (Python — conceptual)
policy = {
  "budgets": {"steps": 20, "seconds": 60, "usd": 1.0},
  "controls": {"kill_switch": True, "audit": True},
}

Автор

Микола — інженер, який будує інфраструктуру для продакшн AI-агентів.

Фокус: патерни агентів, режими відмов, контроль рантайму та надійність систем.

🔗 GitHub: https://github.com/mykolademyanov


Редакційна примітка

Ця документація підготовлена з допомогою AI, із людською редакторською відповідальністю за точність, ясність і продакшн-релевантність.

Контент базується на реальних відмовах, постмортемах та операційних інцидентах у розгорнутих AI-агентних системах.