Ідея за 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 = denydeny by default | Новий tool не стає доступним автоматично |
| Allowlist | Які tools дозволені | explicit tool names capability scoping | Дає явні межі для runtime-виконання |
| Incident blocklist | Тимчасові аварійні блокування | incident mode deny list time-bound rules | Дозволяє швидко зменшити ризик без релізу |
| Write escalation | Ризикові write-дії | approval_requiredseparate 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-конфігурації:
policy:
default: deny
allowlist:
- search.read
- kb.read
- refund.lookup
incident_blocklist:
- browser.run
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
Як це виглядає під час виконання
Сценарій 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 він формує єдину систему контролю виконання.
Пов'язані сторінки
Далі за темою:
- Огляд Agent Governance — загальна модель контролю агентів у production.
- Контроль доступу (RBAC) — як поєднувати ролі, permissions і tenant scope.
- Контроль бюджетів — як обмежувати витрати run на рівні runtime.
- Human approval — як додати підтвердження для ризикових дій.
- Audit logs для агентів — як розбирати policy-рішення в інцидентах.