Step Limits для AI-агентів: як зупиняти цикли до інциденту

Step limits у production: як зупиняти цикли, повертати stop reasons і не втрачати контроль над run.
На цій сторінці
  1. Ідея за 30 секунд
  2. Проблема
  3. Рішення
  4. Step limits ≠ budget controls
  5. Метрики step-контролю
  6. Як це виглядає в архітектурі
  7. Приклад
  8. У коді це виглядає так
  9. Як це виглядає під час виконання
  10. Сценарій 1: досягнуто max_steps
  11. Сценарій 2: виявлено loop
  12. Сценарій 3: нормальне виконання
  13. Типові помилки
  14. Самоперевірка
  15. FAQ
  16. Де Step Limits у загальній системі
  17. Пов'язані сторінки

Ідея за 30 секунд

Step limits — це runtime-контроль, який примусово зупиняє run, коли агент зациклюється або не дає прогресу.

Коли це потрібно: коли агент працює в loop, взаємодіє з інструментами і може повторювати одні й ті самі дії в production.

Проблема

Без step limits агент часто "щось робить", але не рухається до результату. На демо це виглядає нормально. У production таке швидко перетворюється на витрати, затримки і шум у логах.

Типовий патерн:

  • одна нестабільна відповідь tool
  • повтор тієї самої дії
  • ще один повтор
  • і так по колу

Аналогія: це як навігатор, який зациклив маршрут на одному перехресті. Машина рухається, але до цілі не наближається.

Щоб це не стало інцидентом, обмеження мають стояти в runtime loop, а не в UI чи промпті.

Рішення

Рішення — винести контроль кроків у policy layer на runtime-рівні. Кожен крок перевіряється після формування наступної дії, але перед її виконанням.

Policy layer повертає одне з рішень:

  • allow
  • stop (reason=max_steps)
  • stop (reason=loop_detected)
  • stop (reason=no_progress)

Це окремий рівень системи, а не частина промпта чи логіки моделі.

Step limits ≠ budget controls

Це різні рівні контролю:

  • Step limits контролюють поведінку циклу (скільки і як агент робить кроки)
  • Budget controls контролюють ресурси run (час, гроші, кількість дій)

Одне без іншого не працює:

  • без step limits цикл може довго крутитися без прогресу
  • без budget controls навіть "обмежений" цикл може бути дорогим

Приклад:

  • step limits: max_steps=18, max_repeat_action=3
  • budget controls: max_seconds=45, max_usd=1.00

Метрики step-контролю

Ці перевірки працюють разом на кожному кроці агента.

МетрикаЩо контролюєКлючові механікиНавіщо
Step capМаксимальну довжину runmax_steps
лічильник кроків у runtime
Зупиняє нескінченний цикл до росту витрат
Repeat-action controlПовтор однієї й тієї ж діїmax_repeat_action
ключ tool + args
Ловить loop, коли агент повторює той самий виклик
No-progress controlСитуації без реального прогресуno_progress_window
перевірка змін у стані
Зупиняє run, якщо кроки є, а прогресу немає
Stop reason surfacingПрозорість причини зупинкиявний stop reason
partial response
Користувач і команда бачать, чому run зупинено

Як це виглядає в архітектурі

Step policy layer стоїть у runtime loop між плануванням і виконанням дії. Кожне рішення (allow або stop) фіксується в audit log.

Кожен крок агента проходить через цей flow перед виконанням: runtime не виконує наступну дію напряму, а спочатку проходить step-перевірку.

Коротко по flow:

  • Runtime формує наступну дію
  • Step policy layer перевіряє max_steps, повтори і прогрес
  • allow -> виконується наступна дія агента
  • stop -> повертається stop reason + partial response
  • обидва рішення пишуться в audit log

Приклад

Агент підтримки багато разів викликає search.docs через нестабільну зовнішню відповідь.

Зі step limits:

  • max_steps = 18
  • max_repeat_action = 3
  • no_progress_window = 4

-> run зупиняється з явним stop reason, а не продовжує цикл без кінця.

Step limits зупиняють інцидент на рівні runtime loop, а не покладаються на поведінку моделі.

У коді це виглядає так

У спрощеній схемі вище показано основний control flow. На практиці step-перевірка виконується централізовано перед кожною дією.

Приклад step-конфігурації:

YAML
step_limits:
  max_steps: 18
  max_repeat_action: 3
  no_progress_window: 4
PYTHON
while True:
    # Тут крок рахується як намір дії, а не як вже виконана дія.
    state = state.with_step_increment()
    action = planner.next(state)  # planner формує дію для цього кроку
    repeat_key = make_repeat_key(action.name, action.args)  # нормалізований ключ tool+args

    decision = step_policy.check(state, action, repeat_key=repeat_key)
    if decision.outcome == "stop":
        audit.log(
            run_id,
            decision.outcome,
            reason=decision.reason,
            step=state.steps,
            action=action.name,
            repeat_key=repeat_key,
        )
        return stop(decision.reason)

    result = tool.execute(action.args)
    state = state.apply(action, result)

    decision = Decision.allow(reason="step_ok")
    audit.log(
        run_id,
        decision.outcome,
        reason=decision.reason,
        step=state.steps,
        action=action.name,
        repeat_key=repeat_key,
        result=result.status,
    )

    if result.final:
        return result

Step policy зазвичай перевіряє три сигнали: ліміт кроків, повтори дій і відсутність прогресу. Для loop detection використовується ключ tool+args, а не тільки action.name.

Як це виглядає під час виконання

Сценарій 1: досягнуто max_steps

  1. Runtime формує крок 19 і оновлює лічильник кроків.
  2. Policy бачить перевищення max_steps.
  3. Рішення: stop (reason=max_steps).
  4. В audit log пишеться причина зупинки.
  5. Користувач отримує partial response.

Сценарій 2: виявлено loop

  1. Runtime кілька разів підряд формує search.docs з тими самими args.
  2. Policy рахує повтори tool+args.
  3. Рішення: stop (reason=loop_detected).
  4. Run зупиняється до наступного зайвого виклику.
  5. У логах видно точну причину і дію.

Сценарій 3: нормальне виконання

  1. Runtime формує новий крок.
  2. Policy перевіряє ліміти: все в межах.
  3. Рішення: allow.
  4. Виконується наступна дія агента.
  5. Результат і рішення фіксуються в audit log.

Типові помилки

  • ставити max_steps тільки в UI, а не в runtime loop
  • не повертати явний stop reason у відповідь
  • рахувати лише виклики інструментів і ігнорувати кроки
  • не перевіряти повтори (tool + args) і no-progress
  • логувати тільки success-кроки без stop-рішень
  • ставити занадто високий max_steps "про всяк випадок"

У результаті run виглядає активним, але цикл росте швидше, ніж команда встигає це побачити.

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

Швидка перевірка step limits перед запуском у production:

Прогрес: 0/8

⚠ Бракує базового governance-контролю

Перед production потрібні мінімум: контроль доступу, ліміти, audit logs і аварійна зупинка.

FAQ

Q: Який стартовий max_steps ставити?
A: Для більшості синхронних run-ів почни з 15-25. Далі дивись на частоту stop-подій і коригуй за реальними сценаріями.

Q: Чи достатньо тільки max_steps?
A: Ні. Мінімум додай max_repeat_action і no-progress контроль. Для production також потрібні бюджети (max_seconds, max_usd, max_tool_calls).

Q: Що важливіше: repeat detection чи no-progress?
A: Потрібні обидва. Repeat detection ловить явні повтори, no-progress ловить "м'які" цикли, де дії різні, але прогресу немає.

Q: Що показувати користувачу при зупинці?
A: Partial response + явний stop reason + коротку дію далі (переформулювати запит або запустити повтор з іншим scope).

Q: Step limits замінюють kill switch?
A: Ні. Step limits керують кожним run, а kill switch потрібен для аварійного глобального зупинення.

Де Step Limits у загальній системі

Step limits — це один із рівнів Agent Governance. Разом із RBAC, бюджетами, approval і audit вони формують єдину систему контролю виконання.

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

Далі за темою:

⏱️ 6 хв читанняОновлено 26 березня 2026 р.Складність: ★★★
Реалізувати в OnceOnly
Budgets + permissions you can enforce at the boundary.
Використати в 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
writes:
  require_approval: true
  idempotency: true
controls:
  kill_switch: { enabled: true }
Інтегровано: продакшен-контрольOnceOnly
Додай guardrails до агентів з tool-calling
Зашип цей патерн з governance:
  • Бюджетами (кроки / ліміти витрат)
  • Дозволами на інструменти (allowlist / blocklist)
  • Kill switch та аварійна зупинка
  • Ідемпотентність і dedupe
  • Audit logs та трасування
Інтегрована згадка: OnceOnly — контрольний шар для продакшен агент-систем.

Автор

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

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

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


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

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

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