Files
egutierrez bd0c8c0dd3 refactor: mover runtime Go de agents/ a devagents/
agents/ ahora solo contiene carpetas de agentes (config, reglas, prompts).
El runtime (Agent, Robot, Runner, registry, handler, commands, llm, memory)
vive en devagents/ como package devagents.

Cambios:
- git mv agents/*.go → devagents/*.go
- package agents → package devagents en todos los archivos movidos
- Actualizar imports en agents/*/agent.go, cmd/launcher/, dev-scripts/
- Actualizar docs: CLAUDE.md, rules/, docs/e2ee.md, issues pendientes

Build y tests pasan sin errores.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 21:19:25 +00:00

4.7 KiB

E2EE (End-to-End Encryption) en agents_and_robots

Resumen

Los bots Matrix usan E2EE via mautrix-go + cryptohelper para comunicarse de forma cifrada. La implementación usa Olm puro en Go (-tags goolm, sin CGO).

Arquitectura

config.yaml (encryption section)
    ↓
devagents/runtime.go → Agent.New() llama a InitCrypto()
    ↓
shell/matrix/client.go → InitCrypto() configura cryptohelper
    ↓
crypto.db (SQLite) — estado persistente de claves
    ↓
mautrix sync loop → cifrado/descifrado transparente

Qué guarda la crypto store (crypto.db)

Dato Qué es Cuándo se crea Cuándo rota
Olm Account Par de claves Curve25519 del dispositivo Al primer Init() Nunca — es la identidad del dispositivo
One-time keys Claves efímeras para sesiones 1:1 Al Init() y cuando se agotan Automáticamente cuando hay < 50% disponibles
Megolm sessions Claves de grupo para rooms Al unirse a un room E2EE Cada ~100 mensajes o ~1 semana
Device list cache Claves públicas de otros dispositivos Al hacer sync Se actualiza con cada sync
Cross-signing keys Master, self-signing, user-signing Al ejecutar cmd/verify Manualmente

Pickle key

El pickle key cifra el material criptográfico en la SQLite. Se configura por agente en .env:

PICKLE_KEY_ASSISTANT_BOT=<hex random 32 bytes>

Y se referencia en config.yaml:

encryption:
  enabled: true
  store_path: "./agents/assistant-bot/data/crypto/"
  pickle_key: "${PICKLE_KEY_ASSISTANT_BOT}"
  trust_mode: tofu

Generar un pickle key

openssl rand -hex 32

Por qué NO derivar del access token

Si el token cambia (re-registro, nuevo login), el pickle key cambia y la DB existente se vuelve ilegible. Esto causa el error:

olm account is not marked as shared, but there are keys on the server

Un pickle key fijo por agente en .env evita este problema.

Crypto store por agente

Cada agente debe tener su propia crypto.db para evitar corrupción cruzada:

agents/assistant-bot/data/crypto/crypto.db
agents/asistente-2/data/crypto/crypto.db

No compartir la crypto store entre agentes.

Auto-recovery

Si cryptohelper.Init() falla por inconsistencia (ej: "not marked as shared"), el runtime borra automáticamente la crypto.db y reintenta. Esto regenera las claves Olm y requiere re-verificar cross-signing.

Cross-signing y verificación

Elimina warnings de "Encrypted by a device not verified by its owner".

go run -tags goolm ./cmd/verify \
    --homeserver https://matrix-af2f3d.organic-machine.com \
    --username <bot-id> \
    --password <password> \
    --token <access_token>

Esto genera y sube cross-signing keys al servidor. Si las claves ya existen, firma el dispositivo actual con la clave existente.

Trust mode

Configurado en config.yaml como trust_mode:

  • tofu (Trust-on-First-Use): confía en un dispositivo la primera vez que lo ve. Cambios posteriores generan warnings.
  • cross-signing: requiere verificación explícita (no implementado aún).
  • manual: cada dispositivo debe verificarse manualmente (no implementado aún).

Build

Siempre compilar con -tags goolm:

go build -tags goolm -o bin/launcher ./cmd/launcher

El driver SQLite se registra como "sqlite3" via modernc.org/sqlite en cmd/launcher/sqlite.go y cmd/verify/sqlite.go.

Troubleshooting

"olm account is not marked as shared, but there are keys on the server"

La crypto store local está desincronizada con el servidor.

Solución: El runtime intenta auto-recovery. Si falla manualmente:

rm agents/<id>/data/crypto/crypto.db
# Reiniciar el bot
# Re-verificar cross-signing

"database is locked (SQLITE_BUSY)"

Dos procesos están accediendo la misma crypto.db simultáneamente.

Solución: Asegurar que cada agente use su propia store_path y no corran múltiples instancias del mismo agente con E2EE habilitado sin coordinación.

"unable to decrypt message"

Las claves Megolm de la sesión se perdieron (DB borrada o corrupta).

Solución: Los mensajes cifrados antes del reset son irrecuperables. Los nuevos mensajes se descifrarán normalmente tras regenerar las claves.

Archivos clave

Archivo Propósito
devagents/runtime.go Inicializa E2EE por agente
shell/matrix/client.go InitCrypto() — setup de cryptohelper
cmd/verify/main.go Herramienta de cross-signing
cmd/launcher/sqlite.go Registro driver SQLite
internal/config/schema.go Schema de EncryptionCfg
agents/*/config.yaml Configuración E2EE por agente