Add save-q-memory skill (v1.0.0) — manual Qdrant write enforcer with 10-type schema
This commit is contained in:
137
save-q-memory/SKILL.md
Normal file
137
save-q-memory/SKILL.md
Normal file
@@ -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": "<text>"}'
|
||||
```
|
||||
|
||||
### 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": "<classified type>",
|
||||
"mem_class": "<semantic|episodic|procedural>",
|
||||
"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": [<point>]}'
|
||||
```
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user