Удаляйте личные данные из журналов агентов ИИ до того, как они попадут в вашу базу данных.
Ваш агент регистрирует каждое приглашение и вызов инструмента. Один пропущенный SSN в стенограмме превращается в раскрытие GDPR. Трехстрочное промежуточное программное обеспечение исправляет это перед записью строки.
Ваш ИИ-агент записывает приглашение. Ввод вызова инструмента. Результат инструмента. Окончательный ответ. Раньше это была золотая жила отладочных данных. Сегодня это раскрытие GDPR, ожидающее обращения в службу поддержки, чтобы пройти проверку SSN.
Вы не можете запретить пользователям вставлять конфиденциальные данные. Вы можете запретить необработанному тексту поступать в ваше хранилище журналов, к поставщику средств наблюдения и к еженедельному экспорту оценок. Небольшое промежуточное программное обеспечение делает это за один переход.
Утечка, которая уже есть в большинстве установок агента
// before: every raw prompt, tool call, and tool result lands in the log row
logger.info({
event: 'agent.turn',
prompt: userInput,
tool_calls: toolCalls,
tool_results: toolResults,
});
// one support ticket later: "My SSN is 123-45-6789 and card 4111 1111 1111 1111"
// sits in the logs, the observability vendor, and the weekly eval export.
Каждая строка теперь содержит номер карты. Хранилище журналов хранит их в течение 30 дней. SDK наблюдаемости передает его третьей стороне. Экспорт eval получает ту же строку через два дня. Пять экземпляров одной карты; все они выходят за рамки вашей политики шифрования в состоянии покоя.
Обнаружение личных данных одним звонком
Ботой /v1/pii/detect Конечная точка сканирует текст на предмет электронных писем, номеров телефонов, SSN, кредитных карт (проверенных Luhn), IP-адресов и дат рождения. Он возвращает каждый результат с начальным смещением, конечным смещением и маскированным значением, которое вы можете разместить на месте.
Запрос
curl -X POST https://api.botoi.com/v1/pii/detect \\
-H "Content-Type: application/json" \\
-d '{"text": "Reach me at alice@example.com or 555-123-4567. Card: 4111 1111 1111 1111."}'
Ответ
{
"found": true,
"count": 3,
"findings": [
{ "type": "email", "value": "alice@example.com", "start": 12, "end": 29, "masked": "al***@example.com" },
{ "type": "phone", "value": "555-123-4567", "start": 33, "end": 45, "masked": "***-***-4567" },
{ "type": "credit_card", "value": "4111 1111 1111 1111", "start": 53, "end": 72, "masked": "************1111" }
]
}
Три матча, три замены в масках, позиции, которые можно аккуратно соединить. Нет библиотеки регулярных выражений, которую нужно поддерживать, нет таблицы префиксов SSN, которую нужно поддерживать в актуальном состоянии, нет прохода Луна, чтобы писать самостоятельно.
Промежуточное программное обеспечение журналов, которое редактирует перед записью
Подходящим местом для этого является последний переход перед тем, как строка покинет ваш процесс. Каждый вышестоящий компонент по-прежнему видит необходимый ему необработанный текст; сохраненная копия очищается.
// log-redact.ts
import type { LogRecord } from './types';
const PII_FIELDS = ['prompt', 'tool_calls', 'tool_results', 'output'] as const;
export async function redactPii(record: LogRecord): Promise<LogRecord> {
const clone = structuredClone(record);
for (const field of PII_FIELDS) {
const value = clone[field];
if (!value) continue;
clone[field] = await scrub(JSON.stringify(value));
}
return clone;
}
async function scrub(text: string): Promise<string> {
const res = await fetch('https://api.botoi.com/v1/pii/detect', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: \`Bearer \${process.env.BOTOI_API_KEY}\`,
},
body: JSON.stringify({ text }),
});
const data = await res.json();
if (!data.found) return text;
// Replace from the end of the string so offsets stay valid.
const sorted = [...data.findings].sort((a, b) => b.start - a.start);
let scrubbed = text;
for (const f of sorted) {
scrubbed = scrubbed.slice(0, f.start) + f.masked + scrubbed.slice(f.end);
}
return scrubbed;
}
В этом фрагменте важны три детали. Во-первых, он проходит известные поля с большим количеством PII, а не всю запись; вам не нужно очищать идентификатор запроса. Во-вторых, он сериализует каждое поле в одну строку перед отправкой в API, поэтому один вызов охватывает весь результат инструмента. В-третьих, он объединяет замены с конца строки, поэтому смещения не смещаются под нее.
Подключите его к регистратору
// logger.ts
import { redactPii } from './log-redact';
export async function logTurn(raw: LogRecord) {
const safe = await redactPii(raw);
await logStore.write(safe);
}
// anywhere in your agent loop:
await logTurn({
event: 'agent.turn',
prompt: userInput,
tool_calls: toolCalls,
tool_results: toolResults,
});
Вызов logTurn вместо существующего logger.info на границе поворота. Все, что выше по течению, остается прежним.
Закрыто, а не тихо
Конечная точка обнаружения обычно отвечает менее чем за 20 мс. Когда истечет время ожидания, у вас все равно будет выбор: записать необработанную строку (риск утечки) или удалить конфиденциальные поля и записать маркер. Удаление — более безопасный вариант по умолчанию для рабочих нагрузок, чувствительных к соблюдению требований.
async function redactPiiSafe(record: LogRecord): Promise<LogRecord> {
try {
return await Promise.race([
redactPii(record),
new Promise<LogRecord>((_, reject) =>
setTimeout(() => reject(new Error('pii-detect timeout')), 250)
),
]);
} catch (err) {
// Fail closed: drop the sensitive fields rather than logging them raw.
return { ...record, prompt: '[REDACT_FAILED]', tool_calls: [], tool_results: [] };
}
}
Установите тайм-аут на что-нибудь маленькое. 250 мс достаточно, чтобы компенсировать региональное замедление, не блокируя работоспособный путь запроса.
Версия Python
# log_redact.py
import os, json, httpx
PII_FIELDS = ('prompt', 'tool_calls', 'tool_results', 'output')
API = 'https://api.botoi.com/v1/pii/detect'
async def scrub(text: str) -> str:
async with httpx.AsyncClient(timeout=0.25) as client:
r = await client.post(
API,
headers={'Authorization': f"Bearer {os.environ['BOTOI_API_KEY']}"},
json={'text': text},
)
data = r.json()
if not data.get('found'):
return text
out = text
for f in sorted(data['findings'], key=lambda x: x['start'], reverse=True):
out = out[:f['start']] + f['masked'] + out[f['end']:]
return out
Уронить scrub в перехватчик журнала вашей агентской среды. Промежуточное программное обеспечение FastAPI, обратные вызовы LangChain и экспортеры интервалов OpenInference — все они принимают асинхронные функции.
Чего не делает это промежуточное программное обеспечение
- Он не распознает имена, адреса или номера счетов, которые не похожи ни на один поддерживаемый тип. Для этого нужна модель именованного объекта и политическое решение (маска? удаление? редактирование всего хода?).
- Это не защищает поставщика вашей модели от просмотра необработанного приглашения. Для этого запустите тот же вызов обнаружения на клиенте перед отправкой в модель.
- Оно не заменяет политику хранения данных. В любом случае сократите TTL журнала.
Два места, где это принадлежит
| Слой | Защищает | Время звонка |
|---|---|---|
| Перед запросом модели | Поставщик модели, данные обучения, утечки оценок | Блокировка, задержка, видимая пользователю |
| Перед записью в журнал | Хранилище журналов, поставщик наблюдаемости, экспорт | Внеполосный, невидимый для пользователя |
Сначала отправьте промежуточное программное обеспечение для записи журналов. Он проходит за пределами горячего пути и блокирует наиболее распространенные утечки. Добавьте предварительную версию, как только будет закрыта сторона бревна.
Получите ключ API и начните
Анонимный доступ дает вам 5 запросов в минуту, чего достаточно, чтобы протестировать конечную точку по образцу журнала. Для производственного промежуточного программного обеспечения получите бесплатный ключ по адресу botoi.com/api/signup. Уровень бесплатного пользования покрывает 1000 срочных вызовов в день без использования кредитной карты.
Полную ссылку на конечную точку см. на странице Страница API обнаружения личных данных или просмотреть api.botoi.com/docs для остальных 149 конечных точек.
FAQ
- Почему журналы агентов ИИ содержат больше личных данных, чем обычные журналы сервера?
- Агенты регистрируют все приглашения, каждый ввод вызова инструмента и каждый вывод инструмента. Транскрипт поддержки, который когда-то находился под флажком «не вести журнал», теперь появляется в пяти местах: оркестраторе, сервере инструментов, поставщике наблюдаемости, поставщике модели и наборе обучающей оценки.
- Где должен выполняться этап редактирования?
- Запустите его на границе записи журнала, прямо перед отправкой строки в хранилище журналов. Таким образом, каждый вышестоящий компонент (оркестратор, инструмент, SDK наблюдения) видит необходимый ему необработанный текст, и очищается только сохраненная копия.
- Редактор регулярных выражений улавливает все?
- Нет. Регулярное выражение «Сверните сами» пропускает номера кредитных карт с необычным интервалом, SSN, похожие на другие 9-значные номера, и имена людей. API, такой как /v1/pii/detect, запускает Luhn на карточках, фильтрует префиксы SSN и возвращает позиции, поэтому вы можете отбросить только совпадение, а не всю строку.
- Какую задержку добавляет API Botoi PII Detect?
- Конечная точка работает на границе и возвращается менее чем за 20 мс для полезной нагрузки в 500 токенов. Вы можете вызывать его синхронно в промежуточном программном обеспечении журнала, не влияя на видимое пользователю время ответа; регистрация происходит после отправки ответа.
- Могу ли я отредактировать на клиенте перед отправкой модели?
- Да, и это хороший второй слой. Редактирование в промежуточном программном обеспечении сервера защищает ваше хранилище журналов; редактирование в клиенте защищает поставщика вашей модели от просмотра необработанных PII. Оба вместе представляют собой установку, дружественную GDPR.
Начните разработку с botoi
150+ API-эндпоинтов для поиска, обработки текста, генерации изображений и утилит для разработчиков. Бесплатный тариф, без банковской карты.