关于 skill-system-memory
skill-system-memory 为 AI Agent 提供基于 PostgreSQL 的持久共享记忆,并支持按项目隔离。它包含可选的 MCP 服务,可供 Agent 搜索、写入和管理记忆。
主要功能
- 01PostgreSQL 持久记忆
- 02按项目隔离数据库
- 03混合检索记忆
- 04管理记忆上下文与状态
- 05支持显式跨库读取
适用场景
- 01在会话间保存 Agent 记忆
- 02从项目记忆中检索信息
- 03重建压缩或丢失的上下文
MCP 相关
内置 MCP 服务,向客户端提供记忆搜索、存储、更新、删除、上下文和状态等工具,并提供数据库结构与状态资源。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ arthur0824hao/ skills --skill skill-system-memory安装后在 Claude Code 中输入/skill-system-memory确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
SKILL.behavior.yamlSKILL.meta.yamlSKILL.spec.yamlans-myelin-bridge-contract.yamlclose-report-ingestion-runbook.mdinit.sqlmcp.jsonmemory-mirror-config.yamlmemory-mirror-contract.mdmigrate-v2-postgres-first.sqlmyelin-registry.schema.yamlmyelin-seeds.yamlschema-diagram.mdartifacts/myelin-registry.jsonhooks/log-compaction.ps1log-compaction.shmemory-rebuild-reminder.shtest_log_compaction.pytest_memory_rebuild_reminder.pymcp/requirements.txtserver.pytest_mcp_server.pyplugins/runtime_sync.jsruntime_sync.test.mjsskill-system-memory.jsscripts/auto-write-template.mdbootstrap.ps1bootstrap.shconsolidate-compactions.ps1consolidate-compactions.sh详细介绍
技能系统记忆(PostgreSQL)
为所有 AI Agent 提供持久化共享记忆。支持 Linux 或 Windows 上的 PostgreSQL 14+。 记忆故障看起来就像智能故障——此技能可确保在合适的时机检索到正确的记忆。
约定说明:
- 模块优先:
mem.py和 MCP 工具是主要的运行时接口。 - 插件可选:OpenCode 插件集成是一个适配层,并非必需依赖。
- 优先使用项目范围的数据库命名:
<project>-memory(例如skills-memory)。
数据库目标 — 项目隔离
技能是全局安装的,但记忆是项目范围的。隔离在数据库级别实现:每个项目都有自己的 PostgreSQL 数据库,命名为 <project>-memory。
跨数据库回忆是一项显式的读取侧功能,而非默认模式。除非调用方通过 scope=all 或 cross_db=true 选择启用,否则搜索和上下文读取都只访问当前记忆数据库。所有写入路径始终固定到本地 SKILL_PGDATABASE 目标。
搜索路径角色架构(SK-C)
兼容的部署路径采用增量方式:
- 旧版模式仍使用每个项目一个数据库:
SKILL_PGDATABASE=<project>-memory - 共享数据库模式使用显式指定的共享数据库,并通过 schema 实现隔离
- 运行时角色拆分为
admin、connector和visitor_<identity>
角色模型:
admin:仅用于迁移/初始化;创建 schema、授权和角色connector:仅有 CONNECT 权限的凭据;打开数据库连接后立即执行SET ROLEvisitor_<identity>:日常查询角色,强制使用search_path
Visitor search_path 矩阵:
visitor_hermes:ep_scope, sk_scope, fd_scope, work_scope, publicvisitor_atlas:ep_scope, publicvisitor_athena:sk_scope, publicvisitor_fd_coder:fd_scope, publicvisitor_ep_coder:ep_scope, publicvisitor_sk_coder:sk_scope, publicvisitor_hephaestion:work_scope, sk_scope, public
共享数据库模式是显式且向后兼容的:
SKILL_PGSHARED_DB=<shared-db-name>选择共享数据库SKILL_PGSCHEMA=<scope-schema>选择本地可写 schemaSKILL_PGDATABASE在旧版的每个项目一个数据库模式下仍然有效
共享数据库模式下的运行时流程:
- 以
connector身份连接 - 执行
SET ROLE visitor_<identity> - 依靠 visitor 的
search_path进行范围限定的查询 - 仅允许 Hermes 显式覆盖设置,以执行全范围审计查询
共享数据库示例:
# Provision shared DB schemas/roles for SK scope
python3 scripts/mem.py init-project \
--project-id sk \
--db-name shared-memory \
--schema-name sk_scope \
--shared-db-mode
# Run local SK queries through shared DB scope
SKILL_PGSHARED_DB=shared-memory \
SKILL_PGSCHEMA=sk_scope \
SKILL_VISITOR_ROLE=visitor_sk_coder \
python3 scripts/mem.py search "router policy"
# Hermes explicit all-scopes audit across the shared DB
SKILL_PGSHARED_DB=shared-memory \
SKILL_PGSCHEMA=sk_scope \
SKILL_VISITOR_ROLE=visitor_hermes \
python3 scripts/mem.py search "friction skill-system-comms" --all-scopes
跨数据库可见性约定
visibility=private(默认):只能在记忆所在的数据库内搜索;没有 visibility 字段的旧记录按private处理visibility=shared:显式启用联邦查询时,可跨已配置的记忆数据库搜索visibility=global:可跨已配置的记忆数据库搜索,也可用于跨数据库自动注入上下文- 跨数据库结果必须包含
source_db - 跨数据库排序使用归一化融合(RRF 风格),而非直接比较各数据库的原始分数
- 已知的数据库扇出目标配置在
config/insight.yaml的memory.cross_db_targets下 - 即使启用了读取侧跨数据库联邦查询,所有变更路径(
store、update、delete、purge)仍仅作用于当前SKILL_PGDATABASE目标
自动检测(推荐)
未设置环境变量时,会根据项目目录名称自动推导数据库名称:
- 插件(JS):使用 OpenCode 主机传入的
directory→ 最后一个路径段 →<dir>-memory - mem.py CLI:使用脚本的根目录或当前工作目录 →
<dir>-memory - MCP 服务:在启动时使用
Path.cwd()→<dir>-memory
请勿全局设置 SKILL_PGDATABASE。 它会覆盖所有项目的自动检测结果。
# WRONG — breaks project isolation
export SKILL_PGDATABASE=skills-memory # every project now hits skills-memory
# RIGHT — let auto-detection work (no env var needed)
cd /path/to/FraudDetect && opencode # → FraudDetect-memory
cd /path/to/skills && opencode # → skills-memory
按项目覆盖(必要时)
如果必须覆盖,请在项目级别而非全局设置 SKILL_PGDATABASE:
- 在项目的
.opencode配置或启动脚本中 - 在项目的
.env文件中(如果你的主机读取该文件) - 作为命令前缀:
SKILL_PGDATABASE=FraudDetect-memory opencode
故障时拒绝连接策略
如果设置了 PGDATABASE,但未设置 SKILL_PGDATABASE,所有入口点都会拒绝连接。这可以防止不同项目的记忆意外混杂。
多项目设置的 MCP 服务路径
如果技能全局安装在 ~/.agents/skills/,请将 MCP 配置为指向全局安装目录的绝对路径:
{
"skill-system-memory": {
"command": "python3",
"args": ["~/.agents/skills/skill-system-memory/mcp/server.py"]
}
}
请勿使用 skills/skill-system-memory/mcp/server.py 这类相对路径——在没有本地 skills/ 目录的项目中,这类路径会失效。
快速开始
数据库 <project>-memory 和所有函数均由此技能目录中的 init.sql 创建。
当前支持的运行时范围涵盖核心记忆、类型化上下文读取、类型化演进账本,以及 doctor/压缩支持。
会话/项目/上下文投影表和行为图刷新仍是由能力门控的可选功能,并非无条件保证的运行时功能。
# Linux — replace 'postgres' with your PostgreSQL superuser if different (e.g. your system username)
psql -U postgres -c "CREATE DATABASE <project>-memory;"
psql -U postgres -d <project>-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 <project>-memory;"
& "C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -d <project>-memory -f init.sql
注意:如果你的 PostgreSQL 安装中没有
postgres角色,请使用实际的 PostgreSQL 超级用户名称。在许多 Linux 发行版中,该名称与操作系统用户名相同。 你可以随时在运行脚本前设置PGUSER来覆盖:export PGUSER=your_pg_username(Linux/macOS),或$env:PGUSER = "your_pg_username"(PowerShell)。
验证:SELECT * FROM memory_health_check();
MCP 服务(阶段 6.1)
此技能包含一个 MCP(Model Context Protocol)服务,可将记忆操作作为 Agent 工具提供。
MCP 服务设置
# Install dependencies
cd skills/skill-system-memory/mcp
pip install -r requirements.txt
# Verify installation
python server.py --help
# Run with stdio transport (default)
python server.py
# Run with SSE transport (for remote access)
MCP_TRANSPORT=sse MCP_PORT=8000 python server.py
# Or via MCP CLI
mcp dev server.py
MCP 环境变量
| 变量 | 默认值 | 说明 |
|---|---|---|
SKILL_PGDATABASE | <project>-memory | 传统的每项目一个 PostgreSQL 数据库名称 |
SKILL_PGSHARED_DB | (未设置) | search_path 模式下共享的 PostgreSQL 数据库名称 |
SKILL_PGSCHEMA | (未设置) | search_path 模式下本地可写的 schema |
PGHOST | localhost | PostgreSQL 主机 |
PGPORT | 5432 | PostgreSQL 端口 |
PGUSER | (可选) | PostgreSQL 用户 |
MCP_TRANSPORT | stdio | 传输模式(stdio 或 sse) |
MCP_PORT | 8000 | SSE 传输端口 |
MCP 工具
| 工具 | 说明 |
|---|---|
memory_search | 按自然语言查询搜索记忆(混合方式:FTS + trigram + pgvector) |
memory_store | 存储新记忆,自动去重并隔离本地写入 |
memory_update | 按 ID 更新本地记忆行中的选定字段,并记录审计日志 |
memory_delete | 按 ID 软删除本地记忆行,并记录审计日志 |
memory_purge | 仅在明确授权后,硬删除本地记忆行 |
memory_auto_match | 根据输入文本自动匹配记忆,并写入 .sisyphus/tmp/mem-{session}.md |
memory_context | 获取用户上下文(灵魂状态、偏好、近期特征) |
memory_status | 检查记忆系统健康状况(连接、schema、pgvector) |
ingest-close-reports | 将收件箱关闭报告解析为结构化的情景记忆候选项或写入记录 |
backfill-embeddings | 修复 pgvector 后,为现有记忆补齐缺失的向量嵌入 |
myelin_search | 按意图/上下文搜索 myelin 适配注册表,并仅返回 top-k 封装器/反射 |
myelin_get | 获取一条包含完整元数据的适配记录 |
myelin_validate | 根据参数和防护规则验证一条适配记录 |
debug_diagnose | 通过统一 MCP 服务运行调试工具诊断 |
eda_profile | 通过统一 MCP 服务运行 EDA 数据集分析 |
gate_validate | 通过统一 MCP 服务运行门控验证 |
memory_rebuild | 压缩或记忆丢失后重建完整的 Agent 上下文 |
MCP 资源
| 资源 | 说明 |
|---|---|
memory://schema | 记忆数据库 schema 信息 |
memory://status | 当前记忆系统状态 |
MCP Agent 集成
要将 MCP 服务用于 Agent,请配置 Agent 的 MCP 设置,添加以下内容:
{
"mcpServers": {
"skill-system": {
"command": "python",
"args": ["skills/skill-system-memory/mcp/server.py"],
"env": {
"SKILL_PGDATABASE": "<project>-memory"
}
}
}
}
共享数据库 MCP 示例:
{
"mcpServers": {
"skill-system": {
"command": "python",
"args": ["skills/skill-system-memory/mcp/server.py"],
"env": {
"SKILL_PGSHARED_DB": "shared-memory",
"SKILL_PGSCHEMA": "sk_scope",
"SKILL_VISITOR_ROLE": "visitor_sk_coder"
}
}
}
}
MCP 工具示例
# Search memories
mcp_tool: memory_search
args: { "query": "pgvector installation", "limit": 5 }
# Search memories with full content for the returned top-k rows
mcp_tool: memory_search
args: { "query": "pgvector installation", "limit": 5, "mode": "full" }
# Explicit cross-DB search
mcp_tool: memory_search
args: { "query": "reviewer feedback", "cross_db": true, "limit": 5 }
# Hermes all-scopes override in shared-DB mode
mcp_tool: memory_search
args: { "query": "cross-project audit", "all_scopes": true, "limit": 10 }
# Store a memory
mcp_tool: memory_store
args: { "type": "semantic", "category": "troubleshooting", "title": "Fixed pgvector on Windows", "content": "Build steps...", "importance": 8 }
# Update a memory locally
mcp_tool: memory_update
args: { "id": 42, "fields": { "title": "Updated title", "visibility": "shared" } }
# Soft-delete a memory locally
mcp_tool: memory_delete
args: { "id": 42 }
# Hard-delete a memory locally only with explicit authorization
mcp_tool: memory_purge
args: { "id": 42, "hard": true, "authorized": true }
# Auto-match memories (KEY TOOL for near-automatic surfacing)
mcp_tool: memory_auto_match
args: { "text": "I'm seeing an error with database connections", "threshold": 0.8, "limit": 5 }
# Auto-match without hiding low-score candidates
mcp_tool: memory_auto_match
args: { "text": "I'm seeing an error with database connections", "threshold": 0.8, "include_below_threshold": true, "limit": 5, "mode": "full" }
# Get user context
mcp_tool: memory_context
args: { "user": "default" }
# Check system health
mcp_tool: memory_status
args: {}
对于现有安装,也请运行:
psql -U postgres -d <project>-memory -v ON_ERROR_STOP=1 -f migrate-v2-postgres-first.sql
纯 Skill 模式(默认)
此 Skill 无需安装任何插件即可运行。在纯 Skill 模式下:
- 需要时手动运行脚本(渐进式披露)
- 不会自动修改全局 OpenCode 配置
可选的引导程序(询问并记录选择 + 尝试安装)
注意:
- 交互模式默认不安装占用资源较多的可选组件。
- 只有在准备好安装所有内容时,才使用
-InstallAll/--install-all。
运行引导脚本以选择可选组件(pgpass、本地嵌入、pgvector)并记录选择。
引导程序还可以选择安装 OpenCode 压缩日志插件(会将插件复制到 OpenCode 插件目录)。
Windows:
# run from the skill directory
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\bootstrap.ps1"
Linux/macOS:
# run from the skill directory
bash "scripts/bootstrap.sh"
选择记录存储于:
~/.config/opencode/skill-system-memory/setup.json
Agent 规则:
- 如果此文件不存在,询问用户是否要启用可选组件。
- 建议:启用所有选项运行引导程序(然后修复它报告的任何失败)。
运行时能力模型
当前的实时能力分类刻意保持精简:
| 能力 | 当前状态 | 当前支持范围 |
|---|---|---|
core_memory | SUPPORTED_NOW | agent_memories 以及 store_memory、search_memories、memory_health_check |
evolution_ledger | SUPPORTED_NOW | evolution_snapshots 以及 insert_evolution_snapshot、get_evolution_history |
compaction_logging | 在同步仓库插件时为 SUPPORTED_NOW | 本地 JSONL 压缩日志,以及受保护的 store_memory(...) 写回 |
typed_context_reads | SUPPORTED_NOW | get_agent_context、get_soul_state、get_recent_facets、get_user_preferences |
runtime_sync_projections | GATED_OPTIONAL | 仅当这些表存在时提供 session_summaries、project_summaries、context_rollups |
behavior_refresh_graph | GATED_OPTIONAL | 仅当这些表存在时提供 behavior_* 刷新 |
control_plane_refresh | DEFERRED_UNSUPPORTED | 不属于当前面向用户的记忆运行时 |
存在持久化演进提案模型时,doctor 还会报告:
- 规范的已接受存储:
evolution_nodes - 规范的已拒绝存储:
evolution_rejections - 规范的任务物化:
evolution_tasks -> agent_tasks agent_memories的角色:可搜索的摘要/反向引用范围,包含明确的旧版兼容行- 批准/拒绝路径状态:在 CLI 边界具备事务安全性
- 迁移/回填幂等性:可安全重复运行
- 决策重放状态:通过
proposal_id实现重放幂等 - 协调机制:按提案使用 advisory lock,并在规范的已接受/已拒绝行上使用语义指纹
- 负载不匹配策略:阻止操作且不做任何修改
- 终态冲突策略:阻止操作且不做任何修改
- 任务权威模型:
agent_tasks负责生命周期权威管理,evolution_tasks仅用于映射
在此状态下,evolution_snapshots 对提案持久化被视为 LEGACY_COMPAT_SURFACE,同时仍用于快照/版本历史。
在 Windows 上,pgvector 安装遵循官方 pgvector 说明(Visual Studio C++ + nmake /F Makefile.win)。引导程序将尝试通过 winget 安装先决条件。
可选自动化:压缩日志记录(OpenCode 插件)
如果需要自动记录压缩日志,请安装此技能附带的 OpenCode 插件模板。
选项 A(推荐):运行 bootstrap 并选择插件选项。
- 将
plugins/skill-system-memory.js和plugins/runtime_sync.js复制到~/.config/opencode/plugins/ - 重启 OpenCode
安全措施/回滚(如果 OpenCode 在启动时卡住):
- 移除或重命名
~/.config/opencode/plugins/skill-system-memory.js - 移除或重命名
~/.config/opencode/plugins/runtime_sync.js - 重启 OpenCode
- 查看日志:
- macOS/Linux:
~/.local/share/opencode/log/ - Windows:
%USERPROFILE%\.local\share\opencode\log
- macOS/Linux:
插件行为说明:
- 除非通过 bootstrap 明确启用(
setup.json设置selected.opencode_plugin=true),否则该插件不会执行任何操作。 - 仅当
selected.pgpass=true时才会尝试写入 Postgres(避免在身份验证提示处卡住)。 - 压缩时,只要数据库目标有效,插件始终会保留本地 JSONL 日志记录以及核心
store_memory(...)路径。 - 运行时投影 upsert(
session_summaries、project_summaries、context_rollups)受功能检测控制:如果这些表不存在,插件会跳过操作并明确说明原因,而不是尝试写入。 - 将行为图刷新到
behavior_*表也受功能检测控制;如果缺少必需的表,插件会明确跳过此操作。
卸载:
- 移除
~/.config/opencode/plugins/skill-system-memory.js - 移除
~/.config/opencode/plugins/runtime_sync.js - 重启 OpenCode
凭据(psql)
不要在脚本、技能文档或配置文件中硬编码密码。
非交互式 psql 的推荐选项:
.pgpass/pgpass.conf(推荐)- Linux/macOS:
~/.pgpass(必须执行chmod 0600 ~/.pgpass,否则 libpq 会忽略它) - Windows:
%APPDATA%\postgresql\pgpass.conf(示例:C:\Users\<you>\AppData\Roaming\postgresql\pgpass.conf) - 格式:
hostname:port:database:username:password - 文档:https://www.postgresql.org/docs/current/libpq-pgpass.html
- Linux/macOS:
PGPASSFILE(可选覆盖项):指向密码文件的自定义位置PGPASSWORD(不推荐):仅用于快速本地测试;在某些系统上,环境变量可能会泄露
提示:每个 shell 只需设置一次连接默认值,即可缩短命令:
export PGHOST=localhost
export PGPORT=5432
export SKILL_PGDATABASE=<project>-memory
export PGUSER=postgres # change to your PG superuser if postgres role does not exist
Shell 复制粘贴安全提示:
- 避免将行内 Markdown 反引号(例如
semantic)复制到 shell 中。在 zsh 中,反引号会进行命令替换。 - 建议使用包装脚本(
scripts/mem.sh、scripts/mem.ps1),或从围栏代码块中复制。
一次性设置辅助脚本
此技能附带辅助脚本(相对路径):
scripts/setup-pgpass.ps1scripts/setup-pgpass.sh
OpenCode 用法:从技能目录运行这些脚本。
Windows 运行:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\setup-pgpass.ps1"
Linux/macOS 运行:
bash "scripts/setup-pgpass.sh"
记忆类型
| 类型 | 生命周期 | 使用场景 |
|---|---|---|
working | 24 小时后自动过期 | 当前对话上下文(需要 session_id) |
episodic | 永久保存 + 衰减 | 问题解决经验、调试会话 |
semantic | 永久保存 | 提取的事实、知识、模式 |
procedural | 永久保存 | 分步流程、检查清单(重要性 >= 7) |
核心函数
store_memory(type, category, tags[], title, content, metadata, agent_id, session_id, importance)
根据内容哈希自动去重。重复插入会增加 access_count 和 importance_score。
SELECT 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.py(推荐——参数化查询,无 quoting 问题)
Requirements:
pip install psycopg2-binary
# DB 連線狀態 + 記憶總數
python3 scripts/mem.py status
# 搜尋記憶(含特殊字元也安全)
python3 scripts/mem.py search "pgvector windows install" --limit 5
python3 scripts/mem.py search "pgvector windows install" --limit 5 --mode full
python3 scripts/mem.py search "fraud features" --scope project --limit 10
python3 scripts/mem.py search "reviewer feedback" --cross-db --limit 10
python3 scripts/mem.py search "shared debugging notes" --scope all --limit 10
# 跨 5 維度診斷搜尋 (B-015 TKT-001)
python3 scripts/mem.py search "alert file" --diagnostic --limit 10
# Tag 前綴自動展開 (B-015 TKT-003)
python3 scripts/mem.py search "root-cause" --auto-expand
# 儲存記憶(--content flag)
python3 scripts/mem.py store --type semantic --category project --title "pgvector install" --tags "postgres,pgvector,windows" --importance 8 --scope project --content "Steps: ..."
python3 scripts/mem.py store --type semantic --category feedback --title "Reviewer note" --visibility shared --content "Cross-DB searchable note"
python3 scripts/mem.py update 42 --field title="Updated note" --field visibility=shared
python3 scripts/mem.py delete 42
python3 scripts/mem.py purge 42 --hard --authorized
# 儲存記憶(stdin)
printf '%s' "Steps: ..." | python3 scripts/mem.py store semantic project "pgvector install" "postgres,pgvector,windows" 8 --scope session
# 列出 / 匯出 / 壓縮
python3 scripts/mem.py list --scope project --limit 20
python3 scripts/mem.py export --format json --scope global
python3 scripts/mem.py compact --scope project
# session 開頭自動撈出相關記憶
python3 scripts/mem.py context "pgvector ssh tunnel"
# 列出所有已使用的 tags / categories
python3 scripts/mem.py tags
python3 scripts/mem.py categories
# DB 不可用時,將 pending fallback 寫回 DB
python3 scripts/mem.py flush
# 保守升級 visibility(只影響本地 DB)
python3 scripts/mem.py visibility-upgrade --visibility shared --category feedback --dry-run
python3 scripts/mem.py visibility-upgrade --visibility global --tags reviewer,decision
回退行为:
- DB 连接失败时,
store会降级写入.memory/pending/*.json,search/context会读取本地 pending 文件并打印警告 list/export也会从 pending 回退读取;DB 不可用时,compact只打印警告,不会崩溃- DB 可连接但 memory schema 缺失时,
store会发出警告并不执行操作,search/context/tags/categories会返回空结果并发出警告 - DB 恢复后,
flush会将.memory/pending/的内容写回 PostgreSQL
作用域模型:
session(默认):记录在metadata.scope=session,并尽可能带上session_idproject:记录在metadata.scope=project+metadata.project_id=<repo>global:记录在metadata.scope=global,仍需明确执行联邦读取才会跨 DB 查询search/list/export不带--scope时,会返回所有作用域,并在结果中标记来源作用域
可见性与作用域不同:
private(默认):仅本地 DBshared:可用于显式跨 DB 搜索global:可用于显式跨 DB 搜索和自动上下文注入
变更审计规则:
update仅写入选定字段的变更,且仅写入本地 DBdelete仅执行软删除(deleted_at),保留向后兼容的读取方式purge执行硬删除,且必须获得明确授权- 每次变更都会写入一条
memory_audit记录,包含旧值/新值及操作者元数据
CLI 变更示例:
python3 scripts/mem.py update 42 --field title="Updated note" --field visibility=shared
python3 scripts/mem.py delete 42
python3 scripts/mem.py purge 42 --hard --authorized
memory_audit 是这些操作的规范变更记录。每条记录包含:
memory_idaction(update、delete、purge)old_valuenew_valueactor_idsession_idchanged_at
警告:purge 会造成破坏性影响,并绕过软删除恢复机制。它仅限本地操作,且需要明确的授权标志;请勿将其用于常规清理。
已知的联邦读取目标在 config/insight.yaml 中配置:
memory:
cross_db_targets:
- Work-memory
- skills-memory
- ExperimentPipeline-memory
- FraudDetect-memory
cross_db_context_visibility:
- global
此列表仅控制显式读取的扇出范围。即使调用方传入类似 target_db 的数据,写入路径仍会指向本地 SKILL_PGDATABASE 数据库。
包装器:scripts/mem.sh / scripts/mem.ps1(Shell 回退)
# 連線狀態
bash "scripts/mem.sh" status
# 搜尋
bash "scripts/mem.sh" search "pgvector windows install" 5
# 儲存 (content via stdin)
printf '%s' "Steps: ..." | bash "scripts/mem.sh" store semantic project "pgvector install" "postgres,pgvector,windows" 8
# 列出 tags / categories
bash "scripts/mem.sh" tags
bash "scripts/mem.sh" categories
powershell.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" 8
路由器集成(可选)
如果你使用执行固定流水线的 Router 技能,它可以读取嵌入在此 SKILL.md 中的清单。
为确保可移植性,清单块采用 YAML 围栏格式,但内容是 JSON(有效的 YAML)。Router 会对其进行解析。
{
"schema_version": "2.0",
"id": "skill-system-memory",
"version": "1.0.0",
"capabilities": ["memory-search", "memory-search-cross-db", "memory-role-scope", "memory-store", "memory-update", "memory-delete", "memory-purge", "memory-visibility-upgrade", "memory-list", "memory-compact", "memory-export", "memory-export-md", "memory-flush", "memory-mirror-capture", "memory-reconcile-note-live", "memory-ingest-close-reports", "memory-backfill-embeddings", "myelin-search", "myelin-get", "myelin-validate", "memory-health", "memory-types", "memory-auto-write", "memory-doctor", "plugin-debug", "plugin-eda", "plugin-gate", "memory-rebuild"],
"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" },
"scope": { "type": "string", "required": false, "description": "global | project | session filter; all enables explicit cross-DB federation" },
"cross_db": { "type": "boolean", "required": false, "description": "Explicitly fan out reads across configured memory DBs" },
"all_scopes": { "type": "boolean", "required": false, "description": "Hermes/admin override to bypass visitor search_path scoping for cross-project audit" }
},
"output": {
"description": "Array of memory matches with local scope labels and cross-DB source attribution when federation is enabled",
"fields": { "status": "ok | error", "data": "array of {id, title, content, relevance_score, scope, source_db?}" }
},
"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 and always writes to the local memory DB.",
"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" },
"scope": { "type": "string", "required": false, "description": "global | project | session" },
"visibility": { "type": "string", "required": false, "description": "private | shared | global" }
},
"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}"]
}
},
"update": {
"description": "Update selected fields of a local memory row by id with audit logging.",
"input": {
"id": { "type": "integer", "required": true },
"fields": { "type": "object", "required": true }
},
"output": {
"description": "Update summary",
"fields": { "status": "ok | error", "id": "integer", "updated_fields": "array" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "update"],
"windows": ["python", "scripts/mem.py", "update"]
}
},
"delete": {
"description": "Soft-delete a local memory row by id with audit logging.",
"input": {
"id": { "type": "integer", "required": true }
},
"output": {
"description": "Soft-delete summary",
"fields": { "status": "ok | error", "id": "integer", "deleted_at": "string" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "delete"],
"windows": ["python", "scripts/mem.py", "delete"]
}
},
"purge": {
"description": "Hard-delete a local memory row only with explicit authorization.",
"input": {
"id": { "type": "integer", "required": true },
"hard": { "type": "boolean", "required": true },
"authorized": { "type": "boolean", "required": true }
},
"output": {
"description": "Hard-delete summary",
"fields": { "status": "ok | error", "id": "integer", "purged": "boolean" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "purge"],
"windows": ["python", "scripts/mem.py", "purge"]
}
},
"list": {
"description": "List memories with optional scope/category filters.",
"input": {
"scope": { "type": "string", "required": false },
"category": { "type": "string", "required": false },
"limit": { "type": "integer", "required": false, "default": 20 }
},
"output": {
"description": "Memory listing with scope labels",
"fields": { "status": "ok | error", "results": "array" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "list"],
"windows": ["python", "scripts/mem.py", "list"]
}
},
"compact": {
"description": "Compact duplicate memories within an optional scope.",
"input": {
"scope": { "type": "string", "required": false }
},
"output": {
"description": "Compaction result",
"fields": { "status": "ok | warn | error", "compacted_count": "integer" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "compact"],
"windows": ["python", "scripts/mem.py", "compact"]
}
},
"export": {
"description": "Export memories in json or csv format.",
"input": {
"format": { "type": "string", "required": false },
"scope": { "type": "string", "required": false },
"limit": { "type": "integer", "required": false, "default": 1000 }
},
"output": {
"description": "Export payload",
"fields": { "status": "ok | error", "results": "array|string" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "export"],
"windows": ["python", "scripts/mem.py", "export"]
}
},
"export-md": {
"description": "Export DB-only memories to markdown files that memory_sync can re-import.",
"input": {
"folder": { "type": "string", "required": true, "description": "Target folder for markdown exports" }
},
"output": {
"description": "Markdown export result",
"fields": { "status": "ok | error", "created": "integer", "skipped": "integer", "folder": "string" }
},
"entrypoints": {
"agent": "Use the memory_export MCP tool from skills/skill-system-memory/mcp/server.py"
}
},
"visibility-upgrade": {
"description": "Batch-upgrade local memory visibility conservatively by category and/or tag selectors.",
"input": {
"visibility": { "type": "string", "required": true, "description": "shared | global | private" },
"category": { "type": "string", "required": false },
"tags": { "type": "string", "required": false },
"dry_run": { "type": "boolean", "required": false, "default": false }
},
"output": {
"description": "Upgrade summary",
"fields": { "status": "ok | error", "matched": "integer", "updated": "integer" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "visibility-upgrade"],
"windows": ["python", "scripts/mem.py", "visibility-upgrade"]
}
},
"flush": {
"description": "Flush local pending fallback files into PostgreSQL when the DB is back.",
"input": {},
"output": {
"description": "Confirmation that pending fallback files were replayed",
"fields": { "status": "ok | warn | error", "flushed_count": "integer" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "flush"],
"windows": ["python", "scripts/mem.py", "flush"]
}
},
"mirror-capture": {
"description": "Mirror changed decision-critical file sections into the selected project memory DB with fail-open behavior.",
"input": {
"file": { "type": "string", "required": true, "description": "Changed file path" },
"content": { "type": "string", "required": false, "description": "New file content" },
"content_file": { "type": "string", "required": false, "description": "Path containing new file content" },
"old_content": { "type": "string", "required": false, "description": "Previous file content" },
"old_content_file": { "type": "string", "required": false, "description": "Path containing previous file content" },
"config": { "type": "string", "required": false, "description": "Whitelist config path" },
"pattern": { "type": "string", "required": false, "description": "Additional whitelist glob pattern" },
"work_root": { "type": "string", "required": false, "description": "Optional root for relative whitelist matching" },
"db_target": { "type": "string", "required": false, "description": "Explicit project memory DB target" },
"log_path": { "type": "string", "required": false, "description": "Caller-configurable JSONL log path" },
"pane": { "type": "string", "required": false, "description": "Origin pane/session metadata" },
"dry_run": { "type": "boolean", "required": false, "default": false }
},
"output": {
"description": "Mirror result with changed sections, store ids, and fail-open warnings",
"fields": { "status": "ok | warn | error", "sections": "array", "store_ids": "array", "errors": "array" }
},
"entrypoints": {
"unix": ["python3", "scripts/memory_mirror.py", "capture"],
"windows": ["python", "scripts/memory_mirror.py", "capture"]
}
},
"reconcile-note-live": {
"description": "Reconcile live note decisions against memory backrefs before compact or close flows.",
"input": {
"note_file": { "type": "string", "required": true, "description": "Path to note_live style markdown" },
"db_target": { "type": "string", "required": false, "description": "Explicit project memory DB target" },
"log_path": { "type": "string", "required": false, "description": "Caller-configurable JSONL log path" },
"pane": { "type": "string", "required": false, "description": "Origin pane/session metadata" },
"dry_run": { "type": "boolean", "required": false, "default": false },
"strict": { "type": "boolean", "required": false, "default": false },
"store_missing": { "type": "boolean", "required": false, "default": true }
},
"output": {
"description": "Reconcile result including checked titles, missing backrefs, and auto-store ids",
"fields": { "status": "ok | warn | error", "checked_titles": "array", "missing_titles": "array", "store_ids": "array" }
},
"entrypoints": {
"unix": ["python3", "scripts/memory_mirror.py", "reconcile"],
"windows": ["python", "scripts/memory_mirror.py", "reconcile"]
}
},
"ingest-close-reports": {
"description": "Parse milestone close reports from inbox markdown and ingest them into episodic memory with dedup.",
"input": {
"inbox": { "type": "string", "required": true, "description": "Path to inbox markdown file" },
"dry_run": { "type": "boolean", "required": false, "default": false },
"limit": { "type": "integer", "required": false }
},
"output": {
"description": "Structured candidates, stored ids, and dedup skips",
"fields": { "status": "ok | error", "candidate_count": "integer", "candidates": "array", "stored_ids": "array", "skipped": "array" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "ingest-close-reports"],
"windows": ["python", "scripts/mem.py", "ingest-close-reports"]
}
},
"backfill-embeddings": {
"description": "Backfill missing vector embeddings for existing memories after pgvector repair.",
"input": {
"limit": { "type": "integer", "required": false, "default": 50 },
"model": { "type": "string", "required": false }
},
"output": {
"description": "Updated ids, skipped ids, and provider/model summary",
"fields": { "status": "ok | error", "updated_count": "integer", "updated_ids": "array", "skipped": "array" }
},
"entrypoints": {
"unix": ["python3", "scripts/mem.py", "backfill-embeddings"],
"windows": ["python", "scripts/mem.py", "backfill-embeddings"]
}
},
"myelin-search": {
"description": "Search the myelin affordance registry by intent/context and return top-k relevant wrappers/reflexes.",
"input": {
"intent": { "type": "string", "required": true, "description": "Intent label such as dispatch, inbox, or EP-status" },
"context": { "type": "string", "required": false, "description": "Free text or JSON context payload" },
"limit": { "type": "integer", "required": false, "default": 5 }
},
"output": {
"description": "Ranked affordance results with guard warnings and bridge metadata",
"fields": { "status": "ok | error", "results": "array", "warnings": "array", "bridge_contract": "object" }
},
"entrypoints": {
"unix": ["python3", "scripts/myelin_registry.py", "search", "{intent}"],
"windows": ["python", "scripts/myelin_registry.py", "search", "{intent}"]
}
},
"myelin-get": {
"description": "Get one affordance record with full metadata.",
"input": {
"id": { "type": "string", "required": true, "description": "Affordance identifier" }
},
"output": {
"description": "Affordance record",
"fields": { "status": "ok | error", "record": "object" }
},
"entrypoints": {
"unix": ["python3", "scripts/myelin_registry.py", "get", "{id}"],
"windows": ["python", "scripts/myelin_registry.py", "get", "{id}"]
}
},
"myelin-validate": {
"description": "Validate one affordance against args and guard raw-shell fallbacks.",
"input": {
"id": { "type": "string", "required": true },
"args": { "type": "string", "required": false, "description": "JSON args/context payload" }
},
"output": {
"description": "Validation result",
"fields": { "status": "ok | error", "valid": "boolean", "warnings": "array", "missing_required_context": "array" }
},
"entrypoints": {
"unix": ["python3", "scripts/myelin_registry.py", "validate", "{id}"],
"windows": ["python", "scripts/myelin_registry.py", "validate", "{id}"]
}
},
"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"]
}
},
"auto-write": {
"description": "Procedure template for automatically storing a memory after solving a non-obvious problem.",
"input": {},
"output": {
"description": "Proposed memory fields to store",
"fields": {"memory_type": "string", "category": "string", "title": "string", "tags_csv": "string", "importance": "integer", "content": "string"}
},
"entrypoints": {
"agent": "Follow scripts/auto-write-template.md"
}
},
"doctor": {
"description": "Report the current runtime capability map, memory plugin drift, memory DB target, OMO resolution, canonical evolution stores, table/routine readiness, and evolution ledger status.",
"input": {},
"output": {
"description": "Doctor report for the current runtime state",
"fields": {"status": "ok | warn | error", "doctor_report": "object"}
},
"entrypoints": {
"unix": ["python3", "scripts/runtime_doctor.py", "--format", "json"],
"windows": ["python", "scripts/runtime_doctor.py", "--format", "json"]
}
},
"debug-diagnose": {
"description": "Expose skill-system-debug diagnose through the unified MCP server.",
"input": {
"symptom": { "type": "string", "required": true },
"context": { "type": "string", "required": false }
},
"output": {
"description": "Structured diagnosis payload",
"fields": { "status": "ok | error", "result": "object" }
},
"entrypoints": {
"agent": "Use the debug_diagnose MCP tool from skills/skill-system-memory/mcp/server.py"
}
},
"eda-profile": {
"description": "Expose skill-system-eda dataset profiling through the unified MCP server.",
"input": {
"input_path": { "type": "string", "required": true },
"sample": { "type": "integer", "required": false },
"target": { "type": "string", "required": false }
},
"output": {
"description": "EDA profile output",
"fields": { "status": "ok | error", "profile_path": "string", "report_path": "string" }
},
"entrypoints": {
"agent": "Use the eda_profile MCP tool from skills/skill-system-memory/mcp/server.py"
}
},
"gate-validate": {
"description": "Expose skill-system-gate validation through the unified MCP server.",
"input": {
"rules": { "type": "string", "required": false },
"artifact_root": { "type": "string", "required": false }
},
"output": {
"description": "Gate validation summary",
"fields": { "status": "ok | error", "passed": "boolean", "results": "array" }
},
"entrypoints": {
"agent": "Use the gate_validate MCP tool from skills/skill-system-memory/mcp/server.py"
}
},
"rebuild": {
"description": "Rebuild full agent context after compact or memory loss.",
"input": {
"user": { "type": "string", "required": false },
"recent_limit": { "type": "integer", "required": false }
},
"output": {
"description": "Soul, preferences, recent memories, and pending decisions",
"fields": { "status": "ok | error", "rebuild_context": "object" }
},
"entrypoints": {
"agent": "Use the memory_rebuild MCP tool from skills/skill-system-memory/mcp/server.py"
}
}
},
"stdout_contract": {
"last_line_json": true
},
"mcp": {
"server": {
"name": "skill-system",
"description": "Unified skill-system MCP server exposing memory, myelin, debug, eda, gate, and memory_rebuild tools",
"entrypoint": "python skills/skill-system-memory/mcp/server.py",
"transport": "stdio",
"tools": ["memory_search", "memory_store", "memory_auto_match", "memory_context", "memory_status", "memory_sync", "memory_export", "myelin_search", "myelin_get", "myelin_validate", "debug_diagnose", "eda_profile", "gate_validate", "memory_rebuild"],
"resources": ["memory://schema", "memory://status"]
}
}
}
说明:
- Router 要求每个步骤都打印最后一行 JSON。
- 这些 Router 适配器脚本与
mem.sh/mem.ps1分开,以避免破坏现有工作流。
Memory Mirror 引擎(SK-005)
scripts/memory_mirror.py 是由 SK 负责的故障开放引擎,用于自动镜像记忆并在压缩前进行协调。
python3 scripts/memory_mirror.py capture --file Work/note/note_live.md --content-file /tmp/new.md --old-content-file /tmp/old.md --db-target Work-memory --log-path Work/.tkt/memory-mirror.log
python3 scripts/memory_mirror.py reconcile --note-file Work/note/note_live.md --db-target Work-memory --log-path Work/.tkt/memory-mirror.log
- 默认白名单位于
memory-mirror-config.yaml - Work 负责的包装器应明确传入
--db-target Work-memory - 结构化日志输出为 JSONL,且可由调用方配置
- 决策日志事务加固契约见
memory-mirror-contract.md
Close Report 摄取
./sk mem ingest-close-reports --inbox /share/nas165/arthur0824hao/Work/.tkt/inbox/hermes/inbox.md --dry-run
./sk mem ingest-close-reports --inbox /share/nas165/arthur0824hao/Work/.tkt/inbox/hermes/inbox.md
- 目的:将里程碑关闭/阻塞报告转为可搜索的情景记忆
- 去重:使用 bundle id + actor + timestamp + report status 作为摄取键
- 操作手册:
close-report-ingestion-runbook.md
向量 / 嵌入健康状态
memory_status 现在将语义/向量检索视为受能力门控的可选健康功能:
pgvector_enablement_status:enabled | disabled | unavailable-on-hostpgvector_blocker:不可用时的确切主机/安装阻碍embedding_dependency_installed:本地嵌入运行时是否存在semantic_search_mode:hybrid-ready | hybrid-schema-no-vectors | vector-installable-but-disabled | fts-trgm-only
当 pgvector 或 sentence-transformers 不存在时,FTS + pg_trgm 回退仍是默认安全路径。
语义检索修复命令
SKILL_PGDATABASE=Work-memory python3 scripts/mem.py backfill-embeddings --limit 100
SKILL_PGDATABASE=Work-memory python3 scripts/semantic_smoke.py --db-target Work-memory
- 加载 sentence-transformers 模型时,
mem.py现在默认禁用 HuggingFace Xet,以避免 CAS 重试故障;该故障曾阻止在当前 MCP 环境中冷下载all-MiniLM-L6-v2。 semantic_smoke.py会存储一条改述后的语义记忆,并用一种非平凡的表述查询它,以验证混合检索路径。
Codex MCP 传输恢复备用方案
如果原生 MCP 会话报告 Transport closed,请先在 MCP 之外使用规范 CLI/脚本:
python3 scripts/mcp_health_probe.py --db-target Work-memory --tool-error "Transport closed"
python3 scripts/mem_work.py status
python3 scripts/mem_work.py search "Hermes inbox triage latest 14:35 Talos Sisyphus Daedalus memory MCP fallback mem.py" --limit 5
python3 scripts/mem_work.py store --type episodic --category scratch --title "transport recovery check" --content "explicit fallback path" --scope project
mem_work.py是对规范mem.py的轻量封装- 它会注入
SKILL_PGDATABASE=Work-memory、PGDATABASE=Work-memory、PGHOST=localhost和PGPORT=5432 - Finch/Wren 的备用方案请使用它,无需每次手动输入环境变量
恢复规则(故障时关闭):
- 如果
mcp_health_probe.py返回diagnosis=client_transport_stale,则无法纯粹在服务端修复当前客户端/工具传输。 - 不要盲目终止记忆 MCP 进程,也不要重启无关的窗格。
- 仅重启受影响的客户端会话/工具传输(经操作员批准),然后重新验证:
- MCP
memory_status恢复正常 python3 scripts/mem_work.py status保持健康nvidia-smi --query-compute-apps显示 GPU0 上没有skill-system-memory支持上下文
- MCP
Myelin Registry + ANS Bridge
scripts/myelin_registry.py 将 SK MCP 转换为髓鞘索引/可供性接口。
python3 scripts/myelin_registry.py build --output artifacts/myelin-registry.json
python3 scripts/myelin_registry.py search dispatch --context '{"pane":"dev_coder:SK-coder","message_file":"/tmp/spec.txt"}' --limit 3
python3 scripts/myelin_registry.py get dispatch:hermes-dispatch
python3 scripts/myelin_registry.py validate cli:raw-tmux-sendkeys --args '{"pane":"dev_coder:SK-coder","message":"hi","intent":"dispatch","urgent":false}'
- 元数据架构:
myelin-registry.schema.yaml - 预置的高价值可供性:
myelin-seeds.yaml - ANS 事件/响应契约:
ans-myelin-bridge-contract.yaml - 策略:索引所有可供性,仅按意图/上下文注入最相关的 top-k 项
可视化记忆(Markdown 导出)
如果查询 PostgreSQL 对日常使用来说太不方便,可以将记忆导出到 ./Memory/ 下的 Markdown 文件中(默认使用当前目录):
bash "<skill-dir>/scripts/sync_memory_to_md.sh" --out-dir "./Memory"
输出:
Memory/Long.md(语义 + 程序性)Memory/Procedural.md(仅程序性)Memory/Short.md(摩擦 + 每日压缩 + 程序性要点)Memory/Episodic.md(情景性)
备份:
- 备份存储在
Memory/.backups/下,以避免git status输出过多内容。 - 使用
--no-backup禁用备份。
如果 Memory/.gitignore 不存在,同步脚本也会创建该文件(忽略 .backups/ 和 SYNC_STATUS.txt)。
长记忆索引:
Memory/Long.md包含一个Index部分(主要类别 + 标签),便于浏览导出内容。
search_memories(query, types[], categories[], tags[], agent_id, min_importance, limit)
混合搜索:全文搜索(tsvector)+ 三元组相似度(pg_trgm)+ 标签筛选。
接受自然英语查询——无需 tsquery 语法。
相关性评分: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_type
其中 match_type 的值包括:fulltext、trigram_title、trigram_content、metadata。
memory_health_check()
返回 metric | value | status,对应 total_memories、avg_importance、stale_count。
apply_memory_decay()
按 0.9999^days_since_access 衰减情景记忆。每日运行。
prune_stale_memories(age_days, max_importance, max_access_count)
软删除低于阈值的陈旧情景记忆。默认值:180 天、重要性 <= 3、从未访问。
Agent 工作流
自动写入模板
修复 bug 或解决非显而易见的问题后,使用标准模板存储记忆:
- 流程:
scripts/auto-write-template.md
最佳实践:优先使用
mem.pywrapper,避免 shell quoting 与认证问题。 Raw SQL 范例请见 Appendix: Raw SQL。
任务开始前
# 自動撈出相關記憶摘要(推薦)
python3 scripts/mem.py context "keywords from user request"
# 或搜尋並手動閱讀
python3 scripts/mem.py search "keywords from user request" 5
如果找到相关记忆,请引用它们:“根据以往经验(记忆 #1)……”
解决问题后
python3 scripts/mem.py store semantic category-name "One-line problem summary" \
"tag1,tag2,tag3" 8 --content "Detailed problem + solution"
委派给子 Agent 时
在提示词中包含:
MUST DO FIRST:
python3 scripts/mem.py context 'relevant keywords'
MUST DO AFTER:
If you solved something new:
python3 scripts/mem.py store semantic <category> '<title>' '<tags>' <importance> --content '<solution>'
检查记忆系统健康状况
python3 scripts/mem.py status
任务记忆层(可选)
此技能还提供一个受 Beads 启发的精简任务/问题层:图语义 + 确定性的“就绪任务”查询。
对象:
agent_tasks:任务(状态、优先级、负责人)task_links:类型化链接(blocks、parent_child、related等)blocked_tasks_cache:物化缓存,用于加快就绪任务查询task_memory_links:将任务链接到记忆(agent_memories),以记录结果/备注
创建任务:
INSERT 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_blocks(尚未实现)
- 这是有意推迟的,直到核心工作流足够稳定。
- 如果现在就需要,可将条件存储在
task_links.metadata中(例如,{ "os": "windows" }),并将其作为文档说明处理。
包装脚本(推荐)
为避免反复输入 SQL,请使用此技能附带的包装脚本:
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-1
Linux/macOS:
bash "scripts/tasks.sh" ready 50
bash "scripts/tasks.sh" create "Install pgvector" 1
bash "scripts/tasks.sh" claim 2 agent-1
压缩日志(高价值)
压缩可能会删除上下文。请将每次压缩都视为重要事件并记录下来。
如果你使用 OpenCode,建议优先采用 OpenCode 插件方式自动记录压缩日志。
OpenCode 插件(experimental.session.compacting)
- 将
plugins/skill-system-memory.js和plugins/runtime_sync.js复制到~/.config/opencode/plugins/ - 重启 OpenCode
它会将本地压缩事件写入:
~/.config/opencode/skill-system-memory/compaction-events.jsonl
它还会尽力写入 Postgres store_memory(...)(需要 pgpass)。
验证
SELECT id, title, relevance_score
FROM search_memories('compaction', NULL, NULL, NULL, NULL, 0, 10);
如果没有插入任何内容,请设置 .pgpass / pgpass.conf,以便 psql 无需提示即可进行身份验证。
每日压缩整合
原始压缩事件内容杂乱。请运行每日整合作业,将多个压缩事件合并为一条每日记忆。
整合脚本默认使用 OpenCode 插件事件日志路径。
- OpenCode 事件:
~/.config/opencode/skill-system-memory/compaction-events.jsonl - 输出目录:
~/.config/opencode/skill-system-memory/compaction-daily/
Windows 手动运行:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\consolidate-compactions.ps1"
Linux/macOS 手动运行:
bash "scripts/consolidate-compactions.sh"
计划任务:
- Windows 任务计划程序:创建一个每日任务,运行上方的 PowerShell 命令
- Linux cron 示例:
# every day at 02:10 UTC
10 2 * * * bash "<skill-dir>/scripts/consolidate-compactions.sh" >/dev/null 2>&1
摩擦日志(将痛点转化为工具)
每当遇到令人烦恼、脆弱或失败的情况时:
- 存储一条类别为
friction、标签包含工具/操作系统/错误信息的episodic记忆。 - 如果重复出现(2 次以上),将其提升为
procedural记忆(重要性 >= 7),并附上检查清单。 - 当修复方案成为稳定的规则/工作流时,更新此技能文档(让每个 Agent 都能学到)。
架构概览
agent_memories — 通用事件日志。全文搜索、三元组索引、JSONB 元数据、软删除。
soul_states — 每位用户一行。包含结构化的个性/情绪/缓冲区 JSONB。外键 → agent_memories。
insight_facets — 每个会话的特征,包含结构化字段。外键 → agent_memories。
evolution_snapshots — 带有变更 JSONB 的版本化演进记录。外键 → agent_memories。当前状态:用于提案持久化的 LEGACY_COMPAT_SURFACE,同时仍用于快照/版本历史记录。
user_preferences — 带有置信度分数的键值型用户偏好。
memory_links — 图关系(引用、取代、矛盾)。
working_memory — 带自动过期机制的临时会话上下文。
类型化表函数(同时写入类型化表和 agent_memories):
upsert_soul_state(user, yaml, personality, emotion, ...)→ soul_statesinsert_insight_facet(user, session_id, yaml, ...)→ insight_facetsinsert_evolution_snapshot(user, version_tag, target, ...)→ evolution_snapshotsupsert_user_preference(user, key, value, source, confidence)→ user_preferencesget_soul_state(user)、get_recent_facets(user, limit)、get_evolution_history(user, limit)、get_user_preferences(user)→ 类型化读取get_agent_context(user, facet_limit)→ 用于插件注入的聚合上下文
目前没有由代码仓库支持的 migrate-typed-tables.sql 文件。请将旧版类型化表回填视为已延期;不要声称它是受支持的迁移路径。
可选的 PostgreSQL 优先运行时投影表(session_summaries、project_summaries、context_rollups、behavior_*)由 migrate-v2-postgres-first.sql 创建,前提是你明确选择启用该功能。
关键列:memory_type、category、tags[]、title、content、content_hash(自动生成)、metadata(JSONB)、importance_score、access_count、relevance_decay、search_vector(自动生成)。
反模式
| 不要 | 应该这样做 |
|---|---|
| 什么都存 | 只存储不明显的解决方案 |
| 不添加标签 | 全面添加标签:技术、错误代码、平台 |
直接使用 to_tsquery | search_memories() 会通过 plainto_tsquery 处理 |
| 所有数据只用一种类型 | 根据内容使用正确的 memory_type |
| 忘记重要性评分 | 如实评分:9-10 表示经过实战验证,5-6 表示部分验证 |
注意事项
| 问题 | 严重性 | 缓解措施 |
|---|---|---|
| 分块会丢失上下文 | 严重 | 将完整的问题和解决方案作为一个整体存储 |
| 过时的技术记忆 | 高 | 每天运行 apply_memory_decay();清除过时内容 |
| 重复记忆 | 中 | store_memory() 会根据 content_hash 自动去重 |
| 无向量搜索 | 信息 | pg_trgm 提供模糊匹配;之后可添加 pgvector |
跨平台说明
- PostgreSQL 14-18 受支持(不使用分区或 GENERATED ALWAYS)
- pg_trgm 是唯一必需的扩展(随所有 PG 发行版提供)
- Linux:
psql -U postgres -d <project>-memory -f init.sql - Windows:使用 psql.exe 的完整路径,或将 PG bin 添加到 PATH
- MCP postgres_query:可用于读取操作;DDL 需要使用 psql
维护
SELECT 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(); -- anytime
可选:pgvector 语义搜索
如果 PostgreSQL 服务上已安装 pgvector,init.sql 将会:
- 创建扩展
vector(若缺失则不会导致失败) - 添加
agent_memories.embedding vector(维度可变) - 创建
search_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);
注意:pgvector 索引无法为维度可变的向量建立索引。为了支持嵌入维度不同的本地模型,这是一个权衡。
如果未安装 pgvector,其他所有功能仍可正常工作(fts + pg_trgm)。
嵌入向量摄取管道
只有填充 agent_memories.embedding 后,pgvector 搜索才能正常工作。
此技能附带摄取脚本(相对路径)。请在技能目录中运行:
scripts/ingest-embeddings.ps1scripts/ingest-embeddings.sh
这些脚本会:
- 查找
embedding IS NULL的记忆 - 调用兼容 OpenAI 的嵌入向量 API 端点(包括 Ollama)
- 将向量写入
agent_memories.embedding vector
要求:
- 已安装 pgvector 且已应用
init.sql(以便agent_memories.embedding存在) - 已配置
.pgpass/pgpass.conf(以便psql -w无需提示即可写入) - 嵌入向量 API 环境变量:
EMBEDDING_PROVIDER(ollama或openai;默认值为openai)EMBEDDING_API_KEY(openai必需;ollama可选)EMBEDDING_API_URL(默认值取决于提供方)EMBEDDING_MODEL(默认值取决于提供方)EMBEDDING_DIMENSIONS(可选;如果嵌入向量 API 端点支持,则会将其转发)
Windows 示例:
$env:EMBEDDING_PROVIDER = "ollama"
$env:EMBEDDING_MODEL = "nomic-embed-text"
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "scripts\ingest-embeddings.ps1" -Limit 25
Linux/macOS 示例:
export EMBEDDING_API_KEY=...
export EMBEDDING_MODEL=text-embedding-3-small
bash "scripts/ingest-embeddings.sh"
调度:
- 添加新记忆后,每天(或每小时)运行一次
- 在确认其可靠之前,将
Limit设为较小值
稳健性说明:
- 在 Windows 上,通过
psql -c传递很长的 SQL 字符串可能不可靠。摄取脚本会将逐行更新写入临时.sql文件,并运行psql -f,以避免命令行长度和引号处理方面的边界问题。
相关技能
systematic-debugging、postgres-pro、postgresql-table-design
共享数据库模式需要在运行时切换角色:
- 使用连接器凭据连接
- 每个请求执行一次
SET ROLE visitor_<identity> - 仅在 Hermes/管理员跨项目审计流程中使用
--all-scopes