Loading...
Loading...
Persistent shared memory for AI agents backed by PostgreSQL (fts + pg_trgm, optional pgvector). Includes compaction logging and maintenance scripts.
npx skill4agent add arthur0824hao/skills skill-system-memoryagent_memoryinit.sql# Linux — replace 'postgres' with your PostgreSQL superuser if different (e.g. your system username)
psql -U postgres -c "CREATE DATABASE agent_memory;"
psql -U postgres -d agent_memory -f init.sql
# Windows (adjust path to your psql.exe; replace 'postgres' with your PG superuser if needed)
& "C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -c "CREATE DATABASE agent_memory;"
& "C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -d agent_memory -f init.sqlNote: If your PostgreSQL installation does not have arole, use your actual PostgreSQL superuser name. On many Linux distros this matches your OS username. You can override at any time by settingpostgresbefore running scripts:PGUSER(Linux/macOS) orexport PGUSER=your_pg_username(PowerShell).$env:PGUSER = "your_pg_username"
SELECT * FROM memory_health_check();-InstallAll--install-all# run from the skill directory
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\bootstrap.ps1"# run from the skill directory
bash "scripts/bootstrap.sh"~/.config/opencode/skill-system-memory/setup.jsonnmake /F Makefile.winwingetplugins/skill-system-memory.js~/.config/opencode/plugins/~/.config/opencode/plugins/skill-system-memory.js~/.local/share/opencode/log/%USERPROFILE%\.local\share\opencode\logsetup.jsonselected.opencode_plugin=trueselected.pgpass=true~/.config/opencode/plugins/skill-system-memory.jspsql.pgpasspgpass.conf~/.pgpasschmod 0600 ~/.pgpass%APPDATA%\postgresql\pgpass.confC:\Users\<you>\AppData\Roaming\postgresql\pgpass.confhostname:port:database:username:passwordPGPASSFILEPGPASSWORDexport PGHOST=localhost
export PGPORT=5432
export PGDATABASE=agent_memory
export PGUSER=postgres # change to your PG superuser if postgres role does not existsemanticscripts/mem.shscripts/mem.ps1scripts/setup-pgpass.ps1scripts/setup-pgpass.shpowershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\setup-pgpass.ps1"bash "scripts/setup-pgpass.sh"| Type | Lifespan | Use When |
|---|---|---|
| 24h auto-expire | Current conversation context (requires |
| Permanent + decay | Problem-solving experiences, debugging sessions |
| Permanent | Extracted facts, knowledge, patterns |
| Permanent | Step-by-step procedures, checklists (importance >= 7) |
store_memory(type, category, tags[], title, content, metadata, agent_id, session_id, importance)access_countimportance_scoreSELECT store_memory(
'semantic',
'windows-networking',
ARRAY['ssh', 'tunnel', 'port-conflict'],
'SSH Tunnel Port Conflict Resolution',
'Fix: 1) taskkill /F /IM ssh.exe 2) Use processId not pid 3) Wait 3s',
'{"os": "Windows 11"}',
'sisyphus',
NULL,
9.0
);scripts/mem.shscripts/mem.ps1# show allowed enum values
bash "scripts/mem.sh" types
# search
bash "scripts/mem.sh" search "pgvector windows install" 5
# store (content via stdin)
printf '%s' "Steps: ..." | bash "scripts/mem.sh" store semantic project "pgvector install" "postgres,pgvector,windows" 8powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\mem.ps1" types
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\mem.ps1" search "pgvector windows install" 5
"Steps: ..." | powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\mem.ps1" store semantic project "pgvector install" "postgres,pgvector,windows" 8SKILL.md{
"schema_version": "2.0",
"id": "skill-system-memory",
"version": "0.2.0",
"capabilities": ["memory-search", "memory-store", "memory-health", "memory-types"],
"effects": ["proc.exec", "db.read", "db.write"],
"operations": {
"search": {
"description": "Search memories by natural language query. Returns ranked results with relevance scores.",
"input": {
"query": { "type": "string", "required": true, "description": "Natural language search query" },
"limit": { "type": "integer", "required": false, "default": 5, "description": "Max results" }
},
"output": {
"description": "Array of memory matches with id, title, content, relevance_score",
"fields": { "status": "ok | error", "data": "array of {id, title, content, relevance_score}" }
},
"entrypoints": {
"unix": ["bash", "scripts/router_mem.sh", "search", "{query}", "{limit}"],
"windows": ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts\\router_mem.ps1", "search", "{query}", "{limit}"]
}
},
"store": {
"description": "Store a new memory. Auto-deduplicates by content hash.",
"input": {
"memory_type": { "type": "string", "required": true, "description": "One of: semantic, episodic, procedural, working" },
"category": { "type": "string", "required": true, "description": "Category name" },
"title": { "type": "string", "required": true, "description": "One-line summary" },
"tags_csv": { "type": "string", "required": true, "description": "Comma-separated tags" },
"importance": { "type": "integer", "required": true, "description": "1-10 importance score" }
},
"output": {
"description": "Confirmation with stored memory id",
"fields": { "status": "ok | error", "id": "integer" }
},
"entrypoints": {
"unix": ["bash", "scripts/router_mem.sh", "store", "{memory_type}", "{category}", "{title}", "{tags_csv}", "{importance}"],
"windows": ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts\\router_mem.ps1", "store", "{memory_type}", "{category}", "{title}", "{tags_csv}", "{importance}"]
}
},
"health": {
"description": "Check memory system health: total count, average importance, stale count.",
"input": {},
"output": {
"description": "Health metrics",
"fields": { "status": "ok | error", "data": "array of {metric, value, status}" }
},
"entrypoints": {
"unix": ["bash", "scripts/router_mem.sh", "health"],
"windows": ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts\\router_mem.ps1", "health"]
}
},
"types": {
"description": "List available memory types and their descriptions.",
"input": {},
"output": {
"description": "Memory type definitions",
"fields": { "status": "ok | error", "data": "array of {type, lifespan, description}" }
},
"entrypoints": {
"unix": ["bash", "scripts/router_mem.sh", "types"],
"windows": ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts\\router_mem.ps1", "types"]
}
}
},
"stdout_contract": {
"last_line_json": true
}
}mem.shmem.ps1./Memory/bash "<skill-dir>/scripts/sync_memory_to_md.sh" --out-dir "./Memory"Memory/Long.mdMemory/Procedural.mdMemory/Short.mdMemory/Episodic.mdMemory/.backups/git status--no-backupMemory/.gitignore.backups/SYNC_STATUS.txtMemory/Long.mdIndexsearch_memories(query, types[], categories[], tags[], agent_id, min_importance, limit)text_score * decay * recency * importance-- Natural language
SELECT * FROM search_memories('ssh tunnel port conflict', NULL, NULL, NULL, NULL, 7.0, 5);
-- Filter by type + tags
SELECT * FROM search_memories(
'troubleshooting steps',
ARRAY['procedural']::memory_type[],
NULL,
ARRAY['ssh'],
NULL, 0.0, 5
);id, memory_type, category, title, content, importance_score, relevance_score, match_typematch_typefulltexttrigram_titletrigram_contentmetadatamemory_health_check()metric | value | statustotal_memoriesavg_importancestale_countapply_memory_decay()0.9999^days_since_accessprune_stale_memories(age_days, max_importance, max_access_count)SELECT id, title, content, relevance_score
FROM search_memories('keywords from user request', NULL, NULL, NULL, NULL, 5.0, 5);SELECT store_memory(
'semantic',
'category-name',
ARRAY['tag1', 'tag2', 'tag3'],
'One-line problem summary',
'Detailed problem + solution',
'{"os": "...", "tools": [...]}',
'agent-name',
NULL,
8.0
);MUST DO FIRST:
Search agent_memories: SELECT * FROM search_memories('relevant keywords', NULL, NULL, NULL, NULL, 5.0, 5);
MUST DO AFTER:
If you solved something new, store it with store_memory(...)agent_taskstask_linksblocksparent_childrelatedblocked_tasks_cachetask_memory_linksagent_memoriesINSERT INTO agent_tasks(title, description, created_by, priority)
VALUES ('Install pgvector', 'Windows build + enable extension', 'user', 1);-- Task 1 blocks task 2
INSERT INTO task_links(from_task_id, to_task_id, link_type)
VALUES (1, 2, 'blocks');
-- Task 2 is parent of task 3 (used for transitive blocking)
INSERT INTO task_links(from_task_id, to_task_id, link_type)
VALUES (2, 3, 'parent_child');SELECT rebuild_blocked_tasks_cache();SELECT id, title, priority
FROM agent_tasks t
WHERE t.deleted_at IS NULL
AND t.status IN ('open','in_progress')
AND NOT EXISTS (SELECT 1 FROM blocked_tasks_cache b WHERE b.task_id = t.id)
ORDER BY priority ASC, updated_at ASC
LIMIT 50;SELECT claim_task(2, 'agent-1');INSERT INTO task_memory_links(task_id, memory_id, link_type)
VALUES (2, 123, 'outcome');conditional_blockstask_links.metadata{ "os": "windows" }powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\tasks.ps1" ready 50
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\tasks.ps1" create "Install pgvector" 1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\tasks.ps1" claim 2 agent-1bash "scripts/tasks.sh" ready 50
bash "scripts/tasks.sh" create "Install pgvector" 1
bash "scripts/tasks.sh" claim 2 agent-1plugins/skill-system-memory.js~/.config/opencode/plugins/~/.config/opencode/skill-system-memory/compaction-events.jsonlstore_memory(...)SELECT id, title, relevance_score
FROM search_memories('compaction', NULL, NULL, NULL, NULL, 0, 10);.pgpasspgpass.confpsql~/.config/opencode/skill-system-memory-postgres/compaction-events.jsonl~/.config/opencode/skill-system-memory-postgres/compaction-daily/powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\consolidate-compactions.ps1"bash "scripts/consolidate-compactions.sh"# every day at 02:10 UTC
10 2 * * * bash "<skill-dir>/scripts/consolidate-compactions.sh" >/dev/null 2>&1hooks/episodicfrictionproceduralagent_memoriesmemory_linksworking_memorymemory_typecategorytags[]titlecontentcontent_hashmetadataimportance_scoreaccess_countrelevance_decaysearch_vector| Don't | Do Instead |
|---|---|
| Store everything | Only store non-obvious solutions |
| Skip tags | Tag comprehensively: tech, error codes, platform |
Use | |
| One type for all data | Use correct memory_type per content |
| Forget importance rating | Rate honestly: 9-10 battle-tested, 5-6 partial |
| Issue | Severity | Mitigation |
|---|---|---|
| Chunks lose context | Critical | Store full problem+solution as one unit |
| Old tech memories | High | |
| Duplicate memories | Medium | |
| No vector search | Info | pg_trgm provides fuzzy matching; pgvector can be added later |
psql -U postgres -d agent_memory -f init.sqlSELECT apply_memory_decay(); -- daily
SELECT prune_stale_memories(180, 3.0, 0); -- monthly
DELETE FROM working_memory WHERE expires_at < NOW(); -- daily
SELECT * FROM memory_health_check(); -- anytimeinit.sqlvectoragent_memories.embedding vectorsearch_memories_vector(p_embedding, p_embedding_dim, ...)agent_memories.embedding-- p_embedding is a pgvector literal; pass it from your app.
-- Optionally filter by dimension (recommended when using multiple models).
SELECT id, title, similarity
FROM search_memories_vector('[0.01, 0.02, ...]'::vector, 768, NULL, NULL, NULL, NULL, 0.0, 10);agent_memories.embeddingscripts/ingest-embeddings.ps1scripts/ingest-embeddings.shembedding IS NULLagent_memories.embedding vectorinit.sqlagent_memories.embedding.pgpasspgpass.confpsql -wEMBEDDING_PROVIDERollamaopenaiopenaiEMBEDDING_API_KEYopenaiollamaEMBEDDING_API_URLEMBEDDING_MODELEMBEDDING_DIMENSIONS$env:EMBEDDING_PROVIDER = "ollama"
$env:EMBEDDING_MODEL = "nomic-embed-text"
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\ingest-embeddings.ps1" -Limit 25export EMBEDDING_API_KEY=...
export EMBEDDING_MODEL=text-embedding-3-small
bash "scripts/ingest-embeddings.sh"Limitpsql -c.sqlpsql -fsystematic-debuggingpostgres-propostgresql-table-design