bitácora · alethech

Memoria de agente verificable: firmas Ed25519, un DAG enlazado por hashes y rotación de claves que no puede borrar el pasado

2026-10-18 · Edison Flores (AliceLabs) · alethech.alicelabs.site ↩

01El problema: la memoria de un agente es una caja negra

Un agente LLM que trabaja durante semanas acumula memoria: decisiones, credenciales de contexto, hallazgos de una investigación, el estado de un despliegue. Casi todas las soluciones actuales guardan esa memoria como texto o como resúmenes re-escritos por otro LLM. El resultado es que la memoria no tiene historia auditable: nadie puede responder tres preguntas básicas. ¿Quién escribió exactamente esta entrada y con qué clave? ¿Se modificó algo después de escribirla? ¿Y si la clave con la que se firmó quedó comprometida, cómo demuestro que lo escrito antes del compromiso sigue siendo auténtico?

El problema no es teórico. Un agente que opera con acceso a billeteras, despliegues o correos produce memoria que otras personas — y otros agentes — usan para decidir. Una memoria que puede mutar en silencio no es memoria: es un borrador. Y un borrador re-escrito por un LLM hereda todos los problemas de confianza del modelo que lo reescribió.

02Objetivos de diseño

alethech nace de cuatro restricciones, en este orden:

03El modelo: cada entrada es un commit firmado

La memoria es un archivo append-only donde cada entrada es un commit: un contenido arbitrario (JSON), metadatos de tipo, el hash del commit anterior, y una firma. Para que dos implementaciones en lenguajes distintos produzcan exactamente los mismos bytes antes de firmar, el objeto se canoniza con JCS (RFC 8785): serialización JSON canónica, sin ambigüedad de orden de claves ni de números. Sobre esos bytes se calcula el digest sha256 y se firma con Ed25519.

El resultado es un DAG enlazado por hashes: cada commit referencia a su padre, y la cabeza (head) es un resumen de todo el estado. Mutar cualquier entrada rompe todos los hashes posteriores; insertar una entrada falsa exige una firma válida de la clave, y modificar una firma vieja exige la clave vieja. La verificación recorre la cadena completa y devuelve un informe estructurado — no un booleano — con el estado de cada commit.

from alethech import Alethech

store = Alethech.open("memory.aleth")

store.commit(
    {"decision": "deploy v0.9.5", "env": "production",
     "approved_by": "release-checklist#12"},
    memory_type="decision",
)

report = store.verify()
print(report.errors)   # [] = cadena íntegra, todas las firmas válidas

Ese verify() comprueba, para cada commit: digest JCS correcto, firma Ed25519 válida respecto de la clave declarada, enlace al padre, y vigencia de la clave según la tabla de identidades del store.

04Rotación de claves sin romper la cadena — la parte difícil

Rotar la clave de firma es trivial si puedes re-firmar todo. El problema real es que re-firmar destruye el valor probatorio: si puedes re-firmar el pasado, el pasado no prueba nada. alethech lo resuelve con un evento de control: una rotación es un commit especial firmado por la clave saliente que declara la clave entrante y un cutoff_head — el punto exacto donde termina la era de la clave vieja.

La garantía de reachability es la contrapartida: un commit firmado con una clave ya revocada solo es válido si pertenece a la ancestría de cutoff_head. Cualquier commit "oscuro" — firmado con la clave revocada fuera de esa ancestría, por ejemplo algo inyectado después con la clave filtrada — es rechazado por verify() con not_in_proven_pre_rotation_history. Puedes rotar mil veces: cada era sigue verificando con la clave que le corresponde, y nada firmado fuera de su era pasa como histórico.

Las dos derrotas clásicas de esta garantía — mover la clave de revoked_keys a active_keys, o mutar cutoff_head para que apunte al propio commit oscuro — están implementadas como mutation guards con tests dedicados: el verificador detecta la inconsistencia entre la tabla de control y el estado declarado, no solo el valor puntual.

La rotación de la clave de firma es distinta de la rotación de la clave de cifrado. Esta última (rekey_aleth) re-envuelve la clave de datos (DEK) con una nueva KEK derivada por scrypt, sin tocar el contenido: cambiar tu frase no invalida la historia, y la historia sigue probando quién la escribió.

05Cifrado en reposo: scrypt + AES-256-GCM

El archivo de memoria se puede sellar (seal_v2) como .aleth: una KEK derivada de la frase con scrypt envuelve una DEK aleatoria, y el contenido se cifra con AES-256-GCM (autenticado: un byte alterado del contenedor falla la apertura, además de fallar la verificación de firmas). La combinación da dos capas independientes — confidencialidad ante robo del archivo, integridad ante manipulación de quien lo obtenga.

06El puente MCP: memoria verificable para cualquier cliente

El paquete incluye alethech-mcp, un puente solo lectura sobre stdio que expone el store verificado como servidor MCP. Cualquier cliente consciente del protocolo MCP puede inicializar y consultar dos herramientas: alethech_memory_context (contexto verificado, solo entradas íntegras) y alethech_memory_verify (informe de verificación completo). Sin SDK de MCP — JSON-RPC plano sobre stdio — y atado al archivo: el puente no acepta rutas arbitrarias, solo la memoria con la que se levantó.

{"jsonrpc":"2.0","id":1,"method":"initialize",
 "params":{"protocolVersion":"2024-11-05","capabilities":{},
           "clientInfo":{"name":"tu-cliente","version":"1.0"}}}

# → serverInfo: alethech-memory · protocol 2024-11-05
#   tools: alethech_memory_context, alethech_memory_verify

El bridge está publicado en el MCP Registry oficial como io.github.eddyflores100-lang/alethech, y el repo aparece en Awesome-Agent-Memory tras una auditoría del mantenedor contra el código — firmas, criptografía y CI incluidas.

07Qué NO resuelve (los límites)

Honestidad de protocolo: alethech garantiza integridad y autenticidad de la memoria, y esto es lo que garantiza — y lo que no.

08Verifícalo tú mismo

El núcleo es Python stdlib + cryptography, y todo el pipeline corre local:

pip install alethech          # núcleo + CLI
alethech init ./mi-memoria.aleth
alethech commit ./mi-memoria.aleth --type semantic --stdin
alethech verify ./mi-memoria.aleth

Implementaciones hermanas comparten el mismo formato sobre la marcha: TypeScript (alethech-ts), Rust (alethech-rs) y WASM para el navegador — todas canonizan con JCS, así que un commit escrito desde TypeScript verifica byte a byte desde Python.

Si este protocolo te sirve, el repo es github.com/eddyflores100-lang/alethech.

Una ★ en el repo es como otras personas — y sus agentes — encuentran el proyecto. El listado del que probablemente llegaste: Awesome-Agent-Memory.