OpenViking Agent Plugins 深度解读:openviking-memory Skill 如何用 MCP 工具构建可复现的 Agent 长期记忆回路
OpenViking 把 Agent 记忆、知识 RAG 与技能统一在一个“自进化上下文数据库”中,而 agent-plugins/skills/openviking-memory/SKILL.md 正是让 AI 编码客户端“会自己用这套记忆系统”的关键技能文件。本文以该 SKILL 为主体,完整解析其召回(Recall)与持久化(Persist)双循环的设计、核心工具集与可选工具矩阵,并结合 openviking/server/mcp_endpoint.py 的服务端工具定义和 agent-plugins/plugin.test.mjs 的合规测试,说明这套技能包如何在无 hooks 的 Agent Plugins 1.0 规范下跑通“任务开始先检索、任务结束再沉淀”的记忆闭环。读完后,你可以掌握该技能的使用边界、工具选择策略,以及它所在的 Agent Plugins 包的加载与凭据机制。
一、技能定位:viking:// 寻址的语义记忆,由模型主动驱动
SKILL.md 开篇给出两条基本事实:
- OpenViking 是一个以
viking://URI 寻址的长期语义记忆存储; - 该客户端没有生命周期 hooks——召回与捕获都不会自动发生,模型必须用
openvikingMCP 工具亲自驱动“循环”的两半。
这是理解整个技能的前提。Agent Plugins 1.0 规范刻意排除了 hooks、commands 和 agents,因此 Claude Code 等带 hook 体系的客户端上那种“提示词前自动召回、对话结束后自动捕获”做不了,agent-plugins/README.md 也明确声明了这一点:
Agent Plugins 1.0 deliberately excludes hooks, commands, and agents, so automatic conversation capture and automatic pre-prompt recall are out of scope here.
作为替代,openviking-memory 这个 skill 的职责是教会模型一套操作纪律:在实质性任务(编码、配置、调试、多步或工具型工作)开始时检索相关历史知识,在工作过程中或结束后用 remember 把值得长期保留的事实、偏好、决策与教训沉淀下来。SKILL.md 的 frontmatter description 字段正是这套纪律的浓缩版触发说明——实质性任务开始时召回,日常闲聊和模型可直接回答的简单事实问题则不使用。
这个 frontmatter 本身是被强校验的:plugin.test.mjs 会要求每个 skills/<child>/SKILL.md 都以 YAML frontmatter 开头、包含 name 与 description 字段,且 name 必须与目录名一致(openviking-memory),并符合小写字母数字加连字符/点的命名正则。
二、核心工具集与可选工具集
SKILL.md 将 OpenViking MCP 工具分为两层:核心工具集(所有受支持部署都可用)与可选工具集(取决于服务端版本与托管模式)。
2.1 核心工具:Recall / Persist / Maintain 三组
| 分组 | 工具 | 用途 |
|---|---|---|
| Recall(召回) | find、search、read、list、grep、glob |
检索与读取记忆 |
| Persist(持久化) | remember、add_resource |
沉淀记忆 / 导入外部资源 |
| Maintain(维护) | forget、health |
删除条目 / 健康检查 |
服务端这些工具都是 openviking/server/mcp_endpoint.py 中真实定义的异步函数,可以在源码中逐一确认:find(mcp_endpoint.py#L249)、search(mcp_endpoint.py#L276)、read(mcp_endpoint.py#L501)、grep(mcp_endpoint.py#L1267)、glob(mcp_endpoint.py#L1319,默认 uri="viking://"、node_limit=100)、remember(mcp_endpoint.py#L714)、add_resource(mcp_endpoint.py#L933)、forget(mcp_endpoint.py#L1345,支持 recursive 参数)、health(mcp_endpoint.py#L1358)。
2.2 可选工具:先查注册列表,用前必读参考文档
SKILL.md 特别强调的纪律是:绝不调用未注册的工具,也不允许回退到裸 HTTP 请求;如果整个会话一个 OpenViking 工具都没注册,就直接无记忆继续工作。可选工具的可用性矩阵来自 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,仅限自托管 / 私有部署 | 不暴露 |
optional-tools.md 解释了云端裁剪的原因:托管云是无状态多实例服务,账户级有状态工具(list_watches、cancel_watch)即使底层版本支持也会被裁掉。各工具的具体语义:
tree(uri, level_limit?):列出某viking://作用域的目录树,比单层list深。用于在进入陌生作用域后先建立方位感;若只是查看单个已知目录,优先用更省成本的list。对应实现见 mcp_endpoint.py#L659。write(uri, content, mode?)与edit(uri, ...):对已知 URI 做精确文档持久化,与remember(由服务端自行抽取归档)互补。write可替换、追加或创建文件,但创建要求父目录已存在;edit在既有文件内做定点字符串替换,应优先于整文件重写,且如果本地副本可能过期应先read再改。适用对象是viking://~/(用户自己的根)下的精编笔记和viking://resources/下的共享参考资料。两者均未注册时回退到remember。list_watches()与cancel_watch(to_uri):管理add_resource按 watch 间隔创建的自动刷新订阅(仅限私有 / 自托管部署)。SKILL 要求只触碰用户主动提到的订阅——取消别人的订阅是破坏性操作。
三、Recall 流程:任务开始时的五步纪律
SKILL.md 的“Recall: at task start”一节给出了一套完整的检索决策流程,这是文章的核心实操骨架:
- 判断是否值得检索。可执行或多步的工作、可能碰过旧系统的东西、从失败中恢复——都要检索;寒暄和一次性琐碎事实直接跳过。
- 构造一条简洁查询。要素是任务目标、领域对象、预期操作、约束条件。失败后重试时,查询里要包含失败的操作和错误消息中稳定不变的部分。
- 先
find,按需升级。find快,返回带 URI + 摘要 + 分数的排序结果,limit建议 5–10。需要更深意图分析时用search;用search加mode="context"可拿到由服务端组装、按 token 预算裁剪的上下文块。在 list 模式下,如果知道去哪找,用target_uri收敛范围,例如指向既往任务经验的viking://~/memories/experiences。 - 按“与任务和环境是否契合”而非标题相似度来判读结果。只
read那一两个、最多三四个真正会改变你执行方式的精确文件 URI;忽略.abstract.md、.overview.md、.relations.json等 sidecar 文件。 - 无结果就无记忆继续。只有当执行因一个实质性的新原因失败时,才允许做一次聚焦的追加检索。
检索纪律的最后一条是优先级排序:检索到的记忆只是建议性的,优先级依次是——系统与开发者指令 > 当前用户请求 > 当前环境与工具证据 > 记忆。命令、路径、版本必须对照当前任务核验;过去成功过的操作绝不授权现在执行破坏性动作。
四、Persist 流程:何时存、存什么、不存什么
因为捕获不自动发生,SKILL.md 明确警告“durable information is lost unless you store it”,要求在同一个会话里就持久化。三个入口:
remember(messages)—— 默认路径。把关键对话或简短事实摘要以带 role 标签的消息传入,服务端自行抽取并归档记忆(偏好、实体、事件、经验)。触发时机:用户说“记住这个”、用户表达了持久偏好或决策、或浮现出来之不易的教训(根因、可工作的操作程序、环境怪癖)。add_resource—— 把外部文档或 URL 导入为可检索资源。- 可选的
write/edit—— 需要精确文档落在已知位置时(viking://~/下自己的精编笔记,或viking://resources/下的共享资料);未注册则回退remember。
存什么:稳定的偏好与约定、环境事实、带理由的决策、可复用的操作程序或修复方案。不存什么:密钥与凭据、瞬时状态、猜测、成段的转录倾倒——存的是结论,不是滚动屏。
五、端到端示例:修复一个失败的部署
SKILL.md 自带的示例把两个循环串成一个完整回路:用户要求修复一个失败的部署——
find查询deployment image pull failure private registry,target_uri: "viking://~/memories/experiences";read最相关的那条经验 URI,先核对其假设与当前集群是否一致,再套用其步骤;- 修复问题,验证线上结果;
remember一份简短的根因 + 有效修复摘要,让下一个会话可以召回它。
注意第 2 步的“先核验再套用”:这正是前文“记忆是建议性的”原则在实战中的落地。
六、技能如何到达客户端:stdio 代理链与合规校验
SKILL 只是“教法”,工具要真正出现在模型面前,依赖 agent-plugins 这个 Agent Plugins 1.0 包的加载机制:
- mcp.json 声明了名为
openviking的 stdio MCP 服务器,命令为node,参数为${PLUGIN_ROOT}/servers/mcp-proxy.mjs;mcp-proxy.mjs 是一个 stdio → streamable HTTP 代理,把 JSON-RPC 原样转发到 OpenViking 服务端的/mcp端点。 - 为什么用 stdio 代理而不是
streamable-http条目?README 的解释是:服务端 URL 因部署而异(本地http://127.0.0.1:1933或远端端点),且 Agent Plugins 规范禁止在静态headers里带凭据。代理在运行时按与ovCLI 相同的来源解析 URL 和 API key,按请求注入后转发,一次解决两个问题。 - 凭据解析优先级(从高到低):环境变量
OPENVIKING_URL(或OPENVIKING_BASE_URL)、OPENVIKING_API_KEY(或OPENVIKING_BEARER_TOKEN)、OPENVIKING_ACCOUNT、OPENVIKING_USER、OPENVIKING_PEER_ID→~/.openviking/ovcli.conf(可用OPENVIKING_CLI_CONFIG_FILE覆盖)→~/.openviking/ov.conf的server段(可用OPENVIKING_CONFIG_FILE覆盖)→ 默认http://127.0.0.1:1933无认证(本地模式)。运行中的代理无需重启即可感知配置文件变更;调试可用OPENVIKING_DEBUG=1把 JSON 行日志写入~/.openviking/logs/agent-plugins.log。 - 整个包零 npm 依赖,仅用 Node.js 标准库(Node 18+ 的全局
fetch)。
包自身的正确性由 plugin.test.mjs 的 node --test 用例把关:plugin.json 的根字段必须闭合在 1.0 规范允许集内($schema、name、version、description、author、homepage、repository、license、keywords、extensions);mcp.json 的 mcpServers 条目必须是 stdio 或 streamable-http,且 streamable-http 的 headers 不允许携带任何凭据字样;skills 目录下每个子目录必须有合规的 SKILL.md;SKILL.md 中的相对 markdown 链接必须指向真实文件(这保证了本文引用的 references/optional-tools.md 与 SKILL.md 内的相对链接一致有效);所有 vendored 的 .mjs 必须通过 node --check,且 mcp-proxy.mjs 的相对 import 链必须可解析。
七、适用前提与边界
- 适用场景:harness 没有 hooks 体系、或希望一个包跨多个客户端(Cursor、VS Code 及其他 Agent Plugins 1.0 兼容客户端)加载的场景。如果你的 harness 有 hooks,README 建议优先使用 hook 驱动的专用插件(如 examples/claude-code-memory-plugin/、examples/codex-memory-plugin/ 等)——hook 驱动的召回与捕获不消耗工具调用,也不依赖模型主动选择去记。
- 工具可见性:具体能看到哪些工具取决于服务端版本与托管模式(见 2.2 节矩阵),因此模型的第一动作永远是核对会话注册列表。
- 成本特性:因为没有自动捕获,记忆的完整性取决于模型遵守技能纪律的程度;这是“portable 但由模型驱动”路线的固有取舍,也是该技能用“同一会话内持久化”“失败后最多一次追加检索”等硬约束来对冲的原因。
综上,openviking-memory 这个 skill 的价值不在于引入新工具,而在于把 OpenViking 的 MCP 记忆能力封装成一份可被任何 Agent Plugins 1.0 客户端加载、可被合规测试验证、且对模型有明确行为约束的操作规程:核心工具集保底可用,可选工具按版本协商,召回与持久化各自有清晰的触发条件、参数纪律和失败兜底。
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 StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00