Human Approval для AI-агентів: як безпечно контролювати write-дії

Практичний approval flow у production: approval_required, TTL, stop reasons, approval token і audit trail для write-дій.
На цій сторінці
  1. Ідея за 30 секунд
  2. Проблема
  3. Рішення
  4. Human approval ≠ ручний режим
  5. Метрики approval-контролю
  6. Як це виглядає в архітектурі
  7. Приклад
  8. У коді це виглядає так
  9. Як це виглядає під час виконання
  10. Типові помилки
  11. Самоперевірка
  12. FAQ
  13. Де Human Approval у загальній системі
  14. Пов'язані сторінки

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

Human approval — це runtime-gate для ризикових write-дій: перед виконанням агент отримує approval_required і чекає підтвердження людини.

Коли це потрібно: коли агент може змінювати дані, відправляти повідомлення клієнтам або запускати незворотні дії в production.

Проблема

Без approval write-дії виконуються одразу, якщо вони дозволені policy. У demo це зручно. У production одна помилка агента перетворюється на реальний інцидент.

Проблема не тільки в "поганій" моделі. Навіть хороша модель інколи помиляється на нетипових запитах. Якщо між агентом і write-інструментом немає людського гейта, помилка одразу стає побічним ефектом у реальних системах.

Аналогія: це як платіж без 3D Secure. Поки все йде добре, затримки немає. Коли щось іде не так, наслідки стають дорогими за секунди.

Рішення

Рішення — додати в policy layer окремий approval flow для ризикових write-дій. Policy повертає одне з рішень: allow, deny або approval_required.

approval_required не виконує дію одразу: runtime створює approval request, чекає рішення людини і лише після approval_granted виконує tool call. Це рішення приймається на кожному кроці, а не лише в кінці run.

Human approval ≠ ручний режим

Це різні моделі:

  • Manual mode: людина виконує майже кожну дію замість агента.
  • Human approval: агент працює самостійно, а людина підтверджує тільки ризикові write-дії.

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

  • без approval ризикові дії проходять без додаткового контролю
  • якщо робити manual mode для всього, система втрачає швидкість і масштабованість

Приклад:

  • без approval: ticket.close_bulk виконується одразу
  • з approval: policy повертає approval_required, і дія чекає підтвердження

Метрики approval-контролю

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

МетрикаЩо контролюєКлючові механікиНавіщо
Approval scopeДля яких дій потрібне підтвердженняwrite policy
risk tiers
Зменшує ризик для незворотних дій
Approval request contextЩо саме бачить людина перед рішеннямpreview + args hash
reason + policy context
Дає змогу прийняти обґрунтоване рішення
TTL і скасуванняЖиттєвий цикл approval requestapproval TTL
cancel flow
Не дає run зависати безкінечно
Execution gateФактичний запуск write-діїapproval token
gateway enforcement
Гарантує, що write не піде без підтвердження
Approval observabilityВидимість approval-рішеньaudit logs
alerts on timeout spikes
Не обмежує дію напряму, але допомагає виявити вузькі місця approval-процесу

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

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

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

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

  • Runtime формує tool call
  • Policy layer перевіряє ризик і може повернути approval_required
  • при approval_granted write виконується
  • при approval_denied або approval_timeout run отримує stop reason
  • кожне рішення пишеться в audit log

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

Approval request зазвичай містить:

  • tool
  • короткий preview дії
  • args hash
  • reason / risk tier
  • TTL

Приклад

Агент підтримки хоче виконати email.send для клієнта. Policy визначає, що для цього tool потрібне підтвердження людини.

Результат:

  • без approval token write не виконується
  • після approval_granted виклик проходить
  • при timeout агент повертає stop("approval_timeout")

Human approval зупиняє ризикову дію до побічного ефекту, а не після інциденту.

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

У спрощеній схемі вище показано основний control flow. На практиці перевірка і виконання мають йти через один policy/tool gateway.

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

YAML
approvals:
  required_for:
    - email.send
    - ticket.close_bulk
    - db.write
  ttl_seconds: 300
  fallback_when_not_approved: stop
PYTHON
decision = policy.evaluate(tool, user_context, mode="normal")

if decision.outcome == "approval_required":
    request = approvals.create_request(
        run_id=run_id,
        tool=tool,
        args_hash=hash_args(args),
        ttl_seconds=300,
    )
    audit.log(run_id, decision.outcome, reason="pending_human_review", tool=tool, pending_id=request.id)
    return stop("approval_required", pending_id=request.id)

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

# later, in resume flow with pending_id
approval = approvals.get_decision(pending_id)
if approval.outcome != "approved":
    audit.log(run_id, "deny", reason=approval.outcome, tool=tool, pending_id=pending_id)
    return stop(approval.outcome)

audit.log(run_id, "approval_granted", reason="human_approved", tool=tool, approver=approval.approved_by)
result = tool.execute({**args, "approval_token": approval.token})
decision = Decision.allow(reason="policy_ok")
audit.log(run_id, decision.outcome, reason=decision.reason, tool=tool, result=result.status)
return result

У production approval flow зазвичай асинхронний: runtime створює request, повертає pending/stop стан без блокування worker і відновлює run після рішення людини.

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

TEXT
Сценарій 1: підтверджено (approval granted)

1. Runtime формує виклик email.send.
2. Policy повертає approval_required.
3. Runtime створює approval request і повертає pending/stop стан.
4. Людина підтверджує дію в межах TTL.
5. Runtime відновлює run, виконує tool call і пише `approval_granted -> allow`.

---

Сценарій 2: таймаут підтвердження (approval timeout)

1. Runtime формує виклик db.write.
2. Policy повертає approval_required.
3. Runtime створює approval request і повертає pending/stop стан.
4. Підтвердження не отримано до завершення TTL.
5. Runtime повертає stop (approval_timeout), дія не виконується.

---

Сценарій 3: policy deny без approval

1. Runtime формує write-виклик поза дозволеним scope.
2. Policy одразу повертає deny.
3. Runtime повертає stop reason.
4. Audit: decision=deny, reason=policy_denied.
5. Дія не виконується.

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

  • approval тільки в UI, але не в policy/tool gateway
  • approval без TTL і без скасування
  • однаковий підхід для low-risk і high-risk write-дій
  • відсутність approval token при виконанні tool
  • не логувати approval_required і approval_granted
  • блокувати всі run-и в очікуванні approval замість повернення явного stop/pending стану

У результаті система або пропускає небезпечні дії, або зависає в approval-чергах без прозорого стану.

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

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

Прогрес: 0/8

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

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

FAQ

Q: Для яких дій approval потрібен обов'язково?
A: Для незворотних або клієнтськи видимих write-дій: зміни даних, масові закриття, відправка повідомлень, фінансові операції.

Q: Як не втопити команду в approval-spam?
A: Розбий write-дії на рівні ризику. High-risk -> обов'язковий approval, low-risk -> окрема policy з tighter limits і аудитом.

Q: Чи потрібно блокувати worker, поки чекаємо approval?
A: Краще ні. Поверни pending/stop стан і віднови run після рішення, щоб не отримати черги й deadlocks.

Q: Чи може approval замінити RBAC і бюджети?
A: Ні. Approval — це додатковий gate для ризикових дій. RBAC, ліміти й бюджети все одно потрібні.

Q: Що логувати мінімально?
A: approval_required, approval_granted|approval_denied|approval_timeout, хто підтвердив, який tool, який reason і який результат виконання.

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

Human approval — це один із рівнів Agent Governance. Разом із allowlist/RBAC, бюджетами, лімітами і 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-агентних системах.