--- name: save description: "Use when user types 'save'. Write to Brain (Cognee) and/or Vault (Qdrant ai_vault_kb)." version: 1.3.0 author: Hermes Agent license: MIT platforms: [linux] metadata: hermes: tags: [memory, brain, vault, cognee, qdrant, save] related_skills: [cognee-brain, ai-vault-kb] --- # Save — write to Brain and/or Vault Triggered when the user types "save". Route the current session's content to the right store and write it. ## Routing - **Brain** (Cognee) = durable facts, decisions, preferences, relationships, status changes, corrections. Short atomic statements with time context. - **Vault** (Qdrant `ai_vault_kb`) = longer context, notes, research, summaries, excerpts — for semantic "find similar" recall. - **Both** = when something is a clean fact AND rich context: clean version to Brain, fuller version to Vault. - Be conservative. Only store what's worth remembering. Don't write every message. --- ## BRAIN — Cognee (Kuzu + LanceDB on brain 10.0.0.23) The brain is Cognee, reachable via the auto-discovered MCP tools `mcp__cognee__*` (no CLI needed). Endpoints: API `http://10.0.0.23:8080`, MCP `http://10.0.0.23:8001/mcp`. ### Write (permanent memory) Use the `mcp__cognee__remember` tool. ALWAYS pass `dataset_name="homelab-stack"`. - `data` = the text to store (atomic facts, one per statement where possible). - Omit `session_id` — that makes it permanent memory (add + cognify, builds the graph). - `remember` returns `status: completed` synchronously — the graph is built, no polling. ### Read Use the `mcp__cognee__recall` tool. `query` (required), `datasets="homelab-stack"`, optional `search_type` (HYBRID_COMPLETION default; CHUNKS for LLM-free retrieval). ### Write rules - **One dataset:** `homelab-stack`. Never create a second dataset. - **No group_id, no triplet, no temporal supersession.** Cognee uses datasets. To correct a fact, `remember` the corrected statement; Cognee merges entities by name. - **Don't re-ingest the same content twice** — `remember` is not idempotent. - **Embed dim is 1024** (qwen3-embedding:0.6b on mini) — never let it default to 3072. ### Verify the write - `recall` a distinctive phrase from the content; a correct answer proves the graph has it. - `docker logs cognee-backend` should show zero `api.openai.com` / `ProviderConfigMismatch` hits. --- ## VAULT — Qdrant `ai_vault_kb` CLI: `python3 /home/n8n/bin/ai_vault_kb.py` (zero deps, urllib only). Qdrant `http://10.0.0.22:6333`, collection `ai_vault_kb`. Embeddings: `snowflake-arctic-embed2` on `10.0.0.30:11434`. ### Write (the ONLY sanctioned path) ```bash python3 /home/n8n/bin/ai_vault_kb.py add --type --title "..." --content "..." [flags] ``` Long documents: `--file /abs/path/report.md` instead of `--content` (auto-chunked, one shared `doc_id`). `--json` prints `{"doc_id":…, "chunks":N}`. | Flag | Meaning | |---|---| | `--type` **(required)** | `tool` `setting` `workflow` `host` `model` `technique` `issue` `decision` `research` `asset` `prompt` `finding` | | `--title` **(required)** | headline a future search reads | | `--content` / `--file` | body text, or a file to chunk | | `--stage` | `story` `script` `character` `keyframe` `t2v` `i2v` `upscale` `interpolate` `tts` `lipsync` `music` `assembly` `publish` `infra` | | `--tool` `--host` `--path` `--url` `--version` | provenance; `--host` is the box the fact is about | | `--status` | `active` `candidate` `deprecated` `broken` `planned` (default `active`) | | `--trust` | `official` `github` `community` `social` (default `official`) | | `--tags` | comma-separated; exact-match keyword index — put slug, filename, error code here | | `--importance` | 0.0–1.0 | | `--doc-id` | append more chunks to an existing document | Unknown vocabulary values warn but are accepted — the schema is faceted, not strict. ### Dedup-first (mandatory before every write) ```bash python3 /home/n8n/bin/ai_vault_kb.py search --query "" ``` - score **≥ 0.85** — already recorded, skip - **0.70–0.84** — add only if meaningfully new - **< 0.70** — always add ### Host records `--type host`, one stable `--doc-id` per box. Re-add with the same `--doc-id` to update/append a dated chunk. ### Verify the write landed (both legs) ```bash D= python3 /home/n8n/bin/ai_vault_kb.py search --query "" --mode bm25 --doc-id $D python3 /home/n8n/bin/ai_vault_kb.py list --type --doc-id $D ``` Zero hits on the BM25 leg means something other than `ai_vault_kb.py` wrote it. --- ## Pitfalls - **Brain writes are not idempotent** — don't re-ingest the same content twice. - **Vault writes MUST go through `ai_vault_kb.py`** — never a bare Qdrant upsert or `mcp__better_qdrant__add_documents` (missing bm25/doc_type makes the point unfindable). Never hand-roll raw Qdrant HTTP for a write. - **Collection name is exact** — `ai_vault_kb`, not `ai-vault-kb`. Don't create topic-specific collections. - **On correction:** update Brain (remember the corrected fact) and store the correction. - **`fact_store` and the `memories` collection are not the vault** — research findings, model configs, prompt guides, infra facts go here. - **A search that returns nothing is a real answer** — say "not in the vault" and go research it.