Redactar la PII de los registros del agente de IA antes de que llegue a su base de datos
Su agente registra cada aviso y llamada de herramienta. Un SSN perdido en una transcripción se convierte en una divulgación del RGPD. Un middleware de tres líneas lo soluciona antes de que se escriba la fila.
Su agente de IA registra el mensaje. La herramienta llama a la entrada. El resultado de la herramienta. La respuesta final. Solía ser una mina de oro de datos de depuración. Hoy es una divulgación de GDPR esperando un ticket de soporte para llevar un SSN más allá de su validación.
No puede impedir que los usuarios peguen datos confidenciales. Puede evitar que el texto sin formato llegue a su almacén de registros, a su proveedor de observabilidad y a su exportación de evaluación semanal. Un pequeño middleware lo hace de un solo salto.
La fuga que ya tienen la mayoría de las configuraciones de agentes
// 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 fila ahora lleva un número de tarjeta. El almacén de troncos lo conserva durante 30 días. El SDK de observabilidad lo envía a un tercero. La exportación de evaluación retoma la misma cadena dos días después. Cinco copias de una tarjeta; todos ellos fuera del alcance de su política de cifrado en reposo.
Detecta PII con una llamada
La botoi /v1/pii/detect El endpoint escanea el texto en busca de correos electrónicos, números de teléfono, números de seguro social, tarjetas de crédito (validadas por Luhn), direcciones IP y fechas de nacimiento. Devuelve cada hallazgo con un desplazamiento inicial, un desplazamiento final y un valor enmascarado que puede colocar en su lugar.
Pedido
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."}'
Respuesta
{
"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" }
]
}
Tres partidos, tres reemplazos enmascarados, posiciones que puedes unir limpiamente. No hay una biblioteca de expresiones regulares que mantener, ni una tabla de prefijos de SSN que mantener actualizada, ni un pase de Luhn que escribir usted mismo.
Un middleware de registro que redacta antes de escribir
El lugar correcto para esto es el último salto antes de que la fila abandone su proceso. Cada componente ascendente todavía ve el texto sin formato que necesita; la copia persistente se desinfecta.
// 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;
}
Tres detalles importan en ese fragmento. En primer lugar, recorre campos conocidos con gran cantidad de PII en lugar de todo el registro; no es necesario borrar el ID de la solicitud. En segundo lugar, serializa cada campo en una sola cadena antes de enviarlo a la API, de modo que una llamada cubra el resultado completo de la herramienta. En tercer lugar, empalma los reemplazos desde el final de la cadena para que los desplazamientos no se desplacen debajo de ella.
Conéctelo al 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,
});
Llamar logTurn en lugar de su existente logger.info en el límite de giro. Todo aguas arriba sigue igual.
Falla cerrada, no falla silenciosa.
El punto final de detección suele responder en menos de 20 ms. Cuando se agote el tiempo de espera, todavía tiene una opción: registrar la fila sin procesar (riesgo de fuga) o descartar los campos confidenciales y registrar un marcador. La eliminación es la opción predeterminada más segura para cargas de trabajo sensibles al cumplimiento.
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: [] };
}
}
Establezca el tiempo de espera en algo pequeño. 250 ms son suficientes para absorber una desaceleración regional sin bloquear una ruta de solicitud saludable.
Versión de 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
Gota scrub en el gancho de registro del marco de su agente. El middleware FastAPI, las devoluciones de llamadas de LangChain y los exportadores de tramos de OpenInference aceptan funciones asíncronas.
Lo que este middleware no hace
- No detecta nombres, direcciones o números de cuenta que no se parezcan a ningún tipo admitido. Estos necesitan un modelo de entidad con nombre y una decisión política (¿máscara? ¿soltar? ¿redactar todo el turno?).
- No protege a su proveedor de modelo para que no vea el mensaje sin formato. Para eso, ejecute la misma llamada de detección en el cliente antes de enviarla al modelo.
- No reemplaza una política de retención de datos. Acorte el registro TTL de todos modos.
Dos lugares a los que pertenece
| Capa | Protege | Temporización de llamadas |
|---|---|---|
| Antes de la solicitud del modelo | Proveedor de modelos, datos de entrenamiento, fugas de evaluación. | Bloqueo, latencia visible para el usuario |
| Antes de escribir el registro | Almacén de registros, proveedor de observabilidad, exportaciones. | Fuera de banda, invisible para el usuario |
Envíe primero el middleware de escritura de registros. Corre fuera del camino caliente y bloquea el patrón de fuga más común. Agregue la versión anterior al modelo una vez cubierto el lado del tronco.
Obtenga una clave API y comience
El acceso anónimo le brinda 5 solicitudes por minuto, suficiente para probar el punto final con un registro de muestra. Para middleware de producción, obtenga una clave gratuita en botoi.com/api/signup. El nivel gratuito cubre 1000 llamadas de limpieza por día sin tarjeta de crédito.
Consulte la referencia completa del punto final en Página API de detección de PII o navegar api.botoi.com/docs para los otros 149 puntos finales.
FAQ
- ¿Por qué los registros de los agentes de IA filtran más información de identificación personal que los registros normales del servidor?
- Los agentes registran todo el mensaje, cada entrada de llamada de herramienta y cada salida de herramienta. Una transcripción de soporte que alguna vez estuvo detrás de una bandera de "no registrar" ahora aparece en cinco lugares: el orquestador, el servidor de herramientas, el proveedor de observabilidad, el proveedor del modelo y el conjunto de evaluación de entrenamiento.
- ¿Dónde debería ejecutarse el paso de redacción?
- Ejecútelo en el límite del escritor de registros, justo antes de que la fila se envíe a su almacén de registros. De esa manera, cada componente ascendente (orquestador, herramienta, SDK de observabilidad) ve el texto sin formato que necesita y solo se desinfecta la copia persistente.
- ¿Un redactor de expresiones regulares capta todo?
- No. La expresión regular Roll-your-own omite números de tarjetas de crédito con espacios inusuales, SSN que se parecen a otros números de 9 dígitos y nombres de personas. Una API como /v1/pii/detect ejecuta Luhn en tarjetas, filtra prefijos de SSN y devuelve posiciones para que pueda descartar solo la coincidencia, no toda la línea.
- ¿Qué latencia agrega la API de detección de PII de Botoi?
- El punto final se ejecuta en el borde y regresa en menos de 20 ms para una carga útil de 500 tokens. Puede llamarlo sincrónicamente en un middleware de registro sin afectar los tiempos de respuesta visibles para el usuario; El registro se produce después de enviar la respuesta.
- ¿Puedo redactar sobre el cliente antes de enviarlo al modelo?
- Sí, y es una buena segunda capa. La redacción en el middleware del servidor protege su almacén de registros; La redacción en el cliente protege a su proveedor modelo de ver PII sin procesar. Ambos juntos son una configuración compatible con GDPR.
Empieza a construir con botoi
150+ endpoints de API para consultas, procesamiento de texto, generacion de imagenes y utilidades para desarrolladores. Plan gratuito, sin tarjeta de credito.