🤖 AI-агенты для бизнеса

25. Одобрение действий — что ещё улучшить

🔵 Идеи и пробелы, накопленные по итогам реализации human-in-the-loop approval (23-approvals.md). Не баги — направления развития. Отсортировано по ценности.


Высокий приоритет (прод-готовность)

1. Персистентность pending-одобрений

Сейчас ожидающее одобрение живёт в памяти (DashMap + oneshot). Рестарт сервера теряет висящие запросы (сам ход тоже эфемерен, но очередь /approvals и аудит могли бы переживать рестарт).

2. Аудит всех решений при кворуме

Сейчас ApprovalResolved эмитится один раз с именем последнего апрувера. При quorum: all / N теряются имена остальных одобривших.

3. Условный гейт (по аргументам)

Сейчас тул гейтится всегда. Хочется «одобрять только если сумма > N»:

approval:
  required: true
  when: "{{ input.amount }} > 10000"   # MiniJinja-условие по аргументам тула

Иначе мелкие операции заваливают оператора, и approvals «резинками» аппрувятся без смотрения.

4. Шаблон действия (action)

Текст карточки сейчас захардкожен: «Выполнить действие инструмента „X“?». Полезно дать автору тула свой, с контекстом аргументов:

approval:
  action: "Списать {{ input.amount }} ₽ со счёта {{ input.account }}"

Оператор тогда сразу видит суть, не разворачивая details.

5. Напоминание / эскалация по таймауту

Таймаут (600с) молча режет запрос на deny. Полезно:


Средний приоритет

6. VK как канал оператора

operator_notify уже умеет telegram / webhook / yandex_messenger. Не хватает vk (текстовый «да/нет» + поллер, по аналогии с Яндексом) и, при желании, email.

7. «Диал» по severity

Автоодобрение low-риска, гейт только для high (или обратный порог). Сейчас политика бинарна. Добавить min_severity: high — гейтить только >= порога.

8. Сид ролей из конфига (IaC)

Роли создаются только через API. Для деплоя «как код» удобно сидить роли из config/approval_roles.yaml при старте (upsert), а API оставить для оперативных правок (наняли/уволили).

9. Участники роли по идентичности, а не по каналу

Сейчас член роли — канальный id (ym:login, tg:id). Полезно разрешить user:<user_id> (канонический реестр пользователей) или email — тогда «нанять сотрудника» не привязано к конкретному мессенджеру.

10. Дедупликация / идемпотентность

Если агент в одном ходу повторно просит то же одобрение — сейчас создаётся второй запрос. Можно дедупить по (tool, hash(arguments)) в рамках сессии.


Низкий приоритет (UX / техдолг)

11. История решений в UI

/approvals показывает только pending. Добавить вкладку «история» (из ApprovalResolved в events.db): кто/когда/что/решение.

12. Визуал «отклонено» в виджете

Tool-карточка при остановке помечается «Остановлено», при deny — просто «Действие отклонено» текстом. Можно дать карточке явное состояние denied.

13. Отдельный бот-токен для оператора

Сейчас операторский канал делит бот-токен с end-user каналом агента (drom) — из-за этого drom-бот пришлось отключить. Правильно: оператору — свой бот (отдельный токен), чтобы каналы не конфликтовали.

14. Параметризованные запросы в approval_roles

Ролевой стор использует строковую интерполяцию с экранированием (sql_quote). При рефакторинге — перейти на параметризованные запросы DuckDB для строгости.

15. Аудит паттерна emit в других блокирующих примитивах

Баг «событие шло только подписчикам канала, но не глобальным листенерам» найден в approvals. request_user_input (вложения/oauth) использует тот же txb.send — стоит проверить, не нужно ли там тоже глобальное уведомление (событийный аудит).


Заметки о демо/продакшене