Decisiones de IA que puedes defender: Auditabilidad, Trazabilidad y Pruebas en Producción
Cómo construir sistemas de IA con trazabilidad total de decisiones. Eventos de auditoría estructurados, recibos HMAC, cadenas de decisiones por sesión, registros de aprobación humana y arquitectura de retención.
"¿Qué hizo la IA y puedes demostrarlo?"
Esta pregunta surge en cada despliegue de IA empresarial. No viene de los ingenieros. Viene de legal, cumplimiento, compras y la junta directiva. La respuesta que necesitan no es "usamos GPT-4" ni "el modelo se entrenó con nuestros datos." Necesitan datos específicos: qué datos entraron, qué modelo los procesó, qué herramientas se invocaron, qué humano aprobó la acción y si el registro se puede verificar después de los hechos.
La mayoría de los sistemas de IA no pueden responder esta pregunta. Registran prompts y respuestas (si acaso), pero esos logs no te dicen la cadena de decisiones. No te dicen por qué el sistema eligió la opción A sobre la B. No te dicen quién aprobó una acción de alto valor. Y definitivamente no proporcionan pruebas a prueba de manipulación de que el registro no se ha modificado desde que se tomó la decisión.
Nosotros construimos trazabilidad de decisiones en múltiples sistemas de IA en producción. Este artículo cubre los patrones de arquitectura que hacen que las decisiones de IA sean defendibles. No teóricamente defendibles. Demostrablemente defendibles, con recibos criptográficos y registros inmutables.
Para contexto sobre cómo abordamos la gobernanza de IA de forma general y los sistemas con humano en el bucle en particular, esas guías cubren patrones relacionados. Este artículo se centra en la capa de pruebas: qué registrar, cómo estructurarlo y cómo hacerlo verificable.
Qué significa realmente la trazabilidad de decisiones
La trazabilidad de decisiones no es logging. El logging te dice qué pasó. La trazabilidad te dice por qué pasó, quién lo autorizó y si el registro es confiable.
| Capacidad | Logging estándar | Trazabilidad de decisiones |
|---|---|---|
| Qué pasó | Texto de prompt y respuesta | Evento de decisión estructurado con campos tipados |
| Qué modelo | Quizás en los headers | Explícito: ID del modelo, versión, proveedor, temperature |
| Qué datos se usaron | Prompt sin procesar (contiene PII) | IDs de tokens referenciando mapeo de sesión (sin PII) |
| Qué herramientas se llamaron | Quizás en logs de debug | Cadena de llamadas a herramientas estructurada con entradas y salidas |
| Quién lo aprobó | No se rastrea | Registro de aprobación: quién, cuándo, qué vio, qué decidió |
| ¿Se puede verificar? | No (los logs se pueden editar) | Recibo HMAC: a prueba de manipulación, firmado criptográficamente |
| Retención | Lo que tu agregador de logs conserve | Basado en políticas: 90 días operativo, 7 años archivo |
La diferencia importa cuando un cliente disputa una recomendación generada por IA, cuando un regulador pregunta cómo se tomó una decisión, o cuando una auditoría interna necesita verificar que el sistema de IA siguió la política.
El esquema del evento de decisión
Cada decisión de IA genera un evento estructurado. No una línea de log. Un registro tipado con campos explícitos para cada dimensión de la decisión.
interface AiDecisionEvent {
// Identidad
event_id: string; // UUID, único por evento
event_type: string; // "transform", "rehydrate", "tool_call", "agent_action", "approval"
timestamp: string; // ISO 8601 UTC
// Actor
actor_type: string; // "agent" | "human" | "system" | "scheduler"
actor_id: string; // ID del hilo del agente, ID de usuario o nombre del componente del sistema
// Contexto
tenant_id: string; // alcance multi-tenant
session_id: string; // agrupa eventos dentro de una sesión
correlation_id: string; // enlaza eventos relacionados entre servicios
channel_id?: string; // qué canal (web, api, widget)
// Modelo
model_provider?: string; // "openai" | "anthropic" | "local"
model_id?: string; // "gpt-4o" | "claude-sonnet-4-20250514"
model_version?: string; // versión de despliegue o checkpoint
// Decisión
action: string; // qué se hizo: "generate_response", "call_tool", "approve_order"
input_summary: object; // resumen estructurado (SIN PII sin procesar, solo IDs de tokens y tipos)
output_summary: object; // resumen estructurado del resultado
decision_rationale?: string; // por qué se tomó esta acción (del razonamiento del agente)
// Política
policy_id?: string; // qué política se evaluó
policy_result?: string; // "allowed" | "denied" | "escalated"
policy_conditions?: object; // qué condiciones se verificaron
// Aprobación (si HITL)
approval_required: boolean;
approval_status?: string; // "pending" | "approved" | "rejected"
approved_by?: string; // ID de usuario del aprobador
approved_at?: string; // cuándo se dio la aprobación
approval_context?: object; // qué vio el aprobador al decidir
// Integridad
receipt_hmac?: string; // HMAC-SHA256 del payload del evento
previous_event_id?: string; // enlace de cadena al evento anterior en la sesión
}
Las decisiones de diseño clave:
Sin PII en los eventos. El campo input_summary contiene IDs de tokens (p_001, e_001) y tipos de entidad, nunca valores sin procesar. Esto significa que tu almacenamiento de auditoría no se convierte en un sistema regulado por GDPR. Consulta nuestra guía de cumplimiento GDPR para la arquitectura completa.
Identificación explícita del modelo. No solo "usamos un LLM." Se registra el proveedor específico, el ID del modelo y la versión. Cuando un modelo se actualiza o reemplaza, puedes rastrear qué decisiones usaron qué versión.
Enlace en cadena. El campo previous_event_id crea una cadena enlazada de eventos dentro de una sesión. El evento 3 apunta al evento 2, que apunta al evento 1. La cadena prueba la secuencia de decisiones y que no se insertaron ni eliminaron eventos después de los hechos.
Cadenas de decisiones por sesión
Una sola interacción con IA frecuentemente involucra múltiples decisiones. Un agente de soporte al cliente podría: leer el ticket (evento 1), buscar información del cliente (evento 2), verificar la facturación (evento 3), redactar una respuesta (evento 4) y enviar el correo (evento 5). Cada paso es un evento de decisión. Juntos, forman una cadena de decisiones.
┌──────────────────────────────────────────────────────┐
│ SESSION: sess_abc123 │
│ │
│ Evento 1 Evento 2 Evento 3 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ LEER │──▶│ BUSCAR │──▶│ VERIFICAR│ │
│ │ TICKET │ │ CLIENTE │ │ FACTURA │ │
│ │ │ │ │ │ │ │
│ │ model: │ │ tool: │ │ tool: │ │
│ │ claude │ │ crm_api │ │ billing │ │
│ │ │ │ │ │ _api │ │
│ │ tokens: │ │ tokens: │ │ tokens: │ │
│ │ p_001 │ │ cid_001 │ │ o_001 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ Evento 4 Evento 5 │
│ ┌──────────┐ ┌──────────┐ │
│ │ REDACTAR │──▶│ ENVIAR │ │
│ │ RESPUESTA│ │ EMAIL │ │
│ │ │ │ │ │
│ │ model: │ │ channel: │ │
│ │ claude │ │ email │ │
│ │ │ │ │ │
│ │ policy: │ │ restore: │ │
│ │ support │ │ formatted│ │
│ └──────────┘ └──────────┘ │
│ │
└──────────────────────────────────────────────────────┘
Cada evento referencia al anterior. La cadena es verificable: si alguien elimina el evento 3, la cadena del evento 4 al evento 2 tiene un hueco. Si alguien inserta un evento falso entre el 2 y el 3, los enlaces de la cadena no coinciden.
Consultar la cadena
Cuando un auditor pregunta "¿qué pasó con la sesión X?", consultas por session_id y reconstruyes la cadena:
async function getDecisionChain(sessionId: string): Promise<AiDecisionEvent[]> {
const events = await this.eventStore.findBySessionId(sessionId, {
orderBy: 'timestamp',
direction: 'ASC',
});
// Verificar integridad de la cadena
for (let i = 1; i < events.length; i++) {
if (events[i].previous_event_id !== events[i - 1].event_id) {
throw new ChainIntegrityError(
`Chain broken at event ${events[i].event_id}: ` +
`expected previous ${events[i - 1].event_id}, ` +
`got ${events[i].previous_event_id}`
);
}
}
return events;
}
Para ver cómo manejamos verificación de cadena similar en transacciones de comercio, consulta nuestra guía de comercio agéntico que usa recibos HMAC con el mismo propósito.
Recibos HMAC: prueba a prueba de manipulación
Los eventos de decisión almacenados en una base de datos se pueden modificar. Un recibo HMAC demuestra que los datos del evento no han cambiado desde que se crearon.
function signDecisionEvent(event: AiDecisionEvent, tenantSecret: string): string {
// Forma canónica: claves ordenadas, JSON determinista
const canonical = JSON.stringify(event, Object.keys(event).sort());
return crypto.createHmac('sha256', tenantSecret).update(canonical).digest('hex');
}
function verifyDecisionEvent(event: AiDecisionEvent, storedHmac: string, tenantSecret: string): boolean {
const recomputed = signDecisionEvent(event, tenantSecret);
return crypto.timingSafeEqual(
Buffer.from(recomputed, 'hex'),
Buffer.from(storedHmac, 'hex')
);
}
Cada evento de decisión se firma en el momento de creación. El HMAC se almacena junto al evento. Para verificar, se recalcula el HMAC a partir de los datos actuales del evento y se compara. Si se modificó un solo campo después de la firma, el HMAC no coincidirá.
| Propiedad | Valor |
|---|---|
| Algoritmo | HMAC-SHA256 |
| Clave | Secreto por tenant (rotado anualmente) |
| Canonicalización | JSON.stringify(payload, Object.keys(payload).sort()) |
| Salida | String codificado en hex (64 caracteres) |
| Comparación | Timing-safe (crypto.timingSafeEqual) |
El secreto por tenant significa que los recibos de un tenant no se pueden verificar usando la clave de otro tenant. La rotación de claves incluye un período de superposición de 24 horas donde tanto la clave antigua como la nueva se aceptan para verificación.
Registros de aprobación humana
Cuando una decisión requiere aprobación humana (transacciones de alto valor, acceso a datos sensibles, excepciones de política), la aprobación en sí misma es un evento de decisión con campos específicos:
interface ApprovalEvent extends AiDecisionEvent {
event_type: 'approval';
approval_required: true;
// Lo que el humano vio al decidir
approval_context: {
original_request: string; // resumen de lo que se solicitó
estimated_impact: string; // "Order for 2,500 EUR from supplier Alpha"
policy_triggered: string; // "require_human_approval_above: 500"
agent_recommendation: string; // lo que el agente sugirió
risk_flags: string[]; // alertas mostradas al aprobador
};
// Lo que el humano decidió
approved_by: string; // ID de usuario
approved_at: string; // ISO 8601
approval_status: 'approved' | 'rejected';
rejection_reason?: string; // si se rechazó, por qué
approval_duration_ms: number; // cuánto tardó el humano en decidir
}
El campo approval_context es crítico. Registra qué información se le presentó al humano cuando tomó su decisión. Esto previene el argumento "lo aprobé pero no sabía X." El registro muestra exactamente lo que el aprobador vio.
approval_duration_ms también es útil para auditoría. Si un aprobador aprueba consistentemente en menos de 2 segundos, eso sugiere aprobación mecánica en lugar de revisión genuina. Los equipos de cumplimiento usan esta métrica para evaluar si la supervisión humana es significativa.
Qué NO registrar
La trazabilidad de decisiones requiere disciplina sobre lo que entra en la pista de auditoría.
Sí registrar:
- IDs de tokens y tipos de entidad (por ejemplo, "entidad p_001 de tipo persona fue detectada")
- Identificadores y versiones de modelos
- Nombres de llamadas a herramientas y parámetros estructurados
- Resultados de evaluación de políticas
- Registros de aprobación con contexto
- Información de tiempo (latencias, duraciones)
- Códigos de error y razones de fallo
NO registrar:
- PII sin procesar (nombres, correos, números de teléfono, direcciones)
- Texto completo del prompt (contiene PII y es enorme)
- Respuestas completas del modelo (mismos problemas)
- Credenciales de autenticación o API keys
- Contraseñas internas del sistema o cadenas de conexión
// Bueno: estructurado, libre de PII
{
event_type: "transform",
action: "detect_and_tokenize",
input_summary: {
entities_detected: 3,
entity_types: ["person", "email", "customer_id"],
token_ids: ["p_001", "e_001", "cid_001"],
detection_confidence: [0.95, 1.0, 0.99],
},
policy_id: "german-support",
model_id: "ner-spacy-de",
duration_ms: 12,
}
// Malo: contiene PII, inútil para consultas estructuradas
{
event_type: "transform",
action: "process_input",
input: "Hallo, ich bin Sara Mustermann, meine Kundennummer ist 948221...",
output: "Hallo, ich bin {{person:p_001}}...",
}
El ejemplo bueno es consultable ("muéstrame todos los eventos donde la confianza de detección fue menor a 0.8"), filtrable ("muéstrame todos los eventos para la política german-support") y libre de PII. El ejemplo malo es un bloque de texto que se convierte en una responsabilidad GDPR.
Para la arquitectura completa de logging seguro para PII en sistemas de IA, consulta nuestra guía de observabilidad de IA.
Arquitectura de retención
Los eventos de decisión tienen diferentes requisitos de retención dependiendo de su contexto regulatorio:
| Nivel | Almacenamiento | Retención | Consultable | Caso de uso |
|---|---|---|---|---|
| Caliente | Base de datos (PostgreSQL / DynamoDB) | 90 días | SQL/consulta completa | Depuración, dashboards operativos, monitoreo en tiempo real |
| Templado | Object storage (S3) | 2 años | Por session_id, rango de fechas | Auditorías internas, disputas de clientes, revisiones de cumplimiento |
| Frío | Object storage con bloqueos write-once | 7 años | Solo por session_id | Auditorías regulatorias, retenciones legales, cumplimiento financiero |
El nivel frío usa object storage con bloqueos en modo de cumplimiento. Una vez escritos, los registros no se pueden modificar ni eliminar hasta que expire el período de retención. Esto no es solo control de acceso. El sistema de almacenamiento impide físicamente la eliminación, incluso por administradores.
Evento de Decisión Creado
│
├──▶ Nivel Caliente (base de datos): escritura inmediata, consultable
│
├──▶ Nivel Templado (object storage): exportación diaria por lotes
│
└──▶ Nivel Frío (object storage con bloqueo): streaming desde la base
de datos vía change data capture, write-once, bloqueo de 7 años
El streaming de la base de datos al almacenamiento frío ocurre a través de change data capture (streams de base de datos o envío WAL). Los eventos se escriben en el archivo inmutable en minutos desde su creación. No hay un batch job que se ejecute diariamente y pueda perder eventos. El stream es continuo.
Correlación entre servicios
En un sistema de IA distribuido, una sola solicitud de usuario puede tocar múltiples servicios: un API gateway, un runtime de protección de datos, un proveedor de LLM, un servidor de herramientas y un servicio de auditoría. El correlation_id une todos los eventos de decisión de todos los servicios.
// El API gateway genera el correlation_id
const correlationId = generateUUID();
// Cada servicio downstream lo recibe
const response = await dataProtection.transform(input, {
headers: { 'X-Correlation-Id': correlationId },
});
// Cada evento de decisión lo incluye
const event: AiDecisionEvent = {
correlation_id: correlationId,
// ...
};
Al depurar o auditar, consulta por correlation_id para obtener el panorama completo de todos los servicios. Este es el mismo patrón usado en trazado distribuido, pero aplicado específicamente a eventos de decisión en lugar de trazas de rendimiento.
Implementación práctica
Elección de almacenamiento
| Requisito | PostgreSQL | DynamoDB | Event Store (ej. EventStoreDB) |
|---|---|---|---|
| Consultas estructuradas | Excelente | Limitado (clave-valor) | Limitado (basado en streams) |
| Throughput de escritura | Bueno (con connection pooling) | Excelente (auto-scaling) | Excelente |
| Integridad de cadena | A nivel de aplicación | A nivel de aplicación | Integrado (streams append-only) |
| Políticas de retención | A nivel de aplicación | TTL en items | Integrado |
| Costo a escala | Fijo (basado en servidor) | Pago por solicitud | Fijo |
Para la mayoría de las implementaciones, PostgreSQL es la elección correcta para el nivel caliente. Es consultable, transaccional, y tu equipo ya lo conoce. DynamoDB funciona bien si estás en AWS y necesitas throughput de escritura con auto-scaling. Un event store dedicado es excesivo a menos que tengas miles de eventos de decisión por segundo.
Patrones de consulta
Las consultas más comunes contra el almacén de eventos de decisión:
-- Todas las decisiones en una sesión (reconstruir la cadena)
SELECT * FROM ai_decision_events
WHERE session_id = $1
ORDER BY timestamp ASC;
-- Todas las decisiones de un agente específico en las últimas 24 horas
SELECT * FROM ai_decision_events
WHERE actor_type = 'agent' AND actor_id = $1
AND timestamp > NOW() - INTERVAL '24 hours'
ORDER BY timestamp DESC;
-- Todas las evaluaciones de política denegadas (encontrar políticas mal configuradas)
SELECT * FROM ai_decision_events
WHERE policy_result = 'denied'
AND timestamp > NOW() - INTERVAL '7 days'
ORDER BY timestamp DESC;
-- Todas las aprobaciones humanas con tiempo de revisión corto (detección de aprobación mecánica)
SELECT * FROM ai_decision_events
WHERE event_type = 'approval'
AND approval_status = 'approved'
AND approval_duration_ms < 3000
AND timestamp > NOW() - INTERVAL '30 days';
-- Verificar integridad de la cadena para una sesión
SELECT e1.event_id, e1.previous_event_id,
CASE WHEN e2.event_id IS NULL AND e1.previous_event_id IS NOT NULL
THEN 'BROKEN' ELSE 'OK' END as chain_status
FROM ai_decision_events e1
LEFT JOIN ai_decision_events e2 ON e1.previous_event_id = e2.event_id
WHERE e1.session_id = $1;
Indexación
CREATE INDEX idx_session ON ai_decision_events (session_id, timestamp);
CREATE INDEX idx_actor ON ai_decision_events (actor_type, actor_id, timestamp);
CREATE INDEX idx_correlation ON ai_decision_events (correlation_id);
CREATE INDEX idx_policy_result ON ai_decision_events (policy_result, timestamp);
CREATE INDEX idx_approval ON ai_decision_events (event_type, approval_status, timestamp)
WHERE event_type = 'approval';
Errores comunes
-
Registrar prompts sin procesar como pista de auditoría. Los prompts contienen PII. Tu almacenamiento de auditoría se convierte en un sistema regulado por GDPR. Usa eventos estructurados con IDs de tokens en su lugar.
-
Sin enlace de cadena entre eventos. Sin
previous_event_id, no puedes probar la secuencia de decisiones. Los eventos se pueden insertar, eliminar o reordenar sin detección. -
Sin firma HMAC. Los registros de base de datos se pueden modificar. Sin recibos criptográficos, la pista de auditoría no es a prueba de manipulación. "Confía en nosotros, no editamos los logs" no es defendible.
-
Misma retención para todo. Los datos de depuración necesitan 90 días. Los datos de cumplimiento necesitan 7 años. Mezclarlos desperdicia dinero (guardar datos de depuración demasiado tiempo) o crea riesgos (eliminar datos de cumplimiento demasiado pronto).
-
Sin contexto de aprobación. Registrar que "el usuario X aprobó la acción Y" no es suficiente. Registra qué información vio el aprobador al decidir. Sin contexto, la aprobación no tiene sentido para la auditoría.
-
Falta detección de aprobación mecánica. Si la supervisión humana es un requisito de cumplimiento, necesitas verificar que los humanos realmente están revisando, no solo haciendo clic en "aprobar" de forma reflexiva. Rastrea
approval_duration_ms. -
Sin correlación entre servicios. Si tu sistema de IA abarca múltiples servicios, los eventos de cada servicio están aislados. Sin un correlation_id, no puedes reconstruir la cadena de decisiones completa.
-
Almacenamiento frío mutable. Si tu archivo a largo plazo se puede editar o eliminar por administradores, no es una pista de auditoría. Usa almacenamiento write-once con bloqueos en modo de cumplimiento.
Conclusiones clave
-
"Usamos GPT-4" no es una respuesta defendible. Registra el modelo específico, la versión, el proveedor, los tokens de entrada, los tokens de salida, las herramientas invocadas, las políticas evaluadas y los humanos que aprobaron. Cada dimensión de la decisión.
-
Eventos estructurados, no líneas de log. Los campos tipados permiten consultas estructuradas, dashboards, detección de anomalías e informes de cumplimiento. Los logs de texto libre no permiten nada excepto grep.
-
Sin PII en eventos de decisión. Usa IDs de tokens de tu capa de protección de datos. La pista de auditoría no debe convertirse en sí misma en una responsabilidad de protección de datos.
-
El enlace de cadena prueba la secuencia. Cada evento apunta a su predecesor. Los huecos e inserciones son detectables. Combinado con la firma HMAC, la cadena es a prueba de manipulación.
-
Los recibos HMAC proporcionan prueba criptográfica. Claves de firma por tenant, serialización JSON canónica, comparación timing-safe. Cualquier modificación a cualquier campo invalida el recibo.
-
Los registros de aprobación humana deben incluir contexto. ¿Qué vio el aprobador? ¿Cuánto tiempo tardó? Sin esto, "supervisión humana" es un checkbox, no un control.
-
La retención en tres niveles refleja la realidad regulatoria. Caliente para depuración (90 días), templado para auditorías (2 años), frío con bloqueos write-once para reguladores (7 años).
Aplicamos estos patrones en todos nuestros sistemas de IA, desde runtimes de protección de datos hasta plataformas de comercio agéntico. Si estás construyendo sistemas de IA que necesitan satisfacer requisitos de cumplimiento empresarial, habla con nuestro equipo o solicita un presupuesto. Puedes explorar nuestros servicios de IA, nuestro enfoque de confianza y cumplimiento, y nuestras guías sobre arquitectura de sistemas de IA y modos de fallo de IA para más contexto.
Temas cubiertos
Guías relacionadas
Guía Empresarial de Sistemas de IA Agéntica
Guia tecnica de sistemas de IA agentica en entornos empresariales. Descubre la arquitectura, capacidades y aplicaciones de agentes IA autonomos.
Leer guíaComercio Agéntico: Cómo Dejar que los Agentes IA Compren de Forma Segura
Cómo diseñar comercio iniciado por agentes IA con gobernanza. Motores de políticas, puertas de aprobación HITL, recibos HMAC, idempotencia, aislamiento de tenants y el Agentic Checkout Protocol completo.
Leer guíaLos 9 Puntos Donde Tu Sistema de IA Filtra Datos (y Cómo Sellar Cada Uno)
Un mapa sistemático de cada lugar donde se filtran datos en sistemas de IA. Prompts, embeddings, logs, llamadas a herramientas, memoria de agentes, mensajes de error, caché, datos de fine-tuning y handoffs entre agentes.
Leer guía¿Listo para construir sistemas de IA listos para producción?
Nuestro equipo se especializa en sistemas de IA listos para producción. Hablemos de cómo podemos ayudar.
Iniciar una conversación