Mocking інструментів і fault injection для AI-агентів

Як мокати інструменти і симулювати збої для перевірки поведінки агента при помилках API.
На цій сторінці
  1. Ідея за 30 секунд
  2. Проблема
  3. Коли використовувати
  4. Реалізація
  5. Як це працює в одному тесті
  6. 1. Зафіксуйте контракт mock-інструмента
  7. 2. Інжектуйте збій керовано
  8. 3. Перевіряйте retry і fallback
  9. 4. Фіксуйте структуру помилки
  10. 5. Запускайте такі тести в CI
  11. Типові помилки
  12. Mock не відповідає реальному контракту
  13. Перевірка тільки happy-path
  14. Випадкова fault injection
  15. Немає перевірки stop_reason і error shape
  16. Немає перевірки побічних ефектів при retry
  17. Змішування unit і інтеграційних перевірок
  18. Коротко
  19. FAQ
  20. Що далі

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

Mocking інструментів і fault injection дозволяють керовано відтворювати помилки API і перевіряти, як агент їх обробляє, без реальної мережі і без недетермінованого шуму.

Головна цінність у тому, що ви керовано відтворюєте timeout, 5xx або зламану відповідь і перевіряєте retry, fallback та stop reason.

Проблема

Без mocks і fault injection команда зазвичай бачить лише happy-path:

  • інструмент відповідає швидко;
  • відповідь валідна;
  • агент завершує run без помилок.

У production так буває рідко. Інструменти можуть повертати timeout, часткові збої, порожні поля або нестабільну latency.

Без окремих тестів на помилки це зазвичай призводить до:

  • непередбачуваних падінь у критичних сценаріях;
  • нескінченних повторів викликів;
  • дорогих і шумних інцидентів, які складно відтворити.

Коли використовувати

Цей підхід потрібен, якщо агент працює через зовнішні інструменти:

  • API платежів, CRM, пошук, бекенд-сервіси;
  • інструменти з retry/backoff;
  • сценарії, де важливий правильний stop_reason;
  • сценарії з fallback (наприклад, резервний інструмент або безпечна відповідь).

Якщо збій інструмента можна змоделювати локально, це хороший кандидат для тесту з fault injection.

Реалізація

На практиці це тримається на простому правилі: один тип збою - один тест - контрольовані умови. Приклади нижче схематичні і не прив'язані до конкретного фреймворку.

Як це працює в одному тесті

Як працюють mocks і fault injection
🧰 Тест на збої
🗒️
Тестовий кейсодна поведінка інструмента для перевірки
🧪
Мок інструментафіксований контракт входу/виходу
⚠️
Інжекція збоюtimeout, 5xx, невалідна відповідь
▶️
Запуск крокузапуск логіки агента у фіксованих умовах
Перевіркиfallback, retry, stop reason, структура помилки
Успіхповедінка передбачувана
🔁
Збійвиправити обробку і прогнати знову
Що це перевіряє
🛠️ обробку помилок інструментів і відновлення
🚫 а не повну end-to-end якість відповіді
Короткий цикл тесту з fault injection
  • Test case — одна поведінка для перевірки.
  • Mock tool — фіксуємо контракт input/output.
  • Inject fault — підставляємо конкретний збій (timeout, 5xx, bad_payload).
  • Run — запускаємо конкретний крок агента.
  • Assertions — перевіряємо retry, fallback, stop_reason і формат помилки.

1. Зафіксуйте контракт mock-інструмента

PYTHON
class FakePaymentsAPI:
    def __init__(self, mode: str = "ok"):
        self.mode = mode

    def refund(self, order_id: str):
        if self.mode == "ok":
            return {"status": "approved", "order_id": order_id}
        if self.mode == "timeout":
            raise TimeoutError("payments_timeout")
        if self.mode == "http_500":
            raise RuntimeError("payments_500")
        return {"status": None}

Mock має відтворювати реальний контракт інструмента максимально точно, інакше тести створюють хибне відчуття безпеки.

2. Інжектуйте збій керовано

PYTHON
def test_timeout_fault_is_injected():
    payments = FakePaymentsAPI(mode="timeout")
    agent = Agent(payments_api=payments)

    result = agent.handle_refund("order-8472")

    assert result.stop_reason in {"tool_error_handled", "fallback_used"}

Збій має бути явним і повторюваним: тест повинен завжди відтворювати той самий профіль збою.

3. Перевіряйте retry і fallback

PYTHON
def test_retry_then_fallback():
    payments = FlakyPaymentsAPI(fail_times=2, then="timeout")
    backup = FakeBackupTool()
    agent = Agent(payments_api=payments, backup_tool=backup, max_retries=2)

    result = agent.handle_refund("order-9001")

    assert payments.calls == 2
    assert result.selected_tool == "backup_tool"
    assert result.stop_reason == "fallback_used"

Важливо перевіряти не лише факт помилки, а й політику відновлення після неї.

Для retry важливо перевіряти не лише кількість спроб, а й умови, за яких система припиняє повтори і переходить до fallback або fail.

Для інструментів із побічними ефектами важливо перевіряти, що retry не створює дубльованих операцій.

4. Фіксуйте структуру помилки

PYTHON
def test_error_envelope_is_stable():
    payments = FakePaymentsAPI(mode="http_500")
    agent = Agent(payments_api=payments)
    result = agent.handle_refund("order-1122")

    assert result.error["code"] == "tool_error"
    assert result.error["tool"] == "payments_api"
    assert result.error["retryable"] is True

Стабільний формат помилок спрощує дебаг, алерти і regression-перевірки.

5. Запускайте такі тести в CI

Ці тести мають запускатися в кожному PR через стандартний pytest крок у CI, якщо зміни торкаються логіки інструментів, retries або fallback-правил.

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

Mock не відповідає реальному контракту

Тест проходить, але в production агент падає через іншу структуру поля або інший код помилки.

Типова причина: mock повертає спрощений payload, який не схожий на реальний API.

Перевірка тільки happy-path

У тестах є тільки "успішна відповідь", але немає timeout, 5xx і невалідних payload.

Типова причина: відсутній список обов'язкових профілів збою для кожного критичного інструмента.

Випадкова fault injection

Один і той самий тест то проходить, то падає.

Типова причина: рандомні збої без фіксованого seed або нестабільні таймаути.

Немає перевірки stop_reason і error shape

Команда перевіряє лише фінальний текст відповіді, а поведінка recovery-логіки лишається непокритою.

Типова причина: відсутні структурні assertions для stop_reason, error.code, selected_tool.

Немає перевірки побічних ефектів при retry

Повторний виклик формально обробляє помилку, але створює дубльовану операцію або повторний запис.

Типова причина: тестують тільки stop_reason і fallback, але не перевіряють ідемпотентність інструментного шару.

Змішування unit і інтеграційних перевірок

Тест називається unit, але ходить у реальний API.

Типова причина: немає межі між локальними тестами (mocks/fault injection) і інтеграційним шаром.

Коротко

Коротко
  • Mocking і fault injection перевіряють, як агент обробляє збої інструментів.
  • Один тип збою тестується окремим детермінованим тестом.
  • Перевіряйте не лише текст, а й retry, fallback, stop_reason та формат помилки.
  • Критичні fault-тести мають запускатися в кожному PR.

FAQ

Q: Чи можна тестувати збої без реального API?
A: Так. Для unit-рівня це стандартний підхід: fakes і mocks дають стабільний, відтворюваний сигнал.

Q: Що важливіше: retry чи fallback?
A: Обидва. Retry покриває короткі збої, а fallback захищає сценарій, коли основний інструмент недоступний довше.

Q: Скільки профілів збою треба мати на інструмент?
A: Мінімум три: timeout, серверна помилка (5xx) і невалідний payload.

Q: Це замінює eval harness і regression?
A: Ні. Ці тести закривають локальну поведінку інструментного шару. Поведінку системи на завершених сценаріях перевіряють eval harness і regression.

Що далі

Підключіть fault-кейси до Eval Harness і зафіксуйте їх у Golden Datasets. Для контролю змін між версіями додайте Regression Testing, а інциденти розбирайте через Replay and Debugging.

⏱️ 5 хв читанняОновлено 13 березня 2026 р.Складність: ★★☆
Інтегровано: продакшен-контрольOnceOnly
Додай guardrails до агентів з tool-calling
Зашип цей патерн з governance:
  • Бюджетами (кроки / ліміти витрат)
  • Дозволами на інструменти (allowlist / blocklist)
  • Kill switch та аварійна зупинка
  • Ідемпотентність і dedupe
  • Audit logs та трасування
Інтегрована згадка: OnceOnly — контрольний шар для продакшен агент-систем.
Автор

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

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

Патерни та рекомендації базуються на постмортемах, режимах відмов і операційних інцидентах у розгорнутих системах, зокрема під час розробки та експлуатації governance-інфраструктури для агентів у OnceOnly.