feat(memory): add per-user scoping to holographic memory plugin - #7256
Closed
nericervin wants to merge 10 commits into
Closed
feat(memory): add per-user scoping to holographic memory plugin#7256nericervin wants to merge 10 commits into
nericervin wants to merge 10 commits into
Conversation
Los mensajes de status/lifecycle (connection dropped, reconnecting, model failed, operation interrupted, etc.) solo se envian a Mattermost y CLI. En WhatsApp, Telegram y otras plataformas externas se suprimen y se loguean a debug. Evita que clientes vean errores internos del gateway.
Red de seguridad: antes de enviar por WhatsApp, verifica que el contenido no sea un mensaje interno del sistema (Memory updated, No home channel, skill_view, razonamiento interno como 'silencio absoluto', etc.). Si matchea algun patron, se suprime y se loguea a debug. Complementa el filtro de lifecycle en run.py como segunda linea de defensa.
Tres funcionalidades en el adapter de WhatsApp: 1. Group debounce (WHATSAPP_GROUP_DEBOUNCE_SECONDS): En grupos, espera N segundos antes de procesar un mensaje. Si alguien del equipo (WHATSAPP_TEAM_NUMBERS) responde durante el delay, el bot cancela y no responde. Normaliza JIDs correctamente (quita +, @s.whatsapp.net, :lid). 2. Group block (WHATSAPP_ALLOWED_GROUPS): Bloquea envio de mensajes a grupos no autorizados. Solo permite enviar a JIDs en la whitelist. Proteccion contra baneo de Meta. 3. Silence filter (_SUPPRESS_PATTERNS): Red de seguridad que suprime mensajes internos antes de enviarlos (Memory updated, No home channel, skill_view, razonamiento interno como 'silencio absoluto', etc.). Env vars: WHATSAPP_GROUP_DEBOUNCE_SECONDS=120 WHATSAPP_TEAM_NUMBERS=5492996351947,5492995347180,... WHATSAPP_ALLOWED_GROUPS=jid1@g.us,jid2@g.us
Dos funcionalidades para el adapter de Mattermost: 1. MATTERMOST_IGNORE_DMS: si es 'true', ignora mensajes directos al bot. Util para bots que solo deben operar en canales (ej: Dewun en dev-*). 2. MATTERMOST_NO_MENTION_PREFIX: prefijos de nombre de canal donde el bot responde sin necesidad de @MENCION. Ej: 'dev-' para que Dewun responda en todos los canales dev-general, dev-kellu, etc.
WhatsApp no puede enumerar chats, action='list' retorna vacio. Se actualiza la descripcion del schema para instruir al modelo a enviar directamente con target='whatsapp:NUMERO@s.whatsapp.net'.
Align env var name with upstream PR convention: MATTERMOST_FREE_RESPONSE_PREFIX (consistent with FREE_RESPONSE_CHANNELS)
When replying inside an existing thread, Hermes was using event.message_id as root_id — which is a reply post, not the thread root. Mattermost rejects this with root_id.app_error. Now prefer metadata.thread_id (the actual thread root) over reply_to when available.
The holographic memory plugin stores all facts in a single global table without any user isolation. When multiple users share a Hermes instance via the API server gateway, every user's facts are visible to every other user — a data leak. This commit adds a `user_scope` column to the facts table and threads the gateway `user_id` (from the `X-Hermes-User-Id` header) through `AIAgent → HolographicMemoryProvider → MemoryStore → FactRetriever`. Changes: - store.py: `user_scope` column with composite unique index on (content, user_scope), auto-migration for existing databases, `scope_clause()` helper for consistent WHERE filtering - __init__.py: extract `user_id` from kwargs in `initialize()`, pass as `user_scope` to MemoryStore; scope `system_prompt_block` count query - retrieval.py: apply `scope_clause()` to all retrieval paths (FTS candidates, probe, related, reason, contradict, vector scoring) - api_server.py: read `X-Hermes-User-Id` header, pass through `_run_agent` → `_create_agent` → `AIAgent(user_id=...)` for all three endpoints (chat completions, responses, streaming) Backwards-compatible: when `user_id` is None (CLI sessions), all facts remain visible — no behaviour change for single-user setups. Follows up on NousResearch#5895 which threaded `user_id` to Mem0 and Honcho but left Holographic unscoped.
The previous commit added user_id to _run_agent and the handler calls but missed adding it to _create_agent's signature and to the AIAgent constructor call. This caused: "unexpected keyword argument 'user_id'" at runtime.
Contributor
Author
|
Closing in favor of a new PR from the proper GitHub fork (nericervin/hermes-agent) with rebased commits. |
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The holographic memory plugin stores all facts in a single global table without user isolation. When multiple users share a Hermes instance via the API server gateway, every user's facts are visible to every other user.
This PR adds a
user_scopecolumn to the facts table and threads the gatewayuser_idthroughAIAgent → HolographicMemoryProvider → MemoryStore → FactRetriever, completing the per-user memory scoping that #5895 started for Mem0 and Honcho.Changes
user_scopecolumn with composite unique index, auto-migration for existing DBs,scope_clause()helperuser_idfrom kwargs ininitialize(), pass to MemoryStore, scope system_prompt_block countscope_clause()to all retrieval paths (FTS, probe, related, reason, contradict, vector scoring)X-Hermes-User-Idheader, pass through_run_agent→_create_agent→AIAgent(user_id=...)for all endpointsBackwards-compatible
When
user_idis None (CLI sessions), all facts remain visible — no behaviour change for single-user setups. Existing databases are auto-migrated (new column + index added on first connection).Context
Follow-up to #5895 which threaded
user_idto Mem0 and Honcho but left Holographic unscoped. We hit this in production running a multi-tenant API server where different clients' facts were leaking across sessions.Test plan
X-Hermes-User-Id: aliceonly sees alice's facts + globalX-Hermes-User-Id: bobonly sees bob's facts + global