Registro de auditoría de acciones de agentes: un modelo práctico para el control
Crea un registro de auditoría de acciones de agentes que capture la identidad del proceso, los destinos, las aprobaciones, los resultados, las revocaciones y las pruebas de manipulación sin registrar secretos.

Las acciones de los agentes necesitan registros que describan la autoridad, no solo la actividad. Una línea como POST /deploy returned 200 no puede decirle a un investigador si el proceso correcto hizo la solicitud, si una persona la autorizó, qué sistema la recibió ni si una revocación posterior detuvo algo.
La unidad práctica es un registro de acción inmutable, relacionado con eventos de sesión, aprobación y revocación. Mantén el registro lo bastante pequeño para buscarlo y verificarlo, pero con suficientes detalles para que un ingeniero cansado pueda reconstruir una llamada discutida sin inventar una historia alrededor de campos ausentes.
Una entrada de auditoría debe describir un intento autorizado
Un registro de auditoría de acciones de agente captura un efecto intentado sobre un sistema externo y el contexto de autoridad presente en ese instante. Una acción puede fallar antes de llegar a la red, durante la entrega, recibir un rechazo del destino o completarse correctamente. Los cuatro casos pertenecen al registro de auditoría.
Los equipos suelen registrar una de dos cosas insuficientes. Registran una transcripción del chat, que describe la intención pero no la ejecución. O registran el tráfico bruto de las solicitudes, que produce demasiado material secreto y aun así omite la decisión humana que permitió la llamada. Ninguno de los dos registros responde si un actor concreto tenía autoridad para realizar una operación concreta.
Trata estos elementos como objetos separados:
- Una sesión identifica un proceso de agente en ejecución y su ciclo de vida.
- Una aprobación registra una decisión humana con un alcance definido.
- Una acción registra una operación externa solicitada y su resultado.
- Una revocación termina una sesión o autorización en un momento preciso.
La distinción tiene consecuencias durante un incidente. Si una persona revoca una sesión a las 14:03, necesitas ver todas las acciones anteriores a las 14:03, todos los intentos posteriores y la decisión local que denegó esos intentos. Una única fila mutable con la etiqueta «sesión aprobada: no» destruye ese historial.
No hagas que el modelo de registro dependa de que la acción haya tenido éxito. La solicitud en sí puede mostrar una intención maliciosa, un defecto de configuración o un agente que entendió mal su tarea. Las llamadas fallidas suelen ser la primera prueba útil.
El actor es un proceso, no una etiqueta amigable de agente
Registra el proceso que solicitó realmente la acción. El nombre del modelo, del espacio de trabajo o el apodo del agente puede ayudar a una persona a revisar un informe, pero ninguno identifica de forma única el ejecutable que tenía la conexión en ese momento.
Un objeto de actor útil contiene un identificador interno de sesión, el ID del proceso, la ruta del ejecutable, la hora de inicio y la autoridad de firma de código cuando el sistema operativo la proporciona. Incluye el ID del proceso principal y su ejecutable cuando puedas obtenerlos de forma fiable. La relación con el proceso principal suele explicar si el agente fue iniciado desde una terminal, creado por una extensión del editor o ejecutado por un asistente inesperado.
Usa una instantánea de la identidad del proceso en lugar de resolverlo más tarde. Los ID de proceso se reutilizan. Las rutas pueden cambiar. Una consulta posterior no puede reparar una observación que nunca se registró.
{
"actor": {
"session_id": "ses_01J8Q1F9K9Z3",
"pid": 48217,
"started_at": "2025-02-18T21:14:06Z",
"executable": "/usr/local/bin/agent-runner",
"signing_authority": "Developer ID Application: Example Developer",
"parent_pid": 48091,
"parent_executable": "/Applications/Terminal.app"
}
}
El valor de signing_authority debe proceder de la evaluación de firma de la plataforma, no de una cadena proporcionada por el agente. Un agente puede llamarse claude-code, deploy-helper o trusted-agent. Una etiqueta es decorativa a menos que el sistema operativo la vincule a una identidad ejecutable.
No conviertas la identidad del proceso en una afirmación falsa de autoría. Un binario firmado puede actuar mal después de una inyección de instrucciones, un complemento comprometido o una instrucción descuidada. El campo establece qué autoridad de código inició la solicitud. No certifica que la solicitud fuera sensata.
RFC 5424, la especificación del protocolo syslog, separa campos de cabecera como el nombre de la aplicación y el ID del proceso de los datos estructurados. Esa separación sigue teniendo sentido para los registros de agentes. Coloca la identidad estable y los tiempos en campos específicos que las máquinas puedan consultar. Pon el contexto variable, como la referencia al repositorio o a la tarea, en un objeto con espacio de nombres. Cuando todo termina en una única cadena de mensaje, cada investigación posterior se convierte en un problema de análisis de texto.
Un destino necesita una dirección y un significado
Registra adónde fue una acción y qué recurso o comando pretendía afectar. Son hechos relacionados, pero no intercambiables.
En HTTP, el destino de red puede ser api.example.internal, mientras que la operación significativa es POST /v1/releases/{release_id}/promote. Guarda el host, el puerto, el protocolo, el método HTTP y una plantilla de ruta. Añade un identificador del sistema de destino que controle tu equipo, como release-service-prod. El identificador sobrevive a una migración de host, mientras que el nombre del host ayuda a diagnosticar la solicitud que realmente salió de la máquina.
En SSH, guarda el alias o nombre del host, el puerto, la huella de la clave del host o una referencia a la entrada de hosts conocidos y la etiqueta de la cuenta remota cuando sea seguro conservarla. El destino también debe indicar la clase de comando solicitada. restart-worker explica más que ssh succeeded, pero revela menos que un comando de shell completo que contenga rutas de clientes y variables de entorno.
Redacta antes de guardar, no después de que un analista abra el registro. Las cadenas de consulta de URL, los encabezados de solicitud, los argumentos de shell y los cuerpos JSON suelen contener tokens. Una biblioteca de registro que los captura «para depurar» acabará produciendo un archivo de incidente lleno de credenciales.
Esta estructura mantiene consultables los datos del destino sin copiar todo el contenido de la solicitud:
{
"target": {
"kind": "http",
"system_id": "release-service-prod",
"endpoint": {
"scheme": "https",
"host": "api.example.internal",
"port": 443,
"method": "POST",
"route_template": "/v1/releases/{release_id}/promote"
}
},
"operation": {
"name": "promote_release",
"request_fingerprint": "sha256:8e8c...",
"request_bytes": 286,
"redacted_parameters": {
"environment": "production",
"release_id": "rel_7b2"
}
}
}
La huella solo sirve si defines la canonicalización. Ordena los campos de los objetos, elimina los campos que excluya tu política de redacción, normaliza la codificación del texto y calcula después el hash de los bytes resultantes. Registra la versión de canonicalización. De lo contrario, dos solicitudes equivalentes pueden producir resúmenes sin relación y un cambio futuro del esquema puede hacer que los registros antiguos parezcan sospechosos.
Un resumen no sustituye las pruebas conservadas cuando un regulador, un contrato o un proceso de incidentes exige la solicitud original. En ese caso, cifra las pruebas por separado, limita el acceso y guarda su resumen de contenido en el registro de acciones. No pongas el cuerpo original en el diario normal y consultable solo porque el almacenamiento sea barato.
La operación solicitada y el resultado observado necesitan campos distintos
Una solicitud del agente expresa una intención. El resultado informa de lo que observó la puerta de enlace después de intentar ejecutar esa intención. No los mezcles en un estado impreciso como completed.
En una llamada de red, registra la fase del transporte en la que se detuvo la ejecución, el estado del protocolo cuando exista, un resumen limitado de la respuesta y el tiempo empleado. En SSH, registra el resultado de la conexión, el resultado de la autenticación, el código de salida remoto y resúmenes limitados de la salida estándar y de error. Un destino puede aceptar una solicitud y realizar después un trabajo asíncrono, por lo que una respuesta 202 no significa que el cambio externo haya ocurrido.
Usa un vocabulario de resultados que indique dónde ocurrió el fallo. Por ejemplo:
denied_vault_lockedsignifica que el límite local de secretos rechazó la llamada.denied_approvalsignifica que la decisión humana requerida no la autorizó.network_errorsignifica que la puerta de enlace no pudo establecer o mantener una conexión.target_rejectedsignifica que el servicio remoto devolvió un rechazo.target_acceptedsignifica que el servicio remoto aceptó la solicitud.
Mantén el error de transporte sin procesar fuera del campo de estado principal. Coloca un código normalizado como dns_lookup_failed o tls_validation_failed junto a un diagnóstico breve y redactado. Los ingenieros necesitan agregación; quienes responden a incidentes necesitan suficiente contexto local para distinguir un certificado caducado de un nombre de host bloqueado.
Un objeto de resultado completo podría tener este aspecto:
{
"result": {
"outcome": "target_accepted",
"started_at": "2025-02-18T21:19:42.184Z",
"finished_at": "2025-02-18T21:19:43.021Z",
"duration_ms": 837,
"http_status": 202,
"response_fingerprint": "sha256:2a64...",
"response_summary": "promotion job accepted",
"evidence_ref": null
}
}
Evita llamar éxito a target_accepted en tu esquema. Esa palabra causa problemas más adelante. Si el servicio acepta un trabajo y el trabajo falla, la puerta de enlace hizo exactamente lo que debía, pero la operación empresarial no terminó. Un evento remoto de finalización separado, relacionado mediante un ID de trabajo, puede responder después a esa pregunta.
Los registros de aprobación deben indicar qué aprobó la persona
Un registro de aprobación necesita una decisión, un alcance, un sujeto y marcas de tiempo. «El usuario aprobó al agente» dice demasiado poco. Los revisores deben adivinar si la persona autorizó una llamada de API, una credencial concreta, una sesión o todas las sesiones futuras de un proceso con un nombre parecido.
Una aprobación de sesión suele permitir llamadas de un proceso identificado hasta que ese proceso termine o alguien lo revoque. Una aprobación por llamada se aplica a un único uso de una credencial u operación. Registra el alcance directamente, porque ambos controles producen riesgos muy distintos.
{
"approval": {
"approval_id": "apr_01J8Q1P4Y5D6",
"decision": "approved",
"scope": "session",
"subject_session_id": "ses_01J8Q1F9K9Z3",
"approved_at": "2025-02-18T21:14:11Z",
"expires_at": "2025-02-18T22:02:53Z",
"approver_presence": "local_user_confirmation"
}
}
No afirmes más certeza de la que tu interfaz puede proporcionar. Si la aplicación recibe un evento de confirmación local, registra ese hecho. No registres el nombre de una persona, su cuenta del proveedor de identidad ni el método biométrico a menos que el sistema autentique realmente y conserve esa asociación según una política documentada. Inventar detalles de identidad crea una confianza falsa y obligaciones de privacidad.
Guarda la aprobación que gobernó una acción como identificador en el registro de la acción. Guarda también la decisión de autorización que ocurrió inmediatamente antes de la ejecución. Parece repetitivo hasta que investigas un caso límite de sincronización: puede existir una aprobación antigua de sesión, pero un requisito por llamada puede denegar la acción. La acción necesita ambos datos.
La fatiga de aprobación es un defecto de diseño, no una razón para omitir las pruebas de aprobación. Si una persona debe aprobar cada solicitud inofensiva, acabará aprobando sin leer. Reserva la confirmación por llamada para credenciales u operaciones cuyo uso indebido requiera atención directa, y haz que el registro explique por qué la puerta de enlace la solicitó.
La revocación es un evento con una hora de corte
La revocación termina la autoridad hacia el futuro. No borra una sesión, retira una solicitud ya entregada ni cambia la decisión de aprobación que existía cinco minutos antes.
Registra el objetivo de la revocación, el tipo de iniciador, la hora observada y el resultado de la aplicación. Si la puerta de enlace puede terminar o bloquear una sesión activa, registra si lo hizo. Si una acción ya cruzó el límite de red, indica que la revocación no puede retirarla. Los ingenieros necesitan ese hecho desagradable durante la respuesta, no una etiqueta tranquilizadora pero falsa de revoked.
Considera esta secuencia de fallo:
- Un proceso de agente recibe una aprobación de sesión a las 09:00 y envía un cambio de producción a las 09:17.
- El operador detecta un destino inesperado y revoca la sesión a las 09:18:04.
- El destino responde a la solicitud de las 09:17 a las 09:18:07 porque ya había puesto el trabajo en cola.
- El agente intenta otra llamada a las 09:18:09 y la puerta de enlace la deniega.
Un buen diario conserva los cuatro eventos. La acción de las 09:17 estaba autorizada cuando comenzó. La respuesta posterior a la revocación pertenece a esa acción anterior. El intento denegado demuestra que la revocación surtió efecto para el trabajo posterior. Si marcas todas las acciones anteriores como «revocadas», pierdes la secuencia que explica la exposición real.
Usa un número de secuencia monótono además de la hora de reloj. Los relojes pueden desviarse, los usuarios pueden cambiar la hora local y varios eventos pueden compartir la misma resolución temporal. Un número de secuencia establece el orden en el que el diario aceptó los registros. Si operas entre varios hosts, conserva la secuencia local de cada uno y usa ID de correlación en lugar de fingir que los relojes establecen un orden global perfecto.
La evidencia de manipulación depende de una disciplina de solo anexado
Una cadena de hashes dificulta las ediciones no detectadas al incluir el resumen del registro anterior en cada registro nuevo. No convierte un archivo de registro normal en una prueba de que existan todos los eventos esperados. Alguien que controle al escritor y la cabeza de cadena almacenada puede eliminar un sufijo, iniciar una cadena nueva o impedir que los registros lleguen a un almacenamiento duradero.
Esa limitación no vuelve inútiles las cadenas de hashes. Responden a una pregunta más concreta y útil: ¿cambiaron estos registros, desaparecieron elementos del centro o llegaron en un orden distinto después de que el sistema los escribiera? Mantén explícitos los campos de la cadena.
{
"journal": {
"sequence": 1842,
"recorded_at": "2025-02-18T21:19:43.024Z",
"previous_hash": "sha256:68b1...",
"record_hash": "sha256:93f4...",
"hash_format": "canonical-json-v1"
}
}
Calcula el hash del registro canónico completo, excluyendo únicamente record_hash. No calcules el hash de una representación con formato cuyo espacio en blanco, orden de campos o formato de marca de tiempo cambie entre versiones. Versiona el formato canónico y conserva el verificador para cada formato que emitas.
La Publicación especial 800-92 del NIST, Guide to Computer Security Log Management, trata la generación, el almacenamiento, el análisis y la conservación de registros como responsabilidades separadas. Esa distinción aclara un error frecuente: los equipos añaden un hash a las entradas y dan por terminado el trabajo. También necesitas almacenamiento duradero, controles de acceso alrededor del escritor, una decisión de conservación, verificaciones periódicas y un procedimiento de investigación para un control fallido.
Sallyport proyecta sus diarios Sessions y Activity desde un único registro de auditoría cifrado, encadenado mediante hashes y protegido contra escritura. Su comando sp audit verify verifica la cadena sin conexión sobre el texto cifrado, sin necesitar una clave del almacén. Ese diseño separa la capacidad de un lector para comprobar la integridad del diario de su capacidad para usar credenciales.
Un único ID de correlación hace que el registro sea útil bajo presión
Asigna a cada acción solicitada un ID de acción antes de que la puerta de enlace evalúe la autorización. Llévalo a través de la decisión local, el intento de red, el procesamiento de la respuesta y cualquier callback posterior de finalización remota. Cuando un ingeniero vea un despliegue discutido, debería buscar un único identificador y recuperar toda la línea temporal.
Usa ID relacionados para relaciones distintas. La acción apunta a su sesión, aprobación, referencia de credencial, destino y secuencia del diario. Una referencia a una tarea o conversación puede apuntar desde la acción al contexto del agente, pero no conviertas la transcripción de la conversación en la fuente de verdad. El texto de las instrucciones cambia, puede contener material privado y a menudo no describe con precisión la solicitud final.
Un registro completo y compacto puede adoptar esta forma:
{
"schema_version": "1.0",
"action_id": "act_01J8Q2ABR8M7",
"event_type": "action.completed",
"actor": {"session_id": "ses_01J8Q1F9K9Z3", "pid": 48217},
"target": {"kind": "http", "system_id": "release-service-prod"},
"operation": {"name": "promote_release", "request_fingerprint": "sha256:8e8c..."},
"authorization": {"vault": "unlocked", "approval_id": "apr_01J8Q1P4Y5D6", "decision": "approved"},
"result": {"outcome": "target_accepted", "http_status": 202},
"journal": {"sequence": 1842, "previous_hash": "sha256:68b1..."}
}
No uses el ID de correlación como token de autorización. Genéralo de forma independiente, hazlo impredecible cuando las personas externas puedan verlo y nunca aceptes que poseer el ID sea permiso para leer una acción o emitir una llamada posterior.
La conservación debe mantener las pruebas sin crear otro almacén de secretos
Los datos de auditoría acumulan material privado incluso cuando redactas de forma rigurosa. Los nombres de destino pueden revelar clientes, los parámetros de ruta pueden revelar proyectos internos, los resúmenes de respuesta pueden exponer el estado de una cuenta y las rutas de procesos pueden mostrar hábitos de los desarrolladores. Decide quién puede buscar registros, quién puede exportarlos y cuánto tiempo permanece disponible cada categoría.
Mantén los metadatos de acciones consultables separados de cualquier prueba cifrada de solicitud o respuesta. Aplica una conservación más breve a las pruebas detalladas cuando deje de ser necesaria la investigación. Conserva los hashes y los registros de relación el tiempo suficiente para demostrar que los resúmenes restantes siguen correspondiendo a lo que registró el sistema.
Pon a prueba el modelo con una pregunta real de una revisión de incidentes: «¿Qué proceso firmado solicitó acceso a este destino de producción, bajo qué aprobación y continuó algún intento después de la revocación?». Si una consulta obliga al analista a unir mensajes sin estructura, inspeccionar registros de depuración del cliente o preguntar al agente qué recuerda, el modelo está incompleto.
La escalera fija de decisiones de Sallyport establece límites claros para este modelo de registro: la puerta del almacén, la autorización de sesión y la aprobación de credenciales por llamada producen cada una un dato de autorización distinto. Mantén esos datos separados en tu propio diseño de auditoría. El registro debe mostrar dónde se detuvo la autoridad, en lugar de ocultar cada denegación bajo un código de fallo genérico.
Construye el esquema antes de que los agentes obtengan credenciales amplias. Adaptar después de un incidente la identidad del actor, el alcance de la aprobación y el orden de las revocaciones implica reconstruir la autoridad a partir de las lagunas. Es un trabajo lento y normalmente termina con alguien diciendo «creemos» cuando el registro debería haber indicado exactamente qué ocurrió.
FAQ
¿Cuál es la diferencia entre un registro de sesión de agente y un registro de auditoría de acciones?
Un registro de sesión indica que un proceso existió durante cierto periodo. Un registro de auditoría de acciones indica qué pidió hacer ese proceso, qué destino recibió la solicitud, qué límite de credenciales se aplicó, si una persona lo aprobó y qué ocurrió. Necesitas ambos porque una sesión revocada puede haber realizado muchas llamadas antes de la revocación.
¿Un registro de auditoría debe guardar solo las acciones exitosas de los agentes?
No. Un estado HTTP satisfactorio solo describe la respuesta visible para quien llama. Registra el resultado del transporte, el código de estado, un resumen limitado de la respuesta y cualquier error de ejecución detectado localmente para que el investigador pueda distinguir entre un rechazo, un tiempo de espera y un cambio remoto completado.
¿Cómo identifico un sistema de destino sin registrar secretos?
Usa un identificador interno estable del sistema de destino y una descripción redactada, como un host de API y una plantilla de ruta, o un alias de host SSH y una clase de comando. No guardes por defecto credenciales sin procesar, encabezados de autorización, tokens en URL ni cuerpos completos de solicitudes. Un registro que copia secretos ha fracasado en su propio objetivo de seguridad.
¿Por qué debe aparecer la autoridad de firma de código en un registro de auditoría de agentes?
Registra la ruta del ejecutable, el ID del proceso, el ID del proceso principal cuando esté disponible, la hora de inicio y la autoridad de firma de código. La autoridad de firma responde a una pregunta distinta del nombre del proceso: ayuda a distinguir un binario esperado de un programa ajeno que usa una etiqueta conocida.
¿Cómo registro la aprobación de una sesión frente a la aprobación de una acción?
Una aprobación puede cubrir una sesión de proceso, mientras que otra puede cubrir un único uso de una credencial sensible. El registro debe indicar el alcance de la aprobación y su decisión. Sin ese alcance, los revisores suelen suponer que una aprobación anterior autorizó una llamada posterior de alto impacto, aunque no fuera así.
¿La revocación debe sobrescribir las acciones aprobadas anteriormente?
Conserva inmutables los registros de acciones originales y añade un evento de revocación que indique la sesión o autorización que terminó. No reescribas los registros anteriores para decir que después dejaron de estar autorizados. El orden temporal muestra exactamente qué llamadas ocurrieron antes de que la revocación surtiera efecto.
¿Un registro de auditoría encadenado mediante hashes puede demostrar que una acción de agente fue segura?
Una cadena de hashes detecta eliminaciones, inserciones o modificaciones cuando conservas el estado esperado de la cadena y verificas la secuencia. No determina si una acción aprobada fue prudente ni puede demostrar que un sistema remoto cumplió una solicitud. Combínala con registros precisos y, cuando sea necesario, con los registros del sistema remoto.
¿Qué debo registrar de las solicitudes HTTP realizadas por agentes de IA?
Empieza con una huella de la solicitud, no con el cuerpo sin procesar. Guarda el método, la plantilla de ruta, los parámetros no secretos seleccionados, el tamaño del cuerpo y un resumen criptográfico de una representación canónica redactada. Conserva las pruebas cifradas por separado solo cuando la investigación y las reglas de conservación lo justifiquen.
¿Qué debe incluir un registro de auditoría de acciones SSH?
Captura el destino SSH, la huella de la clave del host o una referencia a la entrada de hosts conocidos, la etiqueta de la cuenta remota si no es secreta, la clase de comando y resúmenes limitados de stdout y stderr. Trata la línea de comando completa como información sensible porque suele contener rutas, identificadores y tokens accidentales.
¿Qué preguntas debe responder un registro de auditoría de acciones de agentes?
Quien investigue un incidente debería poder reconstruir quién inició el actor, qué solicitó, qué aprobación lo autorizó, qué destino recibió la solicitud, qué resultado devolvió y si la revocación cambió la autoridad del proceso. Si un registro no puede responder una de esas preguntas, añade un campo o un evento asociado.