Чому вашому ШІ-агенту потрібен комплаєнс-шар
У лютому 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 часу розробки. Інцидент коштував у чотирнадцять разів дорожче, без урахування втраченої довіри.
Чек-лист, який можна скопіювати
Проганяйте список по поточному агенту цього тижня. Позначайте рядки або заводьте задачі.
- Створіть agent_audit з одинадцятьма колонками вище й обома індексами.
- Дайте кожній сесії стабільний session_id з першого повідомлення.
- Логуйте кожен виклик інструмента. Тихих викликів бути не повинно.
- Зберігайте args_hash і відредаговані аргументи. Сирий текст клієнтів у журнал не входить.
- Проставте delete_after у кожному рядку. Тримайте тридцять днів за замовчуванням.
- Плануйте нічну задачу видалення. Сигналізуйте про пропущений запуск.
- Додайте regex-прохід очищення з тестом із двохсот прикладів.
- Додайте модельний прохід для імен і адрес.
- Тримайте оригінали у сховищі з TTL сім днів за break-glass доступом.
- Дозволяйте вихідні надсилання лише за рядком схвалення.
- Тренуйтеся щомісяця: беріть випадкову сесію і відповідайте на три запитання аудиту швидше десяти хвилин.
- Ведіть нотатку про зберігання на одну сторінку: що зберігається, де лежить, скільки живе, хто схвалює зміни.
Я ганяю цю перевірку в перший понеділок кожного місяця. Вона займає двадцять хвилин. Вона врятувала б мій запуск лютого 2024 року.
Що я виміряв
Шар відповідності видно в логах, які він пише. Що змінилось там:
| Метрика | До | Після | Джерело |
|---|---|---|---|
| Виклики інструментів у логах | 0% | 100% | log sampler |