Human-in-the-loop approvals (зупинити writes) + Код

Approvals нудні — і дешевші, ніж відкотити 200 writes. Gate для ризикових tool calls: evidence, enforce в tool gateway, audit.
На цій сторінці
  1. Проблема (з реального продакшену)
  2. Чому це ламається в продакшені
  3. 1) “Write tool” — не одна категорія
  4. 2) Без approval path ти стаєш автономним випадково
  5. 3) Approval без контексту — марний
  6. Приклад реалізації (реальний код)
  7. Реальний інцидент (з цифрами)
  8. Компроміси
  9. Коли НЕ варто
  10. Чекліст (можна копіювати)
  11. Безпечний дефолтний конфіг (JSON/YAML)
  12. FAQ (3–5)
  13. Пов’язані сторінки (3–6 лінків)
Інтерактивний флоу
Сценарій:
Крок 1/3: Execution

Action is proposed as structured data (tool + args).

Проблема (з реального продакшену)

Ти хочеш writes. Агент хоче writes. Клієнти хочуть, щоб writes були правильні.

У демо це звучить легко: “агент просто закриє тікет”. У проді “просто” — це місце, де ти потім пояснюєш, чому 200 речей зламались.

Approvals — не “enterprise фіча”. Це safety valve для системи, яка приймає рішення ймовірнісно.

Чому це ламається в продакшені

1) “Write tool” — не одна категорія

Writes бувають різні:

  • reversible vs irreversible
  • low impact vs high impact
  • idempotent vs “oops, duplicate”

Якщо ставитись однаково, отримаєш або:

  • надто багато approvals (UX помирає)
  • або надто мало (прод помирає)

2) Без approval path ти стаєш автономним випадково

Якщо write tool у allowlist і нічого його не зупиняє — він буде використаний. Не “може”. А коли це найкоротший шлях.

3) Approval без контексту — марний

“Approve цей tool call?” — недостатньо. Потрібне evidence:

  • запропонована дія
  • args (або diff)
  • чому агент думає, що це правильно
  • причина policy / ризик

Приклад реалізації (реальний код)

Мінімальний approval gate:

  • write tools створюють approval request
  • approval підтверджується id/key
  • tool gateway виконує тільки якщо approval валідний
PYTHON
from dataclasses import dataclass
from typing import Any


WRITE_TOOLS = {"ticket.close", "db.write", "email.send"}


@dataclass(frozen=True)
class Approval:
  approval_id: str
  approved: bool
  approved_by: str


class ApprovalRequired(RuntimeError):
  pass


def requires_approval(tool: str) -> bool:
  return tool in WRITE_TOOLS


def tool_gateway_call(tool: str, args: dict[str, Any], *, approval: Approval | None) -> Any:
  if requires_approval(tool):
      if not approval or not approval.approved:
          raise ApprovalRequired(f"approval_required:{tool}")
  return call_tool(tool, args)  # (pseudo)
JAVASCRIPT
const WRITE_TOOLS = new Set(["ticket.close", "db.write", "email.send"]);

export class ApprovalRequired extends Error {}

export function requiresApproval(tool) {
return WRITE_TOOLS.has(tool);
}

export function toolGatewayCall(tool, args, { approval } = {}) {
if (requiresApproval(tool)) {
  if (!approval || approval.approved !== true) throw new ApprovalRequired("approval_required:" + tool);
}
return callTool(tool, args); // (pseudo)
}

Реальний інцидент (з цифрами)

У нас був агент для “прибирання” support тікетів. Зміна prompt’а інтерпретувала “cleanup” як “close”.

Імпакт:

  • 63 тікети закрито помилково
  • ~2 години на reopen + вибачення
  • ми перевели агента в read-only на тиждень, поки не відновили довіру

Fix:

  1. approvals для high-impact writes
  2. approval UI з diff/evidence (не просто “approve?”)
  3. idempotency keys, щоб approval не виконувався двічі

Компроміси

  • Approvals додають latency. Це ціна safety.
  • Забагато approvals вбиває UX → потрібні risk tiers.
  • Approval система без audit logs залишає тебе без доказів в інциденті.

Коли НЕ варто

  • Для read-only tools approvals не потрібні.
  • Для low-risk і повністю reversible writes можна auto-approve під жорсткими budgets.
  • Якщо люди не review реально — це не approval, це театр.

Чекліст (можна копіювати)

  • [ ] Ідентифікувати write tools (capability-based)
  • [ ] Approvals для irreversible/high-impact дій
  • [ ] Evidence в UI (args diff, why, provenance)
  • [ ] Enforce в tool gateway (не тільки в UI)
  • [ ] Idempotency keys для approved actions
  • [ ] Audit logs (who approved what)

Безпечний дефолтний конфіг (JSON/YAML)

YAML
approvals:
  required_for:
    - "db.write"
    - "email.send"
    - "ticket.close"
  evidence:
    include_args: true
    include_diff: true
  enforce_in: "tool_gateway"

FAQ (3–5)

Коли approvals реально потрібні?
Коли дія дорога/незворотна або змінює клієнтські дані. Default: writes → approval.
Як уникнути approval-spam?
Risk tiers + ескалювати тільки high-risk. І тримати write tools маленькими (без ‘універсальних’ RPC).
Можна автоматизувати approvals?
Частково: auto-approve low-risk під tight budgets. Але логувати як ‘auto-approved’.
Де enforce approvals?
У tool gateway. Якщо тільки в UI — це обійдуть.

Q: Коли approvals реально потрібні?
A: Коли дія дорога/незворотна або змінює клієнтські дані. Default: writes → approval.

Q: Як уникнути approval-spam?
A: Risk tiers + ескалювати тільки high-risk. І тримати write tools маленькими (без “універсальних” RPC).

Q: Можна автоматизувати approvals?
A: Частково: auto-approve low-risk під tight budgets. Але логувати як “auto-approved”.

Q: Де enforce approvals?
A: У tool gateway. Якщо тільки в UI — це обійдуть.

Пов’язані сторінки (3–6 лінків)

Не впевнені, що це ваш кейс?

Спроєктувати агента →
⏱️ 4 хв читанняОновлено Бер, 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-агентів у продакшені.

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

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