28 de septiembre de 2026

hermes-memory-pgvector 1.0: una superficie de memoria estable

hermes-memory-pgvector 1.0: una superficie de memoria estable

hermes-memory-pgvector 1.0.0 está disponible. Es la primera versión en la que nos comprometemos a no romper las partes contra las que programas scripts. Esta entrada cubre qué es el plugin, qué garantiza la 1.0, qué descubrió la revisión previa al lanzamiento y cómo actualizar.

Qué es

hermes-memory-pgvector es un proveedor de memoria basado en Postgres + pgvector para hermes-agent. Es una capa de memoria compartida para una flota de agentes cooperantes, construida sobre una instancia de Postgres y un endpoint de embeddings que probablemente ya tengas en funcionamiento.

Las reglas de diseño no han cambiado desde la primera publicación:

  • Capa de almacenamiento, no un modelo de memoria. Los agentes siguen llamando a la herramienta memory integrada. El plugin replica esas escrituras en Postgres y almacena turnos de chat sustantivos para búsqueda semántica.
  • Sin LLM en el camino crítico de la memoria. Los embeddings son cálculo vectorial. No hay derivador, ni bucle dialéctico, ni ciclo de sueño.
  • Temas por agente por defecto. Cada fila lleva un agent_identity. La recuperación se mantiene dentro del tema actual a menos que el agente solicite scope='all'.
  • Degradación controlada. Si el endpoint de embeddings está caído, las escrituras degradan a solo texto. Si la cola de escritura está llena, la escritura se descarta con un único aviso. Si la base de datos está caída, el plugin registra el evento y continúa. Ninguna excepción llega al bucle del agente.
  • Separación entre administración y tiempo de ejecución. El DDL se ejecuta una vez como superusuario mediante hermes-pgvector migrate. El rol de tiempo de ejecución solo obtiene DML.

Qué significa la 1.0

A partir de la 1.0.0 el proyecto sigue versionado semántico en su superficie pública:

  • claves de configuración plugins.pgvector.*
  • nombres y parámetros de herramientas (recall_memory, recall_conversation)
  • comandos, flags y códigos de salida de la CLI
  • nombres de tablas y columnas de la base de datos
  • el nombre de proveedor pgvector y el entry point de pip

Dentro de 1.x esa superficie puede crecer, pero nada de la lista se renombra o elimina, y ningún cambio de comportamiento por defecto llega sin una 2.0. MemoryStore y las demás clases y módulos de Python son internos y no están cubiertos. Un archivo de migración ya publicado nunca se edita en su sitio; los cambios de esquema se entregan como una nueva migración numerada.

La matriz de compatibilidad se prueba en CI en cada push: Python 3.11, 3.12 y 3.13 contra PostgreSQL 16, 17 y 18 con pgvector 0.5.0 o más reciente. Un suite de conformidad de hermes-agent upstream se ejecuta contra un ref fijado, con una verificación semanal de deriva no bloqueante contra main upstream.

Lo que descubrió la revisión

La 1.0.0 no es un reetiquetado de la release candidate, que nunca se publicó en PyPI. Antes del lanzamiento ejecutamos una revisión multi-paso de toda la base de código: varias pasadas con agentes revisores de IA en paralelo, donde un hallazgo necesitaba una reproducción concreta o una verificación independiente antes de que alguien lo aplicase. La 0.6.0 salió de una revisión previa de preparación para la 1.0.

Se encontró un bug de severidad Alta, y era un bug de pérdida de datos. hermes-pgvector remap --old X --new X --execute eliminaba todas las filas de memory_entries para el tema X y salía con código 0. Cada fila entraba en conflicto consigo misma al insertarse, y luego el borrado eliminaba las originales. Ahora remap rechaza --old y --new en blanco o idénticos con código de salida 1, incluso en dry-run.

Los hallazgos de severidad Media y Baja merecen un vistazo si lo usas en producción:

  • identity_signature() leía la configuración congelada al arrancar, por lo que las ediciones de allowed_themes o identity_aliases no llegaban a los agentes pasarela en caché hasta un reinicio. Ahora relee config.yaml ante cualquier cambio.
  • El respaldo on_session_end podía escribir turnos multimodales del usuario dos veces y podía almacenar andamiaje voluminoso de /skill.
  • replace() con un old_text en blanco sobrescribía una fila arbitraria.
  • El cliente de embeddings aceptaba vectores con NaN, Infinity o null. La base de datos los rechazaba y se perdía la fila duradera. Ahora degradan a una fila de solo texto como cualquier otro fallo de embeddings.
  • backfill reintentaba filas en blanco compuestas por espacios en blanco no ASCII indefinidamente, y fallaba en todas las filas en bases de datos SQL_ASCII.
  • Un --config explícito que no se podía leer antes avisaba y caía silenciosamente al DSN por defecto. Ahora es un error.
  • Chats de foros de Telegram (topics), salas de LINE y sesiones webhook no se reconocían como sesiones multi-participante, por lo que sus claves de sesión en crudo, incluyendo un id de participante, se convertían en temas propios. Ahora caen en el cubo compartido external-group como el resto del tráfico de grupo.

El suite de tests creció de 442 a más de 500 tests, incluyendo unos 80 tests de regresión para estas correcciones. CI los ejecuta contra Postgres 16, 17 y 18 en vivo, y ahora falla ante cualquier test saltado, de modo que un entorno roto ya no puede pasar en verde.

Instalación y actualización

pip install hermes-memory-pgvector
hermes-pgvector migrate --admin-dsn \
    "dbname=<your-memory-db> user=postgres host=/var/run/postgresql"
hermes config set memory.provider pgvector
hermes memory status

Si vienes de la 0.6.0, no hay cambios de esquema ni migraciones nuevas. Actualiza el paquete, reinicia y lee las notas de actualización de la 1.0.0 en el CHANGELOG. Estos cambios de comportamiento:

  • remap rechaza --old/--new en blanco o idénticos.
  • Un --config explícito que no se pueda leer o parsear ahora es un error en lugar de una caída silenciosa al DSN por defecto.
  • Las claves de configuración booleanas aceptan solo 1/true/yes/on y 0/false/no/off. Los valores en blanco o no reconocidos ahora se interpretan como el valor por defecto de la clave.
  • prefetch_budget, prefetch_limit y min_similarity se limitan a sus rangos documentados.
  • Las escrituras nuevas de sesiones de foros de Telegram, salas de LINE y webhook van al tema external-group; las filas ya escritas bajo sus claves en crudo se quedan donde están.
  • Las copias de seguridad de instalación ahora se mueven a un directorio oculto plugins/.pgvector.bak-<ts>. Elimina cualquier directorio visible antiguo pgvector.bak* para que hermes-agent no lo descubra como un segundo proveedor.

Si vienes de algo anterior a la 0.6.0, lee primero las notas de la 0.6.0 y sigue la regla de ordenación que aparece allí: actualiza el paquete en cada host que escriba en la base de datos antes de ejecutar migrate. docs/upgrading.md contiene el procedimiento completo.

Enlaces

El proyecto es BSD-3-Clause, copyright Green Yoga Inc. Se agradecen informes de bugs y PRs enfocados.