Ідея за 30 секунд
No Stop Conditions — це анти-патерн, коли агент запускається без чітких умов завершення.
У результаті агент може крутитися в циклі й витрачати бюджет без реального прогресу. Це підвищує latency, вартість і ризик побічних ефектів (змін стану).
Просте правило: кожен запуск агента має мати явні умови зупинки для успішного завершення і для безпечного виходу.
Приклад анти-патерну
Команда робить агента підтримки, який має знайти відповідь у внутрішніх даних і повернути користувачу результат.
Але в циклі агента немає чітких stop conditions.
state = init_state(user_message)
while True:
decision = agent.next_step(state)
result = run_tool(decision.tool, decision.args)
state.append(result)
# немає has_final_answer(...)
# немає no_progress(...)
# немає перевірки repeated_action(...)
У такій схемі агент може нескінченно повторювати схожі кроки:
search_docs -> fetch_page -> summarize -> search_docs -> ...
Для цього кейсу потрібен контрольований цикл із явними межами:
for step in range(MAX_STEPS):
...
if has_final_answer(state):
return build_answer(state)
У цьому випадку відсутність stop conditions призводить до:
- ризик runaway loop (нескінченного циклу)
- зайві tool і LLM виклики
- неконтрольоване споживання часу й бюджету
Чому виникає і що йде не так
Цей анти-патерн часто з’являється, коли команда покладається на модель і очікує, що вона "сама зрозуміє", коли треба зупинитися.
Типові причини:
- немає явного
max_steps,timeoutабо budget limit - не визначено, що вважається "готовою відповіддю"
- немає перевірки
no_progressабо повторних дій - контроль зупинки лишається тільки на рівні інфраструктури
У результаті виникають проблеми:
- нескінченні або довгі цикли — агент повторює схожі кроки без завершення
- вища latency — відповідь приходить значно пізніше або не приходить зовсім
- більша вартість — росте кількість LLM/tool кроків на один запит
- побічні ефекти (зміни стану) — повторні дії можуть створити дубль запису, повторно оновити статус, дублювати API call або ще раз відправити зовнішню дію
- нестабільний результат — один і той самий запит завершується по-різному
Типові production-сигнали, що stop conditions відсутні або слабкі:
- помітна частина запусків завершується інфраструктурним timeout, а не контрольованою зупинкою
P95за кількістю кроків постійно росте- в трейсах видно повтор однакових викликів із мінімальними змінами аргументів
cost per requestросте швидше, ніжsuccess rate
Важливо, що кожен наступний крок — це частина LLM inference. Якщо в циклі немає чітких умов завершення, модель продовжує обирати "ще один крок", навіть коли нової корисної інформації майже немає.
Коли така схема розростається, без trace і візуалізації виконання стає важко пояснити, чому запуск не зупинився вчасно. Тому production-системи зазвичай мають окремий шар спостережуваності для запусків агентів.
Правильний підхід
Починайте з найпростішого контрольованого циклу, який стабільно закриває більшість запитів сьогодні. Нові умови зупинки додавайте лише тоді, коли є вимірюваний збій, ризик або обмеження поточного дизайну.
Практична рамка:
- задайте позитивну умову завершення (
final_answer_ready) - задайте захисні межі (
max_steps,timeout,budget) - додайте перевірки
no_progressі повторних дій - фіксуйте stop reason для кожного запуску й дивіться метрики (наприклад, покращення success rate без різкого росту latency і cost per request)
На практиці no_progress часто означає повтор тих самих tool-викликів, мінімальні зміни в стані або відсутність нової корисної інформації після чергового кроку.
MAX_STEPS = 8
def run_agent(user_message: str):
state = init_state(user_message)
for step in range(MAX_STEPS): # hard limit for runaway loops
if timed_out():
return stop("timeout")
if budget_exceeded():
return stop("budget_exceeded")
decision = agent.next_step(state)
if decision.type == "final_answer":
if validate_output(decision.output): # format, required fields, no empty answer
return decision.output
return stop("invalid_output")
result = run_tool(decision.tool, decision.args)
if no_progress(state, result): # same tool/result pattern or no meaningful state change
return stop("no_progress")
state.append(result)
return stop("max_steps_exceeded")
У такій схемі цикл стає керованим: система або повертає валідну відповідь, або зупиняється з прозорою причиною.
Швидкий тест
Якщо на ці питання відповідь "так", у вас є ризик no-stop-conditions:
- Чи частина запусків закінчується timeout замість контрольованого
stop_reason? - Чи один запит інколи робить непропорційно багато кроків без помітного прогресу?
- Чи в трейсах видно повтор схожих дій без нового результату?
Чим відрізняється від інших анти-патернів
No Monitoring vs No Stop Conditions
| No Monitoring | No Stop Conditions |
|---|---|
| Основна проблема: система не має достатньої спостережуваності, щоб бачити, що відбувається під час run. | Основна проблема: у циклі агента немає чітких умов завершення. |
Коли виникає: коли відсутні логи на рівні run, трейси, метрики і stop_reason. | Коли виникає: коли запуск іде без max_steps, timeout, budget limit або no_progress перевірки. |
Agents Without Guardrails vs No Stop Conditions
| Agents Without Guardrails | No Stop Conditions |
|---|---|
| Основна проблема: агент працює без policy boundaries і системних обмежень. | Основна проблема: агент може виконувати нескінченні або надто довгі цикли. |
| Коли виникає: коли немає allowlist, deny-by-default, бюджетних і safety-обмежень. | Коли виникає: коли логіка циклу не має явного критерію завершення і контрольованого stop_reason. |
Самоперевірка: чи немає у вас цього анти-патерну
Швидка перевірка на anti-pattern No Stop Conditions.
Відмічайте пункти під вашу систему і дивіться статус нижче.
Перевірте свою систему:
Прогрес: 0/8
⚠ Є ознаки цього anti-pattern
Спробуйте винести прості кроки у workflow і залишити агента лише для складних рішень.
FAQ
Q: Якщо є max_steps, цього вже достатньо?
A: Ні. max_steps потрібен, але сам по собі не закриває всі ризики. Потрібні також timeout, budget limit, перевірка прогресу і валідний критерій готової відповіді.
Q: Коли додавати нову stop condition?
A: Коли є конкретний сигнал: інциденти, повторні цикли, ріст вартості або latency, які не закриваються поточними правилами без непропорційного ускладнення системи.
Q: Як почати, якщо зараз stop conditions майже немає?
A: Почніть із мінімуму: max_steps, timeout, budget, stop_reason у логах. Потім додайте no_progress і валідацію фінальної відповіді.
Що далі
Схожі anti-patterns:
- No Monitoring — коли ви не бачите, що агент заходить у цикл або деградує.
- Too Many Tools — коли надлишок інструментів збільшує кількість зайвих кроків.
- Overengineering Agents — коли зайва складність ускладнює контроль завершення.
Що будувати замість цього:
- Stop Conditions — базова модель, як задавати умови безпечної зупинки.
- Step Limits — як задавати ліміти кроків на рівні governance.
- Budget Controls — як обмежувати витрати на запуск.
- Kill Switch — аварійне завершення, коли система виходить за межі контролю.