跨客户端便携式记忆插件包:OpenViking Agent Plugins 1.0 结构、安装与实现剖析
OpenViking 在仓库根目录提供了 agent-plugins/ 这一套基于 Agent Plugins 1.0 规范打包的插件包,用于把 OpenViking 的长期语义记忆与上下文能力交付给各类 AI 编码客户端。本文以 agent-plugins/README.md 为主线,完整讲解插件包的目录组成、plugin.json / mcp.json 清单结构、stdio 代理设计动机、凭据解析优先级,并结合仓库源码(servers/config.mjs、plugin.test.mjs、skills/openviking-memory/SKILL.md 等)揭示其底层实现与可验证细节。读完你将掌握:如何把 OpenViking 记忆能力装载进 Cursor、VS Code 等任何遵循 Agent Plugins 1.0 的客户端,以及为什么这套包内部要用一个 stdio 代理去对接服务端的 /mcp。
一、Agent Plugins 1.0 是什么,这个包是什么
Agent Plugins 1.0 是一种与厂商无关的 AI 编码 Agent 扩展打包格式,由 Amazon、Cursor、Microsoft、OpenAI、Vercel 等生态共同推动。一个插件本质上就是一个普通目录,具备三要素:
plugin.json清单(manifest),声明插件的元数据;skills/下的 Agent Skills,可被客户端自动发现;mcp.json中可选声明的 MCP 服务器。
因此,同一个包可以被任何遵循该规范的客户端(Cursor、VS Code,以及 Amazon/OpenAI 一端的客户端等)以完全相同的方式加载。OpenViking 的 agent-plugins/ 目录正是这样一份"即插即用"包,目标是把 OpenViking 的长期语义记忆与上下文能力带给编码 Agent。
目录结构速览
plugin.json # Agent Plugins 1.0 清单
mcp.json # stdio MCP 服务器声明:"openviking"
servers/mcp-proxy.mjs # stdio -> streamable-HTTP 代理,转发到 OV 服务端 /mcp
servers/config.mjs, debug-log.mjs # 凭据/配置解析(改编自 claude-code-memory-plugin)
servers/shared/ # 由 examples/memory-plugin-shared/lib 生成(不要在此修改)
skills/openviking-memory/SKILL.md # 教模型"召回 + 持久化"闭环的技能文件
plugin.test.mjs # node --test 合规检查
该包零 npm 依赖,代理与测试全部基于 Node.js 标准库运行(需要 Node 18+,因为要用到全局 fetch,见 shared/mcp-proxy-core.mjs 中"global fetch is required"的显式校验)。
二、清单文件结构:plugin.json 与 mcp.json
plugin.json 是插件包的"身份证"。仓库中的 plugin.json 内容如下:
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "openviking",
"version": "0.1.0",
"description": "Semantic long-term memory and context engine for coding agents. Recall prior knowledge with the find/search/read MCP tools and persist durable facts with remember/write, backed by an OpenViking server.",
"author": {
"name": "Volcano Engine"
},
"homepage": "https://github.com/volcengine/OpenViking",
"license": "AGPL-3.0",
"keywords": ["memory", "long-term-memory", "context-engine", "semantic-search", "mcp", "openviking"]
}
说明几点:
name是客户端标识插件的关键字段,必须为 1–64 个字符的小写字母数字串,允许连字符与句点,但不能出现连续分隔符、不能以分隔符开头或结尾(详见 plugin.test.mjs 的NAME_RE正则校验);version必须是严格 semver;- 规范约束了
plugin.json根级字段集合:$schema、name、version、description、author、homepage、repository、license、keywords、extensions。测试文件用PLUGIN_ALLOWED_KEYS集合逐项断言,任何多余字段都会被拒绝(plugin.test.mjs)。
mcp.json 声明随插件一起注册的 MCP 服务器:
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"openviking": {
"type": "stdio",
"command": "node",
"args": ["${PLUGIN_ROOT}/servers/mcp-proxy.mjs"]
}
}
}
关键点:MCP 服务器名为 openviking,类型是 stdio,命令为 node(必须是单一可执行令牌,不能含空格或 shell 拼接),参数中的 ${PLUGIN_ROOT} 占位符由规范客户端展开为插件目录绝对路径。合规测试会校验这些占位符展开后必须仍然位于插件根目录内,防止路径逃逸(plugin.test.mjs)。
三、为什么用 stdio 代理,而不是直接声明 streamable-http
OpenViking 服务端本身已经在 /mcp 提供 streamable HTTP 协议的 MCP 端点,但规范要求"可移植",直接在 mcp.json 里声明 streamable-http 类型会撞上两个现实问题:
- 服务器 URL 是随部署变化的——本地用户是
http://127.0.0.1:1933,远程用户是另一个端点,写死在清单里就无法跨用户分发; - Agent Plugins 规范禁止在
mcp.json静态headers映射中携带凭据,而访问 OpenViking 往往需要 API Key。
stdio 代理同时解决这两点:它由客户端以本地子进程方式启动(node ${PLUGIN_ROOT}/servers/mcp-proxy.mjs),运行时才从与 ov CLI 相同的本地配置源解析 URL 与 API Key,逐请求注入后,将客户端发来的 JSON-RPC 原样转发到服务端 streamable HTTP 端点。对客户端而言它只是一个普通 stdio MCP 服务器;对服务端而言它只是又一位 streamable-HTTP 调用者。代理同时保持 stdout 通道干净,只走 MCP 协议帧,调试日志另走文件。
从源码看,代理的主干调用链是:mcp-proxy.mjs → loadConfig()(config.mjs)→ buildMcpProxyConfig(...)(shared/mcp-proxy-config.mjs)→ createOpenVikingMcpProxy(...).start()(shared/mcp-proxy-core.mjs)。
四、安装步骤与客户端接入
安装前提是一个可访问的 OpenViking 服务端(服务端启动方式见快速开始文档,本地默认端点是 http://127.0.0.1:1933),随后:
- 让遵循 Agent Plugins 规范的客户端指向本目录(各客户端有自己的安装命令或插件目录,详见其文档)。客户端会完成两件事:
- 依据
mcp.json注册openvikingMCP 服务器——也就是以 stdio 方式运行node <plugin>/servers/mcp-proxy.mjs; - 从
skills/发现openviking-memory技能。
- 依据
- 按下一节配置凭据,然后开启一个新会话。
会话建立后,模型即可获得 find / search / read / remember / write 等 OpenViking MCP 工具。语义搜索时用 search 并传 mode="context",可获得由服务端按 token 预算组装好的上下文块,而不是一长串原始命中。
技能所教的"召回 + 持久化"闭环
没有 hook 的客户端不会自动抓取会话,因此 skills/openviking-memory/SKILL.md 承担了"教模型主动使用记忆"的责任。它的核心工具按职责划分如下:
| 类别 | 工具 | 用途 |
|---|---|---|
| 召回 | find、search、read、list、grep、glob |
核心集,所有部署都有 |
| 持久化 | remember、add_resource |
核心集 |
| 维护 | forget、health |
核心集 |
| 可选 | tree、write、edit、list_watches、cancel_watch |
依赖服务端版本与托管模式 |
任务开始时的召回流程:先判断任务是否值得检索(可执行/多步骤工作、可能接触过该系统的工作、故障恢复需要;闲聊和一次性问答则跳过);用任务目标、领域对象、预期操作与约束拼一条简洁 query;用 find(快、按相关度排序,返回 URI + 摘要 + 分数)且 limit 取 5–10 左右,需要更深入意图分析或想要服务端组装上下文时改用 search;在 list 模式下可用 target_uri 收窄范围,例如用 viking://~/memories/experiences 检索历史任务经验;最后针对 1–3 个可能改变执行方式的确切文件 URI 调 read,忽略 .abstract.md、.overview.md、.relations.json 这类 sidecar 文件。
工作期间与结束时的持久化:由于没有自动捕获,遇到值得保留的信息必须在同一会话内存下。remember(messages) 是默认方式,把关键对话或短事实摘要以带角色的消息传入,服务端自行抽取并归档为记忆(偏好、实体、事件、经验);add_resource 用于导入外部文档或 URL 成为可检索资源;需要精确文档且 write/edit 可用时(已知位置如 viking://~/ 个人根或 viking://resources/ 共享资料),用它们覆盖精确写入需求,否则退回 remember。
应持久化的内容:稳定的偏好与约定、环境事实、带理由的决策、可复用的流程或修复方案。不应持久化的:密钥与凭据、瞬态状态、臆测、整段对话转储——只存结论,不存滚动日志。
五、凭据解析:环境变量 → ovcli.conf → ov.conf → 默认值
代理与 OpenViking 的 ov CLI 及其他插件遵循同一条凭据解析链,优先级从高到低:
- 环境变量:
OPENVIKING_URL(或OPENVIKING_BASE_URL)、OPENVIKING_API_KEY(或OPENVIKING_BEARER_TOKEN)、OPENVIKING_ACCOUNT、OPENVIKING_USER、OPENVIKING_PEER_ID; ~/.openviking/ovcli.conf(CLI 客户端配置,字段url、api_key、account、user),可用OPENVIKING_CLI_CONFIG_FILE覆盖路径;~/.openviking/ov.conf的server段(本地服务端配置,字段url或host/port、root_api_key),可用OPENVIKING_CONFIG_FILE覆盖路径;- 默认值:
http://127.0.0.1:1933,无鉴权(本地模式)。
两份配置文件都按 JSON 解析。一个带 server 段和 CLI 配置的示意如下:
// ~/.openviking/ovcli.conf —— 优先级更高,通常由 ov CLI 侧维护
{
"url": "http://127.0.0.1:1933",
"api_key": "<your-api-key>",
"account": "<account>",
"user": "<user>"
}
// ~/.openviking/ov.conf —— 服务端配置文件中的 server 段
{
"server": {
"url": "http://127.0.0.1:1933",
"root_api_key": "<root-key>"
}
}
解析逻辑在 config.mjs 中有更细的实现,可印证几个边界行为:
- baseUrl 构造:优先环境变量 →
ovcli.url→ov.server.url;若都没有,再取ov.server.host/port拼成http://{host}:{port}(端口默认 1933,host 中的0.0.0.0会被替换为127.0.0.1),末尾多余的/会被剥掉(config.mjs); - apiKey 解析:
OPENVIKING_BEARER_TOKEN与OPENVIKING_API_KEY二选一(发送时都作为 Bearer),然后依次是ovcli.api_key、ov.server.root_api_key(config.mjs); - 超时:
OPENVIKING_TIMEOUT_MS可调,默认 15000 ms,且下限被钳制为 1000 ms(config.mjs); - 布尔环境变量:
OPENVIKING_DEBUG接受0/1/false/true/no/yes(config.mjs); - 配置热更新:代理每次请求前重新调用
loadConfig(),配置文件变动无需重启即可被新请求感知(readProxyConfig为每次请求动态取配置)。
调试手段
设置 OPENVIKING_DEBUG=1 可开启调试,代理会以 JSON Lines 格式写日志到 ~/.openviking/logs/agent-plugins.log(日志记录格式为 { ts, hook, stage, data } 或 { ts, hook, stage, error },可通过 OPENVIKING_DEBUG_LOG 覆盖路径;未开启时 log()/logError() 是零开销的空操作)。这两点分别见 config.mjs 与 shared/debug-log.mjs 的注释说明。
六、插件包的边界:做什么与不做什么
本包是"便携的召回 + 写入面":技能 + MCP 工具,由模型驱动。Agent Plugins 1.0 规范刻意排除了 hooks、commands、agents,因此自动会话捕获与自动的 prompt 前召回都不在本包范围内——openviking-memory 技能改为教模型自己在任务开始时召回、在任务中用 remember/write 持久化关键事实。
如果你的宿主环境有 hook 机制,建议优先选择各专用插件,因为基于 hook 的召回与捕获不消耗工具调用、也不依赖模型"自觉去记忆"。仓库中同名安装脚本一次覆盖 Claude Code、Codex、Cursor、TRAE / TRAE CN、ZCode、OpenCode 与 pi 等宿主,支持交互式选择语言、宿主、下载源与凭据,且可重复执行(脚本本体位于 examples/memory-plugin-shared/install.sh)。对应各宿主目录包括:
- claude-code-memory-plugin(Claude Code)
- codex-memory-plugin(Codex)
- opencode-plugin(OpenCode)
- cursor-memory-plugin、trae-memory-hooks、zcode-memory-plugin 等
而本 Agent Plugins 包适用于两类场景:宿主没有任何 hook;或者你希望一份包能在尽量多的客户端间通用加载。依照规范,客户端特定的集成后续也可放进本包内反向域名命名的子目录(如 com.example.client/)或清单的 extensions 对象里,且不影响其他客户端。
可选工具与托管模式的差异
可选工具的可用性取决于服务端版本与托管形态,references/optional-tools.md 给出汇总表:
| 工具 | 服务端要求 | 托管云服务 |
|---|---|---|
tree |
≥ 0.4.14 | 云滚动到 0.4.14 后 |
write、edit |
≥ 0.4.14 | 云滚动到 0.4.14 后 |
list_watches、cancel_watch |
≥ 0.3.18,自托管/私有 | 不暴露 |
托管云是无状态多实例服务,因此账户级的有状态工具(list_watches、cancel_watch)即使底层版本已具备也会被裁剪。技能文件中明确约束:只有当某个可选工具真实出现在当前会话注册的工具列表里时,才能使用它;绝不调用未注册工具,也不要退回裸 HTTP。tree 用于在陌生作用域中快速建立目录感;write 负责在已知 URI 替换/追加/新建文件(新建要求父目录已存在);edit 做目标字符串替换,建议先 read 避免内容过期;list_watches/cancel_watch 管理由带 watch 间隔的 add_resource 创建的自动刷新订阅。
七、开发与质量保障:合规测试与共享库同步
本包自带无依赖的合规测试,运行方式:
node --test agent-plugins/plugin.test.mjs
plugin.test.mjs 逐项断言了以下内容,既是 CI 守护,也是理解 Agent Plugins 1.0 规范的活教材:
plugin.json根字段封闭性、name命名规则、semverversion、author/keywords/description/license完整性;mcp.json与plugin.json的$schema规范版本一致;mcpServers类型只能是stdio或streamable-http;streamable-http的 headers 不得出现authorization/api_key/token/secret/cookie等凭据字样;stdio的command必须是单令牌、且${PLUGIN_ROOT}占位符展开后不得逃逸插件根目录;- 每个
skills/*子目录都必须有带name+descriptionfrontmatter 的SKILL.md,且name与目录名一致; SKILL.md内的相对 Markdown 链接必须真实解析到文件;- 插件内所有
.mjs文件通过node --check语法检查,且mcp-proxy.mjs的 import 均存在。
需要特别提醒的仓库维护约定:servers/shared/*.mjs 是从 examples/memory-plugin-shared/lib 逐字拷贝生成的,不要在本目录内直接编辑它们。本目录是共享库同步脚本的目标之一,需要刷新时运行:
node examples/memory-plugin-shared/sync.mjs
examples/memory-plugin-shared/sync.test.mjs 会在内容漂移时失败。servers/config.mjs、servers/debug-log.mjs、servers/mcp-proxy.mjs 则改编自 claude-code-memory-plugin(只保留连接相关字段,丢弃 hook 调优旋钮——因为本规范没有 hooks);改动代理行为时需同步到那边。本包与 sync 测试文件都由 .github/workflows/pr.yml 在 CI 中执行。
结语:什么时候选它,什么时候不选
一句话总结选型:宿主无 hook、或想要一份跨客户端通用的包时,用本 Agent Plugins 包;宿主具备 hook 能力且希望零工具调用成本地自动召回与会话捕获时,优先选用 examples/memory-plugin-shared/install.sh 覆盖的 claude-code-memory-plugin、codex-memory-plugin、opencode-plugin、cursor-memory-plugin 等专用插件。
本包的核心设计可归纳为三句话:用 Agent Plugins 1.0 清单换取生态级可移植性;用 stdio 代理换取"URL 与凭据按部署解析"的运行时灵活性;用内嵌技能把无 hook 场景下的召回 + 持久化闭环明确教给模型。理解 mcp.json → servers/mcp-proxy.mjs → servers/config.mjs → skills/openviking-memory/SKILL.md 这条链路,你就能在任何 Agent Plugins 客户端中快速复现、调试或二次接入这套 OpenViking 记忆方案。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00