
Rastros de auditoría a prueba de manipulaciones para agentes de IA: Runtime Records encadenados por hash, sin dependencias, verificables por cualquiera.
Registros de ejecución para agentes de IA a prueba de manipulaciones: la pista de auditoría que el proveedor ejecuta pero no puede editar.
Cada acción que realiza tu agente (llamadas a herramientas, llamadas al modelo, acceso a datos, aprobaciones) se convierte en un registro dentro de un log de solo añadidura y encadenado por hashes. Cualquier parte que tenga un punto de control de la cadena puede verificar que los registros detrás de ella nunca fueron alterados, sin tener que confiar en quien los produjo. Cuando el equipo de seguridad de un cliente pregunta «¿qué hizo tu agente con nuestros datos?», le entregas un enlace en lugar de un párrafo. Las revisiones de seguridad ya formulan preguntas sobre IA junto al checklist de SOC 2, y hoy en día una garantía por escrito todavía es aceptada. La apuesta detrás de este proyecto es que eso no durará mucho.
El formato de registro es abierto y libre de implementar. Este paquete es la implementación de referencia: registrador, verificador, cliente de testigo y servidor de informes.
Se te pide que pongas un registrador dentro de tu agente. No deberías aceptar eso por fe:
pip install halo-record instala exactamente un paquete.No se requiere ningún agente. Con uv, no hay nada que instalar:
uvx --from halo-record halo demo --serve
o de la forma clásica:
pip install halo-record
halo demo --serve
Cualquiera de las dos prepara un proveedor ficticio de agente de soporte con dos clientes, atestigua las cadenas, sirve sus Runtime Reports con acceso restringido y abre la consola del operador en tu navegador. Luego prueba el test de manipulación: elimina una línea de uno de los archivos .jsonl y recarga. El informe lo detecta.
Una línea en el límite:
from halo import trace
agent = trace(run_my_agent, profile="my-agent", log="audit.jsonl") # wraps your entrypoint; records every tool call to ./audit.jsonl
Sin log=, los registros van a ~/.halo/my-agent.jsonl (una cadena por agente). O usa el adaptador para lo que ya ejecutas (ver la matriz de abajo). Luego renderiza el informe:
halo report audit.jsonl -o report.html # one chain -> self-verifying HTML
halo serve ./records --port 8721 # all tenants, gated per customer
El inicio rápido termina cuando estás viendo el Runtime Report de tu propio agente en un navegador. Si obtuviste un archivo JSONL y ningún informe, algo está mal: abre un issue.
| Capturado en el límite |
|---|
Cada registro lleva una etiqueta source, por lo que el informe revela cómo se recopiló cada pieza de evidencia. Los registros capturados e ingeridos viven en la misma cadena.
Cualquier cosa que emita spans GenAI de OpenTelemetry (CrewAI, LlamaIndex y la mayoría de los frameworks de agentes con instrumentación OTel) llega a la cadena a través del adaptador OTel, y el paquete TypeScript incluye adaptadores nativos para el SDK de Vercel AI y el ecosistema de agentes JS. ¿Te falta un adaptador para tu stack? Abre un issue. La mayoría de los adaptadores tienen alrededor de cien líneas.
Claude Code dispara un hook PostToolUse después de cada llamada a herramienta. Apúntalo a halo hook y cada acción — escrituras de archivos, comandos de shell, llamadas al conector MCP — se convierte en un registro en una cadena local. Sin cambios de código; solo una entrada de configuración:
{
"hooks": {
"PostToolUse": [
{"matcher": "*", "hooks": [{"type": "command", "command": "halo hook"}]}
]
}
}
Añade eso a ~/.claude/settings.json y los registros se guardan en ~/.halo/audit.jsonl (sobrescribible con $HALO_LOG). Las herramientas de orquestación pura que no tocan datos, red ni estado externo se omiten: la cadena registra acciones en el límite de confianza, no pensamientos. Establece HALO_HASH_ONLY=1 para registrar hashes de contenido sin resúmenes. Establece HALO_AGENT_VERSION (y opcionalmente HALO_AGENT_MODEL) para vincular cada registro a la compilación del agente que lo produjo: cuando un auditor pregunta por la versión que estaba en ejecución en un período determinado, la exportación responde por columna en lugar de por recuerdo.
Si necesitas que el informe responda «¿bajo qué reglas ocurrió esta ejecución?», establece HALO_AUTHORITY_FILE a una instantánea JSON de la autoridad efectiva para la sesión. Mantenla segura en términos de privacidad: hashes y referencias, no prompts brutos, texto de políticas privadas, secretos ni esquemas completos de herramientas.
{
"snapshot_id": "auth_2026_07_08T1100Z",
"captured_at": "2026-07-08T11:00:00Z",
"scope": "session",
"workspace": {"path_hash": "sha256:...", "git_commit": "abc1234"},
"refs": [
{"kind": "project_rules", "id": "CLAUDE.md", "hash": "sha256:...", "loaded": true, "truncated": false},
{"kind": "mcp_tool_registry", "id": "filesystem", "hash": "sha256:..."}
],
"omissions": [{"kind": "private_policy", "reason": "customer_secret", "hash": "sha256:..."}],
"stale_if": ["project_rules_hash_changed", "mcp_tool_registry_hash_changed"]
}
HALO_AUTHORITY_FILE=./authority.json halo hook
La instantánea se sella en la misma cadena de hashes que los registros de acciones. Un buen valor predeterminado es una instantánea a nivel de sesión al inicio, más una nueva instantánea cuando cambian las reglas, Skills, hooks, registros de herramientas MCP o la política de compactación. Para mantener las sesiones largas ligeras, los registros consecutivos con el mismo authority.snapshot_id se compactan después de la primera instantánea completa: los registros posteriores conservan solo {"snapshot_id": "...", "same_as_previous": true}. El puntero permanece encadenado por hash, pero el bloque voluminoso de refs/omissions/stale-if no se repite en cada acción. Luego, lo habitual:
halo verify ~/.halo/audit.jsonl
halo report ~/.halo/audit.jsonl -o report.html
Cualquier runtime de agente que exponga un hook posterior a la acción puede alimentar el mismo comando: el hook lee un evento como JSON desde stdin y añade un registro.
Sé preciso sobre lo que demuestra cada capa — porque son afirmaciones diferentes, y las diferencias son el punto:
Una cadena en manos propias demuestra integridad relativa a una cabeza establecida: dada una cabeza de cadena que alguien ya posee, cualquier edición, reordenamiento o eliminación en los registros que la preceden se vuelve detectable. Por sí sola — antes de que alguien fuera del operador haya visto una cabeza — una cadena demuestra consistencia interna, no historia: un operador podría eliminar un registro y volver a sellar, y el nuevo archivo verificaría. La cadena se vuelve históricamente comprometida en el momento en que su cabeza sale del control del operador.
Ese es el testigo: una parte externa al operador que mantiene huellas periódicas de la cadena (un recuento y un hash de cabeza, nada más). Los puntos de control hacen detectable la reescritura de la historia comprometida, y un punto de control omitido es en sí mismo un evento visible:
halo anchor audit.jsonl witness.jsonl # anchor a checkpoint to a local witness
halo anchor audit.jsonl witness.jsonl --check # completeness verdict against it
Un límite más, dicho claramente: ni la cadena ni el testigo demuestran que toda acción del mundo real pasó por el registrador. Eso es completitud de captura — una propiedad de dónde se sitúa el registrador en el stack (instrumentación nativa, hooks, ingesta por gateway), no de ningún hash. Los registros llevan una etiqueta source precisamente por esta razón.
Cualquiera puede ejecutar un testigo. Un testigo que ejecutas tú mismo compromete la historia ante ti; comprometerla ante tu cliente requiere un testigo en el que tengan razones para confiar. El protocolo está abierto de cualquier manera.
Un testigo alojado y reconocido es cómo este proyecto se sostendrá. Acceso anticipado: [email protected].
halo-record es una capa de evidencia, no una certificación. Produce el artefacto que los marcos de evaluación siguen pidiendo con otras palabras:
AARM.md.ATC.md.Nada de esto certifica nada por sí mismo. Le da a tu evaluador algo verificable que examinar. Los límites — lo que halo-record deliberadamente no hace y qué decir cuando un revisor pregunta — están documentados en LIMITS.md.
halo verify validate schema + hash chain (non-zero exit on failure; CI-friendly)
halo report render a chain as a self-verifying HTML Runtime Report
(--from/--to: a date-windowed report covering only the review period)
halo serve serve per-tenant reports over HTTP, access-scoped per customer
halo grant designate a report recipient (email or domain)
halo anchor witness a chain head, or --check completeness
halo demo scaffold the full vendor demo (record -> witness -> gated report)
halo export date-bounded evidence export: CSV + manifest tied to the chain head
halo sample emit a valid example log
halo hash canonical sha256 of a JSON value
halo hook Claude Code PostToolUse hook
Para calcular el hash de un registro: toma el registro excluyendo integrity.hash, con integrity.prev_hash establecido al hash del registro anterior; canoniza con RFC 8785 (JSON Canonicalization Scheme); aplica SHA-256 a los bytes. El prev_hash del primer registro son 64 ceros. La verificación recalcula cada hash y comprueba cada enlace. No se requiere ningún secreto; ese es el punto.
¿Crees que puedes manipular una cadena sin que el verificador lo note? Los intentos y resultados viven aquí.
Referencia completa de campos: halo-record.schema.json.
El mismo registrador está disponible para Node: halo-record-ts. Mismo formato de cadena, mismo protocolo de testigos. Los registros escritos en cualquiera de los dos lenguajes se verifican con cualquiera de los dos verificadores.
Son bienvenidos issues, discusiones y pull requests — consulta CONTRIBUTING.md para las reglas básicas (versión corta: pruebas requeridas, PRs pequeños, los cambios de esquema se discuten primero).
Apache-2.0
| Ingerido desde telemetría existente |
|---|
Registrador nativo (from halo import trace) | Spans GenAI de OpenTelemetry |
| Interceptor MCP | Callbacks de LiteLLM |
| Callback de LangChain / LangGraph | Exportación de Langfuse |
| Hooks del SDK de OpenAI Agents | Cualquier log de gateway / proxy inverso |
| Hook de Claude Code / Claude Agent SDK |
| Afirmación | Cadena en manos propias | + Puntos de control externos | + Captura confiable |
|---|
| Detectar ediciones en un artefacto establecido | ✔ | ✔ | ✔ |
| Detectar reescritura de historia comprometida | — | ✔ | ✔ |
| Detectar puntos de control faltantes/atrasados | — | ✔ (cadencia acordada) | ✔ |
| Demostrar que toda acción fue registrada | — | — | depende del límite de captura |