Анти-патерн No Monitoring: відсутність моніторингу

Anti-pattern, коли агентна система працює без логів і метрик.
На цій сторінці
  1. Ідея за 30 секунд
  2. Приклад анти-патерну
  3. Чому виникає і що йде не так
  4. Правильний підхід
  5. Швидкий тест
  6. Чим відрізняється від інших анти-патернів
  7. No Stop Conditions vs No Monitoring
  8. Overengineering Agents vs No Monitoring
  9. Agents Without Guardrails vs No Monitoring
  10. Самоперевірка: чи немає у вас цього анти-патерну
  11. FAQ
  12. Що далі

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

No Monitoring — це анти-патерн, коли агентна система працює майже "всліпу": без трейсів запуску, stop_reason і базових метрик.

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

Просте правило: кожен run має залишати зрозумілий слід — run_id, ключові події кроків, stop_reason і usage-метрики.


Приклад анти-патерну

Команда запускає support-агента в production, але логує лише фінальну відповідь.

Коли користувач скаржиться на помилку, команда не бачить, де саме вона виникла.

PYTHON
result = agent.run(user_message)
logger.info("answer=%s", result.text)

У такій схемі немає базового контексту run:

PYTHON
# немає run_id
# немає step trace
# немає tool status/duration
# немає stop_reason

Для цього кейсу потрібен мінімальний observability-шар:

PYTHON
run_id = create_run_id()
log_run_started(run_id, user_message)
...
log_stop(run_id, stop_reason, usage)

У цьому випадку відсутність моніторингу додає:

  • "сліпий" дебаг через припущення
  • довший час відновлення після інциденту
  • повторення тих самих збоїв

Чому виникає і що йде не так

Цей анти-патерн часто з’являється, коли команда фокусується на фічах, а моніторинг відкладає "на потім".

Типові причини:

  • логують лише фінальний output без run-level подій
  • немає єдиної схеми подій для agent/tool/stop
  • відсутні базові метрики по маршрутах (success rate, latency, cost per request)
  • немає власника за observability у команді

У результаті виникають проблеми:

  • довгий MTTR — важко швидко локалізувати корінь збою
  • повторні інциденти — фікси роблять "наосліп" без перевірки причин
  • прихована деградація — latency і вартість ростуть непомітно
  • крихка якість — команда не бачить, де саме падає success rate
  • слабка керованість — неможливо пояснити, чому run завершився саме так

На відміну від No Stop Conditions, тут головний збій у відсутності видимості: навіть якщо стоп-логіка є, команда не бачить, як вона спрацювала у конкретному запуску.

Типові production-сигнали, що моніторингу не вистачає:

  • support дізнається про проблему раніше, ніж моніторинг
  • команда не може відновити ланцюг подій по run_id
  • у логах часто немає stop_reason або його неможливо зіставити з run
  • cost per request або P95 ростуть, а команда помічає це запізно

Важливо, що кожен agent/tool крок — це частина виконання run. Без трейсів і метрик система стає чорним ящиком для команди, і причинно-наслідковий зв’язок між дією та збоєм втрачається.

Правильний підхід

Починайте з мінімального observability-базису і робіть його обов’язковим для кожного маршруту. Нові метрики додавайте тоді, коли вони закривають конкретні інциденти або сліпі зони.

Практична рамка:

  • фіксуйте run_id і step_id для кожного запуску
  • логуйте для tool-call: tool, status (ok/error), duration_ms, args_hash
  • для кожного run логуйте stop_reason і usage-метрики
  • відстежуйте ключові дашборди (наприклад, success rate, P95, cost per request) і ставте алерти на критичні відхилення
PYTHON
def run_support_agent(user_message: str):
    run_id = create_run_id()
    log_event("run_started", run_id=run_id, message=user_message)

    for step_id in range(MAX_STEPS):
        decision = agent.next_step(user_message)

        if decision.type == "tool_call":
            started = now_ms()
            try:
                result = run_tool(decision.tool, decision.args)
                log_event(
                    "tool_result",
                    run_id=run_id,
                    step_id=step_id,
                    tool=decision.tool,
                    duration_ms=now_ms() - started,
                    status="ok",
                )
            except Exception:
                log_event(
                    "tool_result",
                    run_id=run_id,
                    step_id=step_id,
                    tool=decision.tool,
                    duration_ms=now_ms() - started,
                    status="error",
                )
                raise
            continue

        if decision.type == "final_answer":
            log_event("stop", run_id=run_id, stop_reason="final_answer")
            return decision.output

    log_event("stop", run_id=run_id, stop_reason="max_steps_exceeded")
    return fallback_answer()  # safe default response or escalation

У такій схемі кожен run стає прозорим: команда бачить, що саме сталося, де з’явився збій і як перевірити фікс.

Швидкий тест

Якщо на ці питання відповідь "так", у вас є ризик анти-патерну No Monitoring:

  • Чи складно за 1-2 хвилини пояснити, чому конкретний run завершився саме так?
  • Чи support часто сигналізує про збої раніше, ніж ваші алерти?
  • Чи неможливо відтворити останній невдалий run за логами і метриками?

Чим відрізняється від інших анти-патернів

No Stop Conditions vs No Monitoring

No Stop ConditionsNo Monitoring
Основна проблема: у циклі агента немає чітких умов завершення.Основна проблема: немає видимості run/step подій, метрик і stop reasons.
Коли виникає: коли відсутні max_steps, timeout, no_progress.Коли виникає: коли запуск працює без трейсів і базових операційних метрик.

Якщо коротко: No Stop Conditions — про контроль циклу, а No Monitoring — про відсутність видимості того, що реально відбулося.

Overengineering Agents vs No Monitoring

Overengineering AgentsNo Monitoring
Основна проблема: зайві шари архітектури без вимірюваної користі.Основна проблема: немає операційної прозорості для керування складною системою.
Коли виникає: коли під прості кейси додають planner/router/policy шари "про запас".Коли виникає: коли run ідуть без трейсів, і команда не бачить, який шар реально спричинив збій.

Якщо коротко: Overengineering Agents збільшує складність системи, а No Monitoring робить цю складність невидимою і некерованою.

Agents Without Guardrails vs No Monitoring

Agents Without GuardrailsNo Monitoring
Основна проблема: агент працює без чітких policy boundaries і контрольних обмежень.Основна проблема: немає операційної прозорості для керування агентною системою.
Коли виникає: коли критичні правила безпеки й доступу не закріплені в явних runtime-перевірках.Коли виникає: коли навіть прості інциденти доводиться розслідувати без run-level даних.

Якщо коротко: Agents Without Guardrails — про відсутність контрольних меж, а No Monitoring — про відсутність видимості того, як ці межі (не) спрацювали в run.

Самоперевірка: чи немає у вас цього анти-патерну

Швидка перевірка на anti-pattern No Monitoring.
Відмічайте пункти під вашу систему і дивіться статус нижче.

Перевірте свою систему:

Прогрес: 0/8

⚠ Є ознаки цього anti-pattern

Спробуйте винести прості кроки у workflow і залишити агента лише для складних рішень.

FAQ

Q: Достатньо просто писати application logs?
A: Ні. Для агентних систем потрібен run-level моніторинг: run_id, step-події, stop_reason, tool-трейси та метрики якості/вартості.

Q: З чого почати, якщо моніторингу майже немає?
A: Почніть із мінімуму: run_id, stop_reason, tool status/duration, success rate, P95, cost per request. Це вже різко зменшує сліпі зони.

Q: Чи потрібен replay одразу?
A: Повний replay не обов’язковий на старті, але хоча б часткове відтворення run за логами має бути, інакше перевірка фіксів лишається здогадкою.


Що далі

Схожі anti-patterns:

Що будувати замість цього:

  • Stop Conditions — як фіксувати кероване завершення run.
  • Tool Execution Layer — де централізовано логувати і контролювати tool-calls.
  • Agent Runtime — як робити виконання агента прозорим на рівні кроків і рішень.
⏱️ 7 хв читанняОновлено 17 березня 2026 р.Складність: ★★★
Реалізувати в OnceOnly
Safe defaults for tool permissions + write gating.
Використати в OnceOnly
# onceonly guardrails (concept)
version: 1
tools:
  default_mode: read_only
  allowlist:
    - search.read
    - kb.read
    - http.get
writes:
  enabled: false
  require_approval: true
  idempotency: true
controls:
  kill_switch: { enabled: true, mode: disable_writes }
audit:
  enabled: true
Інтегровано: продакшен-контрольOnceOnly
Додай guardrails до агентів з tool-calling
Зашип цей патерн з governance:
  • Бюджетами (кроки / ліміти витрат)
  • Дозволами на інструменти (allowlist / blocklist)
  • Kill switch та аварійна зупинка
  • Ідемпотентність і dedupe
  • Audit logs та трасування
Інтегрована згадка: OnceOnly — контрольний шар для продакшен агент-систем.

Автор

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

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

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


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

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

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