Edite PII dos logs do agente de IA antes que cheguem ao seu banco de dados
Seu agente registra cada solicitação e chamada de ferramenta. Um SSN perdido em uma transcrição se transforma em uma divulgação do GDPR. Um middleware de três linhas corrige isso antes que a linha seja gravada.
Seu agente de IA registra o prompt. A entrada de chamada da ferramenta. O resultado da ferramenta. A resposta final. Isso costumava ser uma mina de ouro de dados de depuração. Hoje é uma divulgação do GDPR aguardando um ticket de suporte para passar um SSN após sua validação.
Você não pode impedir que os usuários colem dados confidenciais. Você pode impedir que o texto bruto chegue ao seu armazenamento de logs, ao seu fornecedor de observabilidade e à sua exportação de avaliação semanal. Um pequeno middleware faz isso em um salto.
O vazamento que a maioria das configurações de agente já possui
// 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.
Cada linha agora carrega um número de cartão. O armazenamento de log o mantém por 30 dias. O SDK de observabilidade o envia para terceiros. A exportação eval pega a mesma string dois dias depois. Cinco cópias de um cartão; todos eles fora do escopo de sua política de criptografia em repouso.
Detecte PII com uma chamada
O Botoi /v1/pii/detect O endpoint verifica texto em busca de e-mails, números de telefone, SSNs, cartões de crédito (validados por Luhn), endereços IP e datas de nascimento. Ele retorna cada descoberta com um deslocamento inicial, um deslocamento final e um valor mascarado que você pode colocar no lugar.
Solicitar
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."}'
Resposta
{
"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" }
]
}
Três fósforos, três substituições mascaradas, posições que você pode emendar de maneira limpa. Nenhuma biblioteca regex para manter, nenhuma tabela de prefixo SSN para manter atualizada, nenhum passe Luhn para escrever você mesmo.
Um middleware de log que edita antes de gravar
O lugar certo para isso é o último salto antes da linha sair do seu processo. Cada componente upstream ainda vê o texto bruto de que precisa; a cópia persistente é higienizada.
// 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;
}
Três detalhes são importantes nesse trecho. Primeiro, ele percorre campos conhecidos com muitas PII, em vez de todo o registro; você não precisa limpar o ID da solicitação. Em segundo lugar, ele serializa cada campo em uma única string antes de enviar para a API, de forma que uma chamada cubra todo o resultado da ferramenta. Terceiro, ele une as substituições do final da string para que os deslocamentos não mudem sob ela.
Conecte-o ao registrador
// 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,
});
Chamar logTurn no lugar do seu existente logger.info no limite da curva. Tudo a montante permanece o mesmo.
Falha no fechamento, não falha no silêncio
O endpoint de detecção geralmente responde em menos de 20 ms. Quando o tempo expirar, você ainda terá uma escolha: registrar a linha bruta (risco de vazamento) ou descartar os campos confidenciais e registrar um marcador. A eliminação é o padrão mais seguro para cargas de trabalho sensíveis à conformidade.
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: [] };
}
}
Defina o tempo limite para algo pequeno. 250 ms são suficientes para absorver uma desaceleração regional sem bloquear um caminho de solicitação íntegro.
Versão 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
Derrubar scrub no gancho de log da sua estrutura de agente. Middleware FastAPI, retornos de chamada LangChain e exportadores de span OpenInference aceitam funções assíncronas.
O que este middleware não faz
- Ele não captura nomes, endereços ou números de contas que não se pareçam com nenhum tipo compatível. Eles precisam de um modelo de entidade nomeada e de uma decisão política (máscara? descartar? redigir toda a curva?).
- Isso não protege o fornecedor do seu modelo de ver o prompt bruto. Para isso, execute a mesma chamada de detecção no cliente antes de enviar para o modelo.
- Ela não substitui uma política de retenção de dados. Encurte o TTL do log de qualquer maneira.
Dois lugares onde isso pertence
| Camada | Protege | Tempo de chamada |
|---|---|---|
| Antes da solicitação do modelo | Fornecedor de modelo, dados de treinamento, vazamentos de avaliação | Bloqueio, latência visível ao usuário |
| Antes da gravação do log | Armazenamento de logs, fornecedor de observabilidade, exportações | Fora de banda, invisível para o usuário |
Envie primeiro o middleware log-write. Ele corre fora do caminho quente e bloqueia o padrão de vazamento mais comum. Adicione a versão pré-modelo assim que o lado do log estiver coberto.
Obtenha uma chave de API e comece
O acesso anônimo oferece cinco solicitações por minuto, o suficiente para testar o endpoint em um log de amostra. Para middleware de produção, obtenha uma chave gratuita em botoi.com/api/signup. O nível gratuito cobre 1.000 ligações por dia, sem cartão de crédito.
Veja a referência completa do endpoint no Página da API de detecção de PII ou navegue api.botoi.com/docs para os outros 149 pontos finais.
FAQ
- Por que os logs do agente de IA vazam mais PII do que os logs normais do servidor?
- Os agentes registram todo o prompt, cada entrada de chamada de ferramenta e cada saída de ferramenta. Uma transcrição de suporte que antes ficava atrás de um sinalizador "não registrar" agora aparece em cinco lugares: o orquestrador, o servidor de ferramentas, o fornecedor de observabilidade, o provedor de modelo e o conjunto de avaliação de treinamento.
- Onde a etapa de redação deve ser executada?
- Execute-o no limite do gravador de log, logo antes de a linha ser enviada para seu armazenamento de log. Dessa forma, cada componente upstream (orquestrador, ferramenta, SDK de observabilidade) vê o texto bruto necessário e apenas a cópia persistente é higienizada.
- Um redator de regex captura tudo?
- Não. O regex roll-your-own ignora números de cartão de crédito com espaçamento incomum, SSNs que se parecem com outros números de 9 dígitos e nomes de pessoas. Uma API como /v1/pii/detect executa Luhn em cartões, filtra prefixos SSN e retorna posições para que você possa descartar apenas a correspondência, não a linha inteira.
- Que latência a API Botoi PII Detect adiciona?
- O endpoint é executado na borda e retorna em menos de 20 ms para uma carga útil de 500 tokens. Você pode chamá-lo de forma síncrona em um middleware de log sem afetar os tempos de resposta visíveis ao usuário; o registro acontece depois que a resposta é enviada.
- Posso redigir no cliente antes de enviar para o modelo?
- Sim, e é uma boa segunda camada. A redação no middleware do servidor protege seu armazenamento de log; a redação no cliente protege o fornecedor do modelo de ver PII brutas. Ambos juntos são a configuração compatível com GDPR.
Comece a construir com botoi
150+ endpoints de API para consultas, processamento de texto, geração de imagens e utilitários para desenvolvedores. Plano gratuito, sem cartão de crédito.