Allowlist vs Blocklist для AI-агентів: чому default deny безпечніший

Практичний підхід до доступу інструментів у production: default deny allowlist, incident blocklist, stop reasons і audit logs.
На цій сторінці
  1. Ідея за 30 секунд
  2. Проблема
  3. Рішення
  4. Allowlist ≠ Blocklist
  5. Метрики контролю доступу для інструментів
  6. Як це виглядає в архітектурі
  7. Приклад
  8. У коді це виглядає так
  9. Як це виглядає під час виконання
  10. Типові помилки
  11. Самоперевірка
  12. FAQ
  13. Де це у загальній системі
  14. Пов'язані сторінки

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

Allowlist у runtime визначає, які інструменти агенту дозволено викликати. Blocklist лише забороняє частину інструментів із уже великого набору.

Коли це потрібно: коли агент має доступ до реальних API, write-дій або регулярно отримує нові tools у production.

Проблема

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

Причина проста: кожен новий tool автоматично стає доступним, якщо його явно не заблокувати. Тобто доступ росте за замовчуванням, а не через явне рішення.

Аналогія: це як офіс без списку дозволених дверей, але зі списком "не заходити сюди". Щойно з'являється нова кімната, вона відкрита для всіх, поки хтось не згадає її заборонити.

Рішення

Рішення — поставити в policy layer правило default deny і дозволяти інструменти тільки через allowlist. Blocklist лишити як додаткове аварійне гальмо для incident mode, а не як основну модель доступу.

Policy layer повертає технічне рішення для кожного виклику: allow, deny або approval_required. Це рішення приймається на кожному кроці, а не лише в кінці run. Це окремий рівень системи, а не частина промпта чи логіки моделі.

Allowlist ≠ Blocklist

Це різні підходи до контролю:

  • Allowlist: дозволено тільки те, що явно внесено в політику.
  • Blocklist: дозволено все, окрім того, що явно заборонено.

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

  • без allowlist доступи між релізами розширюються майже непомітно
  • без blocklist складніше аварійно відключити конкретний tool під час інциденту

Приклад:

  • allowlist: search.read, kb.read, refund.lookup
  • incident blocklist: тимчасово заборонити browser.run через нестабільний vendor

Метрики контролю доступу для інструментів

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

МетрикаЩо контролюєКлючові механікиНавіщо
Default denyБазове правило доступуdefault = deny
deny by default
Новий tool не стає доступним автоматично
AllowlistЯкі tools дозволеніexplicit tool names
capability scoping
Дає явні межі для runtime-виконання
Incident blocklistТимчасові аварійні блокуванняincident mode deny list
time-bound rules
Дозволяє швидко зменшити ризик без релізу
Write escalationРизикові write-діїapproval_required
separate write policy
Не дає виконувати незворотні дії без контролю
Policy observabilityВидимість policy-рішеньaudit logs
alerts on deny spikes
Не обмежує дії напряму, але показує, де і чому доступ блокується

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

Policy layer (tool gateway) стоїть між runtime і tools та є єдиною точкою контролю доступу перед кожним кроком. Кожне рішення (allow, deny, approval_required) фіксується в audit log.

Кожен крок агента проходить через цей flow перед виконанням: runtime не виконує дію напряму — спочатку policy-перевірка, потім виконання. Для write-дій policy може повернути approval_required — це окремий flow підтвердження, який не показаний на цій діаграмі (див. Human approval).

Коротко по флоу:

  • Runtime формує tool call
  • Policy layer застосовує default deny, потім allowlist і incident blocklist
  • allow -> виклик інструмента виконується
  • deny -> повертається stop reason
  • кожне рішення пишеться в audit log

У runtime deny перетворюється на явний stop reason, який видно в логах і відповіді run.

Приклад

Агент підтримки отримує запит на масове закриття тікетів. Tool ticket.close_bulk не входить у allowlist, тому виклик одразу блокується.

Під час окремого інциденту команда додає browser.run у incident blocklist. Навіть якщо цей tool є в allowlist, policy layer тимчасово повертає deny("incident_deny").

Allowlist обмежує базовий доступ, а blocklist дає швидкий аварійний контроль.

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

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

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

YAML
policy:
  default: deny
  allowlist:
    - search.read
    - kb.read
    - refund.lookup
incident_blocklist:
  - browser.run
PYTHON
decision = policy.evaluate(tool, user_context, mode="normal")

if decision.outcome == "approval_required":
    if not approval.ok():
        audit.log(run_id, decision.outcome, reason=decision.reason, tool=tool)
        return stop(decision.reason)
    else:
        audit.log(run_id, "approval_granted", reason="human_approved", tool=tool)

elif decision.outcome == "deny":
    audit.log(run_id, decision.outcome, reason=decision.reason, tool=tool)
    alerts.notify_if_needed(run_id, decision.reason, tool=tool)
    return deny(decision.reason)

result = tool.execute(args)
decision = Decision.allow(reason="policy_ok")
audit.log(run_id, decision.outcome, reason=decision.reason, tool=tool, result=result.status)
return result

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

TEXT
Сценарій 1: tool не в allowlist (deny)

1. Runtime формує виклик ticket.close_bulk.
2. Policy layer перевіряє allowlist.
3. Рішення: deny (tool_not_allowed).
4. Audit: decision=deny, tool=ticket.close_bulk, reason=tool_not_allowed.
5. Дія не виконується.

---

Сценарій 2: інцидентний блок (incident_deny)

1. Runtime формує виклик browser.run.
2. Tool є в allowlist, але активний incident mode.
3. Policy layer перевіряє blocklist і повертає deny (incident_deny).
4. Audit: decision=deny, tool=browser.run, reason=incident_deny.
5. Run зупиняється без виклику інструмента.

---

Сценарій 3: дозволений виклик (allow)

1. Runtime формує виклик kb.read.
2. Policy layer перевіряє правила: allow.
3. Інструмент виконується.
4. Audit: decision=allow, tool=kb.read, result=ok.
5. Результат повертається в runtime.

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

  • робити blocklist основною моделлю доступу
  • не використовувати default deny для нових tools
  • дозволяти wildcard типу * без вузьких меж
  • тримати "універсальні" tools на кшталт workflow.run_anything
  • логувати тільки allow, але не логувати deny/approval_required
  • перевіряти доступ у промпті або UI, а не в policy layer

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

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

Швидка перевірка allowlist-policy перед запуском у production:

Прогрес: 0/8

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

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

FAQ

Q: Чи можна жити тільки з blocklist?
A: Для production — ні. Blocklist корисний як аварійний механізм, але базова модель має бути default deny + allowlist.

Q: З чого почати allowlist?
A: Почни з мінімального read-only набору tools. Write-дії додавай окремо, з явними умовами і approval.

Q: Wildcard allowlist (crm.*) — це нормально?
A: Лише у вузьких випадках і з регулярним рев’ю. Інакше wildcard швидко перетворюється на прихований default-allow. Наприклад, crm.* дозволить crm.delete_all_contacts, якщо такий tool з'явиться в наступному релізі.

Q: Де краще реалізувати ці перевірки?
A: У централізованому policy layer (tool gateway), а не в промпті і не в UI-логіці.

Q: Що робити, якщо tool треба терміново вимкнути?
A: Додай його в incident blocklist, зафіксуй причину в audit log, а потім повернись до постійної allowlist-політики.

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

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

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

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

⏱️ 6 хв читанняОновлено 25 березня 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-агентних системах.