Перейти до вмісту
← Назад до блогу

Чому вашому ШІ-агенту потрібен комплаєнс-шар

У лютому 2024 року я підключив ШІ-агента до пошти відділу бронювання одного клієнта. Демо пройшло чудово. Агент читав нові заявки, перевіряв календар, створював бронювання і надсилав підтвердження через SMS. За три тижні після запуску аудитор клієнта надіслав шість запитань про дані клієнтів. На п'ять я відповів. Шосте вимагало доказів: які записи агент відкривав, хто схвалив кожне вихідне повідомлення і коли видаляються листи з номерами телефонів. Чіткої відповіді я не мав. Запуск зупинився на три тижні, поки я перебудовував шар даних. Цей шар отримує своє місце в порядку випуску, який я веду від першої збірки до щоденного навантаження, у пості Розробка ШІ-агентів: від прототипу до продакшену.

Аудит, який я одного разу провалив

Клієнт тримав сервісну компанію на шістдесят працівників і приймав близько чотирьохсот заявок на бронювання щотижня. Агент розбирав пошту чотирма інструментами: read_inbox, check_calendar, create_booking і send_sms. Я писав запити й сирі виводи інструментів в одну таблицю Postgres під назвою agent_logs у вигляді сирого тексту. Половина рядків лишилася без session id. Крипто-бриф піднімає ті самі питання про записи, і я розбираю аудит-трейл у пості Дизайн для Web3: де довіра зустрічається з регуляцією. Номери телефонів та адреси пошти лежали відкритим текстом. Команда зберігала все підряд для можливого навчання моделі.

Перед партнерською угодою прийшов зовнішній аудитор і поставив три запитання. Перше: перелічити кожен запис клієнта, який агент відкрив 12 березня. Друге: показати, хто схвалив сорок SMS, надісланих агентом за тиждень. Третє: назвати дату видалення листів з номерами телефонів.

Мої відповіді виглядали слабо. Читання за 12 березня я відновив за мітками часу, робота зайняла два дні. В SMS не було поля схвалення, агент надсилав їх за власним рішенням. Дати видалення не існувало, я її ніде не задав. Угода зсунулася на місяць. Наступні два тижні я скриптом видаляв дванадцять тисяч сирих листів і писав нотатку про зберігання на одну сторінку. Клієнт лишив мене в проєкті.

Аудитори просять записи. Наміри їх не переконують. Кожен агент тепер отримує невеликий комплаєнс-шар з першого дня, до дотику до клієнтських даних. У шарі три частини. Я тримаю шар коротким, щоб людина прочитала, до чого торкнулася модель, перш ніж їй повірять: розбір нагляду у пості Glass-box AI: показую впевненість моделі щоб люди довіряли.

Шар із трьох частин: журнал викликів, строк зберігання, очищення PII

Журнал викликів інструментів

Кожен виклик інструмента потрапляє в таблицю Postgres під назвою agent_audit. Колонки: id uuid, created_at timestamptz, tenant_id text, session_id text, actor text, tool_name text, args_hash text, args_redacted jsonb, result_code text, policy_decision text, delete_after date. Я зберігаю SHA-256 хеш повних аргументів і відредаговану копію із заміною персональних даних мітками. Сирий текст клієнтів у таблицю не потрапляє. Навантаження несуть два індекси: за tenant_id з created_at і за session_id.

Actor приймає три значення: user, agent, approver. Кожне вихідне повідомлення вимагає рядка з actor approver або policy_decision auto_approved з номером правила. Інструмент надсилання відмовляється працювати без такого рядка. Коли аудитор питає, яких записів торкнувся агент, відповідає один запит: фільтр agent_audit за session_id і сортування за created_at.

Фіксований строк зберігання

Кожен рядок несе delete_after, значення за замовчуванням дорівнює created_at плюс тридцять днів. Задача pg_cron стартує щоночі о 03:00 і видаляє прострочені рядки. Конфіг клієнта скорочує вікно до семи днів для чутливих листів або подовжує бронювання до дев'яноста днів з письмовою поміткою власника даних. Значення за замовчуванням лишається тридцять днів. Видалення обліковується лічильниками за клієнтами: скільки рядків видалено, який найстаріший рядок лишився. На запитання аудиту про строки я показую рядок конфіга й лічильники за минулий місяць.

Конвеєр очищення PII

Два проходи йдуть до запису на диск. Перший прохід шукає регулярними виразами адреси пошти, номери телефонів, номери карток, IBAN і шаблони національних ID країн, де я працюю. Другий прохід проганяє текст через невелику мовну модель, яка мітить імена, адреси вулиць і дати народження у вільному тексті, включно з одруківками повз регулярки. Очищений текст іде в журнали й пам'ять агента. Оригінали йдуть у шифроване сховище з TTL сім днів за break-glass доступом, кожне читання пише власний рядок аудиту.

Перед кожним релізом я перевіряю конвеєр фіксованим набором із двохсот прикладів. Клас regex зобов'язаний показати нуль пропусків. Клас моделі зобов'язаний показати залоговану оцінку якості для порівняння з минулим релізом. Новий шаблон PII з продакшену стає новим тестом того самого дня.

Скільки коштує шар і скільки коштує витік

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

Порівняйте з рахунком, який заплатила сервісна фірма на сорок людей після інциденту слабшого за витік: близько $35,000 за юридичну перевірку, сповіщення клієнтів і три тижні переробок. Працівники тихо повернулися до ручного введення, довіра до інструмента впала. Шар коштує близько $2,500 часу розробки. Інцидент коштував у чотирнадцять разів дорожче, без урахування втраченої довіри.

Чек-лист, який можна скопіювати

Проганяйте список по поточному агенту цього тижня. Позначайте рядки або заводьте задачі.

  1. Створіть agent_audit з одинадцятьма колонками вище й обома індексами.
  2. Дайте кожній сесії стабільний session_id з першого повідомлення.
  3. Логуйте кожен виклик інструмента. Тихих викликів бути не повинно.
  4. Зберігайте args_hash і відредаговані аргументи. Сирий текст клієнтів у журнал не входить.
  5. Проставте delete_after у кожному рядку. Тримайте тридцять днів за замовчуванням.
  6. Плануйте нічну задачу видалення. Сигналізуйте про пропущений запуск.
  7. Додайте regex-прохід очищення з тестом із двохсот прикладів.
  8. Додайте модельний прохід для імен і адрес.
  9. Тримайте оригінали у сховищі з TTL сім днів за break-glass доступом.
  10. Дозволяйте вихідні надсилання лише за рядком схвалення.
  11. Тренуйтеся щомісяця: беріть випадкову сесію і відповідайте на три запитання аудиту швидше десяти хвилин.
  12. Ведіть нотатку про зберігання на одну сторінку: що зберігається, де лежить, скільки живе, хто схвалює зміни.

Я ганяю цю перевірку в перший понеділок кожного місяця. Вона займає двадцять хвилин. Вона врятувала б мій запуск лютого 2024 року.

Що я виміряв

Шар відповідності видно в логах, які він пише. Що змінилось там:

МетрикаДоПісляДжерело
Виклики інструментів у логах0%100%log sampler
Проєкт: Дашборд комплаєнсу для ШІ-команд

Прочитали? До справи

Ці методи я застосовую на платних проєктах. Подивіться, у скільки це обходиться.