El recall de tu proveedor de memoria estaba siendo truncado: spill opcional y otros dos fallos silenciosos


Conectas un proveedor de memoria externo a Hermes: Hindsight, Mem0, Honcho, el que sea. Durante un par de semanas se acuerda de ti de verdad. Luego, un día, mencionas el contrato de API que acordaste la semana pasada, y responde como si nunca hubiera oído hablar de él. Culpas al modelo, o das por hecho que el proveedor perdió la escritura. La historia real es más molesta: el recall se recuperó, y luego Hermes mismo lo sustituyó por los primeros párrafos, los últimos párrafos y una ruta de archivo.

Ese comportamiento cambió el 9 de octubre, con tres arreglos fusionados que cubren tres fallos silenciosos alrededor de los plugins de memoria externa: recall truncado, proveedores que desaparecen de hermes memory status, y una instalación que reintenta en cada arranque. Aquí tienes cada síntoma, su mecanismo y qué hacer al respecto.

Síntoma uno: el recall se trunca sin aviso

Hermes tiene un mecanismo general de «spill»: cuando la salida de un hook cruza un umbral de tamaño, el texto completo no se coloca en el context. En su lugar entra una vista previa de cabeza y cola, con una ruta de archivo para el resto. Para los hooks de plugin corrientes ese valor por defecto es sensato: un plugin charlatán no debería comerse tu context window.

La trampa era que el mismo mecanismo se aplicaba al recall de prefetch de memoria externa. Así, un proveedor que ya había aplicado su propio presupuesto de recall quedaba recortado una segunda vez por Hermes: el medio ordenado por relevancia desaparecía de la vista, y el modelo solo veía el principio y el final.

El arreglo convierte eso en una elección explícita (PR #135157):

# ~/.hermes/config.yaml
memory:
  prefetch_spill_enabled: false   # default: external recall stays intact

Los detalles merecen conocerse:

  • Por defecto, false. El recall externo llega entero al modelo. Aún existe un techo de seguridad: un recall superior a 10× hooks.output_spill.max_chars (como mínimo 100.000 caracteres) sigue haciendo spill, así que un proveedor desbocado no puede desbordar el context window.
  • Ponlo en true y recuperas el comportamiento antiguo: un recall sobredimensionado se convierte en una vista previa de cabeza y cola más una ruta de archivo. Reutiliza el umbral, las longitudes de vista previa y el directorio compartidos de hooks.output_spill, y hooks.output_spill.enabled: false sigue anulándolo todo.
  • El spill normal de hooks de plugin no cambia y sigue activado por defecto, con independencia de este ajuste de memoria.
  • El ajuste se captura en un snapshot cuando el proveedor se registra, así que reinicia Hermes después de cambiarlo; una conversación en curso no cambiará de comportamiento a mitad de turn.
  • La documentación oficial lo dice sin rodeos: cuando tu proveedor tiene su propio presupuesto de recall, dale prioridad. Sabe mejor que una regla de truncado qué conservar.

Un compromiso honesto: mantener el recall completo hace los prompts más grandes. Si estás con tokens medidos y ejecutas un servicio de memoria charlatán, volver a activar prefetch_spill_enabled puede ahorrar dinero, siempre que aceptes que el medio del recall queda menos visible.

Síntoma dos: tu proveedor desaparece de hermes memory status

El segundo arreglo (PR #135524) es una línea cambiada más una línea de docstring, y importa más de lo que su tamaño sugiere.

Para decidir si una carpeta de plugin es un proveedor de memoria, Hermes busca register_memory_provider o MemoryProvider en su __init__.py. Es un escaneo barato y sin importaciones, pero solo leía los primeros 8 KB del archivo. Un proveedor perfectamente funcional con un docstring de módulo largo quedaba omitido: ausente de hermes memory status, y hermes memory setup <name> decía «not found».

El plugin del catalog excel_line dio justo con esto, y el apaño de entonces era sombrío: acortar el docstring para que el código de registro cayera dentro de los primeros 8 KB (#135442 / #135473). Ese apaño ya no es necesario. La ruta rápida se mantiene (sigue siendo una comprobación de texto barata de 8 KB); solo cuando no encuentra nada recurre al _defines_memory_provider existente, que parsea los módulos de nivel superior del paquete sin importarlos. Los proveedores que ya coincidían no pagan nada extra: solo las carpetas que fallan pagan un parseo AST.

Si escribiste un plugin que se instala pero nunca se detecta: deja de borrar tu documentación, y actualiza en su lugar.

Síntoma tres: el proveedor se reinstala solo en cada arranque

El tercer arreglo (PR #135529) aborda un bucle de reintento que iba a más.

La instalación automática de un proveedor de memoria se ejecuta al arrancar el agente: hermes chat, una ejecución de cron, un agente de gateway, un reinicio de Desktop, cada uno cuenta. Antes del arreglo, una instalación fallida se reintentaba en cada uno de esos arranques, y cada reintento se registraba como un fallo nuevo. La telemetría del PR (14 días, deduplicada) muestra lo que eso producía:

plugin ok fallidos días de instalación fallidos fallidos por día de instalación fallido
hindsight 130 1048 204 5.1
mnemosyne 47 288 83 3.5

Los fallos diarios de Hindsight subieron 8 → 47 → 170 → 204 entre el 09-29 y el 10-02, en su mayoría los mismos pocos fallos contados una y otra vez, sobre un conjunto menor de errores de red genuinos (uv lock de PM, git clone). La conclusión del PR es tajante: esto es un bucle de reintento, no 1.048 fallos distintos.

La semántica ahora está limpia: STARTUP_RETRY_SECONDS = 3600.0 en hermes_cli/memory_provider_migration.py: un proveedor cuya instalación automática falló no se reintenta desde ningún proceso durante una hora. Cuando vuelve a aparecer, te dice qué ejecutar:

Its automatic install failed less than an hour ago: run `hermes plugins install hindsight`

El mismo PR corrigió un diagnóstico erróneo relacionado: cuando plugins/<name> ya existe como symlink a otro sitio, una instalación desde el catalog ahora dice que la ranura está ocupada en lugar de culpar al manifest del plugin.

Cómo comprobar tu propia configuración

hermes memory status     # qué proveedor externo está activo, y si está instalado
hermes memory setup      # elige o configura un proveedor (también menciona una instalación ausente)
hermes memory off        # desactiva el proveedor externo
hermes plugins list      # ¿está presente el plugin?

Un orden de triaje práctico para «se olvidó de algo»: confirma que el proveedor está presente con hermes memory status, luego lee memory.provider y prefetch_spill_enabled en config.yaml, y después decide si el modelo nunca recibió el recall (configuración) o el proveedor nunca lo almacenó (servicio). Para contexto sobre cómo elegir un backend de memoria, consulta nuestro recorrido por la memoria semántica y la función de dreaming / consolidación de memoria; toda la superficie de comandos está en la referencia de hermes memory.

Estado de la release

Los tres arreglos se fusionaron el 2026-10-09, después de que v0.21.6 se publicara el 8 de octubre, así que por ahora están solo en origin/main: espera a la próxima release o ejecuta hermes update. Para saber cómo se revisan y fijan los plugins desde el principio, consulta la guía del catalog de plugins.

La conclusión

Los tres son fallos silenciosos: sin error, sin línea de log, solo un comportamiento discretamente peor: recall recortado, un plugin omitido, un fallo contado mil veces. Sobrevivieron tanto tiempo porque cada uno vive en una capa que los usuarios no pueden ver. Si ejecutas un proveedor de memoria externo, lo más útil que puedes hacer hoy es abrir config.yaml, mirar memory.prefetch_spill_enabled y decidir si quieres un recall completo o un prompt más pequeño.