
halo-record v0.2.8
Rastros de auditoría a prueba de manipulaciones para agentes de IA: Runtime Records encadenados por hash, sin dependencias, verificables por cualquiera.
halo-record
Rastros de auditoría a prueba de manipulación para agentes de IA — Runtime Records encadenados por hash, renderizados como un Runtime Report que tus clientes pueden verificar por sí mismos.
Cada acción que realiza tu agente (llamadas a herramientas, llamadas a modelos, acceso a datos, aprobaciones) se convierte en un Runtime Record en un registro de solo anexado, encadenado por hash; el Runtime Report es esa cadena renderizada como una página HTML autoverificable. Cualquier parte que posea un checkpoint de la cadena puede verificar que los registros detrás de él nunca fueron alterados, sin confiar en quien los produjo — ese checkpoint es la pieza fundamental: la cadena por sí sola es a prueba de manipulación frente a todos excepto la parte que opera el grabador (LIMITS.md §1). Cuando el equipo de seguridad de un cliente pregunta "¿qué hizo tu agente con nuestros datos?", les entregas un enlace en lugar de un párrafo. Las revisiones de seguridad ya hacen preguntas sobre IA junto a la lista de verificación de SOC 2 — y cada vez más esas preguntas provienen de ISO 42001, los artículos de mantenimiento de registros del Reglamento de IA de la UE y los propios cuestionarios de los clientes. Hoy una garantía por escrito todavía pasa. La apuesta detrás de este proyecto es que no lo hará por mucho tiempo.
Destacado en Help Net Security (agosto de 2026).
El formato de registro es abierto y libre de implementar. Este paquete es la implementación de referencia: grabador, verificador, cliente testigo y servidor de informes.
¿Usas halo-record, o lo estás considerando? Cuéntame quién eres y para qué → ¿Quién usa halo-record?
Compruébalo tú mismo
Se te está pidiendo que pongas un grabador dentro de tu agente. No deberías aceptarlo por fe:
- Cero dependencias en tiempo de ejecución. Solo biblioteca estándar.
pip install halo-recordinstala exactamente un paquete. - Sin llamadas de red, excepto tres opcionales — anclaje a un testigo (envía el id del sujeto, un recuento de registros y dos huellas de la cadena — la cabeza y la raíz de la cadena), lectura de los checkpoints de un testigo (envía el id del sujeto), y la marca de tiempo RFC 3161 (envía solo el hash de estado de un checkpoint a una Autoridad de Sellado de Tiempo). Todas están desactivadas a menos que las invoques; el contenido de los registros nunca sale de tu infraestructura.
- Los argumentos de herramientas sin procesar se hashean, con un resumen redactado junto a ellos. Los argumentos se almacenan como un hash canónico más un resumen: el texto del argumento con patrones conocidos de secretos y PII enmascarados, limitado a 200 caracteres. Una entrada corta que no coincide con ningún patrón aparece completa en el resumen; el modo solo hash (
summaries=False) no conserva ningún resumen. La redacción es de mejor esfuerzo (regex sobre formatos comunes de secretos y PII más una captura general por entropía): trátala como defensa en profundidad, no como una garantía. Los campos de resultado que proporciones más allá desummaryse sellan tal cual (LIMITS §13). - Suficientemente pequeño para auditar. ~5.300 líneas de Python (líneas de código, sin contar líneas en blanco ni comentarios). Léelo todo en una tarde.
- Apache-2.0.
- La documentación es de primera clase. LIMITS.md (lo que la cadena no puede probar), PRIVACY.md (qué contienen los registros y qué sale de tu máquina), RETENTION.md (operar bajo una política de retención), y REVIEWERS.md — la verificación independiente de cuatro comandos más un formato de cita para hallazgos de revisión.
Lo que prueba cada capa — la distinción fundamental en este proyecto (LIMITS.md §1): una cadena que tú mismo posees prueba que los registros no fueron editados, en relación con una cabeza que alguien ya posee; solo los checkpoints mantenidos fuera del operador prueban que ninguno fue eliminado; y ningún hash prueba que cada acción fue capturada.
| Afirmación | Cadena propia | + Checkpoints externos | + Captura confiable |
|---|---|---|---|
| Detectar ediciones a un artefacto establecido | ✔ | ✔ | ✔ |
| Detectar la reescritura de historial confirmado | — | ✔ | ✔ |
| Detectar checkpoints faltantes/tardíos | — | ✔ (cadencia acordada) | ✔ |
| Probar que cada acción fue registrada | — | — | depende del límite de captura |
Ve uno antes de instalar: un Runtime Report de ejemplo — datos ficticios, cadena real, y se reverifica a sí mismo en tu navegador mientras observas.
Demo de 60 segundos
No se requiere agente. Con uv, 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 los dos crea un proveedor ficticio de agentes de soporte con dos clientes, es testigo de las cadenas (con un archivo de testigo local que representa a uno fuera del operador — véase LIMITS.md §1), sirve sus Runtime Reports restringidos y abre la consola del operador en tu navegador. Luego prueba la prueba de manipulación: elimina una línea de uno de los archivos .jsonl y recarga. El informe lo detecta.
Registra tu propio agente
Una línea en el límite:```python from halo_record import trace
agent = trace(run_my_agent, profile="my-agent", log="audit.jsonl") # wraps your entrypoint; records the run boundary to ./audit.jsonl — add record_call() or a framework adapter at each tool boundary to capture individual calls
Un shim de conveniencia `from halo import ...` también se incluye — pero el nombre `halo` en PyPI pertenece a un paquete de spinner de terminal no relacionado, y si ese paquete está instalado, gana la importación. `halo_record` no es ambiguo, por lo que los ejemplos lo usan.
Sin `log=`, los registros van a `~/.halo/my-agent.jsonl` (una cadena por agente). El wrapper sella el límite de la ejecución; la evidencia vive en los registros por llamada. Captúralos con un adaptador de framework (matriz a continuación) — o explícitamente, lo que también muestra cómo se enlazan las delegaciones:```python
from halo_record import Recorder, record_call
rec = Recorder("audit.jsonl")
with record_call(rec, "crm.lookup", {"account": "acct-9"}) as call: # one sealed record per tool call
call.result = crm.lookup("acct-9")
with record_call(rec, "payments.refund", {"amount": 120},
parent_id=rec.last_record_id()) as call: # child links to the action that spawned it
call.result = payments.refund(120)
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.
### El bloque de verificación
Si una capa de guardrail o de políticas verificó la acción, su veredicto puede viajar en el registro — un bloque opcional que registra lo que decidió la puerta, sellado en la cadena de hashes como cualquier otro campo:```python
from halo_record import build