diff --git a/save-q-memory/SKILL.md b/save-q-memory/SKILL.md new file mode 100644 index 0000000..0cdcb9e --- /dev/null +++ b/save-q-memory/SKILL.md @@ -0,0 +1,137 @@ +--- +name: save-q-memory +description: "Manual save to Qdrant memories collection with enforced 10-type schema. Load this skill EVERY time the user says 'save to memory' or 'save to qdrant' — it is the ONLY path for manual Qdrant writes." +version: 1.0.0 +author: Hermes Agent +license: MIT +metadata: + hermes: + tags: [qdrant, memories, save, schema, manual] + related_skills: [qdrant-collection-management] +--- + +# Save Q Memory — Manual Write Enforcer + +This skill is the ONLY path for manual Qdrant writes. Load it every time the user says "save to memory" or "save to qdrant." No write bypasses this skill. + +## Trigger + +User says: "save to memory", "save to qdrant", "save this to memories", or any variant directing a manual Qdrant write. + +## Prerequisites + +- Qdrant at `http://10.0.0.22:6333` +- Ollama at `http://localhost:11434` with `snowflake-arctic-embed2:latest` +- Collection: `memories` (1024-dim, Cosine) + +## Mandatory Save Procedure + +### Step 1: Classify the Content + +Before embedding, classify EVERY item: + +**`type`** — pick ONE of 10: +- `fact` — timeless/slow-changing world truth +- `infrastructure` — hosts, IPs, services, configs, topology +- `entity` — person, org, project, tool identity +- `preference` — user's stable likes/dislikes, style, defaults +- `procedure` — how-to: steps, commands, runbooks, fixes +- `decision` — chosen approach + rationale (the why) +- `observation` — consolidated pattern from many episodes (2nd-order) +- `reference` — external KB/docs, URLs, citations +- `event` — something that happened at a time; state change +- `experience` — raw conversation turn / interaction log + +**`mem_class`** — pick ONE: +- `semantic` — for fact, infrastructure, entity, preference, decision, observation, reference +- `procedural` — for procedure +- `episodic` — for event, experience + +**`entities`** — list of people, servers, IPs, tools, projects, models mentioned. Empty array `[]` if none. + +**`tags`** — 2-3 lowercase category tags for filtering. Examples: `["infrastructure", "dgx"]`, `["preference", "output_style"]`. + +**`importance`** — 0.0-1.0: +- 0.9+: critical (court docs, credentials, core infrastructure) +- 0.7-0.8: important (decisions, preferences, procedures) +- 0.5-0.6: useful (facts, entities, references) +- 0.3-0.4: contextual (events, observations) +- 0.1-0.2: noise (raw experiences, heartbeats) + +**`confidence`**: +- 1.0 — user explicitly stated this +- 0.7 — agent inferred this from context +- 0.5 — single episode, low certainty + +**`ttl_hint`**: +- `"slow"` — semantic or procedural types (long-term) +- `"medium"` — references, infrastructure +- `"fast"` — episodic types (event, experience) + +### Step 2: Embed via Ollama + +```bash +curl -s http://localhost:11434/api/embeddings \ + -H "Content-Type: application/json" \ + -d '{"model": "snowflake-arctic-embed2:latest", "prompt": ""}' +``` + +### Step 3: Build the Point + +```python +import json, hashlib, subprocess +from datetime import datetime, timezone + +now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") +point_id = int(hashlib.sha256(text.encode()).hexdigest()[:16], 16) % (2**63) + +point = { + "id": point_id, + "vector": vector, # from Step 2 + "payload": { + "text": text, + "type": "", + "mem_class": "", + "entities": ["entity1", "entity2"], + "tags": ["tag1", "tag2"], + "importance": 0.7, + "quality_score": None, # ALWAYS null — cron computes this + "confidence": 0.7, + "created_at": now, + "updated_at": now, + "source": "agent", # "agent" for manual saves + "ttl_hint": "slow" + } +} +``` + +### Step 4: Upsert to Qdrant + +```bash +curl -s -X PUT http://10.0.0.22:6333/collections/memories/points \ + -H "Content-Type: application/json" \ + -d '{"points": []}' +``` + +Use `subprocess.run(["curl", ...])` — NOT Python `requests` (sandbox can't reach 10.0.0.22 via requests). + +### Step 5: Report + +Confirm to user: what was saved, type, mem_class, point ID. + +## Multi-Item Saves + +If the user asks to save multiple items, classify and embed each one separately. Batch upsert all points in a single curl call (up to 100 points). + +## What NOT to Do + +- Do NOT save without classifying type + mem_class +- Do NOT set quality_score to anything other than null +- Do NOT use Python `requests` library — use `subprocess.run(["curl", ...])` +- Do NOT use string point IDs — must be unsigned integers +- Do NOT save to any collection other than `memories` unless explicitly directed + +## Reference + +Full schema documentation: `/home/n8n/workspace/general/qdrant.md` +Collection management (dedup, migration, registry): `qdrant-collection-management` skill