乐于分享
好东西不私藏

AI 插件的统一包装:Agent Plugins 规范解读

AI 插件的统一包装:Agent Plugins 规范解读

同一个 SKILL.md 技能文件,在 Claude Code 里能用,到 Cursor 里也能用,这件事 Agent Skills 规范已经解决了。但一个完整的插件包是另一回事。里面除了技能,可能还有 MCP 服务器、客户端专属钩子、配置文件。你为 VS Code 打的包,换到 GitHub Copilot 里,目录结构对不上,MCP 配置写法不一样,得重排甚至重写一遍。

这就是 2026 年上半年 AI Agent 生态的现实:组件层面(技能、MCP)正在收敛,打包层面却各搞各的。

2026 年 8 月,一个叫 Agent Plugins 的规范发布了 1.0.0 版本。官网对它的定位只有一句:一个可移植的包装格式,用于打包可复用、可扩展 AI Agent 的组件。技术指导委员会(TSC)的初始核心维护者来自 Amazon、Cursor、Microsoft、OpenAI 和 Vercel。GitHub Copilot、ChatGPT & Codex、Cursor、VS Code、Kiro 已经是兼容客户端。

下面讲它解决什么问题、包格式怎么工作,以及它为什么把"可移植"和"客户端自有"切得那么干净。

解决什么问题:打包层的碎片化

先说现状。AI Agent 客户端过去几年各自长出了自己的插件格式。问题不在组件本身,Agent Skills 有规范,MCP 有规范,问题在怎么把这些组件装进一个可分发的包。

各客户端的打包约定不一样:插件元数据放在哪、叫什么名字、MCP 配置写成什么形状、技能目录怎么发现,各家一套。结果是,插件作者要把同一批组件为每个客户端重新摆位甚至复制一份。为 A 客户端打的包,B 客户端可能根本认不出来,得改了才能用。组件越通用,重复劳动越多。

Agent Plugins 没有去统一所有客户端的插件格式,只定义一个最小的互操作性地基。原话:

Agent Plugins defines a small interoperability floor for the parts that can be portable across clients. Shared components can use one predictable structure, while distribution, installation, permissions, user experience, and client-specific capabilities remain under each client's control.

翻译过来就是两件事画一条线:

  • 可移植的:包结构、校验、组件发现、MCP 配置、插件变量、失败隔离。这些跨客户端共用一套。
  • 客户端自有的:安装来源、注册表、市场、启用/更新/缓存的用户体验、权限提示、信任策略、沙箱、技能怎么展示给用户或模型。这些各客户端自己管,规范不碰。

这条线是理解整个设计的关键。Agent Plugins 不碰插件市场怎么运作、权限审批 UX、沙箱怎么做这些事。它只保证:按规范打好包,任何兼容客户端都能发现并加载里面的技能和 MCP 服务器。装在哪、怎么装、装完给不给你用,那是客户端的事。

包格式:一个目录,一个清单

一个 Agent Plugin 就是一个目录。目录里有一个必需的清单文件 plugin.json,其余组件按固定位置摆放:

my-plugin/├── plugin.json├── skills/│   └── summarize/│       ├── SKILL.md│       ├── scripts/│       └── references/├── mcp.json└── com.example.client/    └── hooks/

四个部分:

  • plugin.json 是必需的清单,标识插件身份和它目标的 Agent Plugins 版本。
  • skills/ 放 Agent Skills,格式遵循 Agent Skills 规范,Agent Plugins 不重新定义。
  • mcp.json 描述 stdio、Streamable HTTP 或旧版 HTTP+SSE 的 MCP 服务器。
  • 反向域名扩展目录(如 com.example.client/)让单个客户端加自己的行为,不动可移植核心。

plugin.json:闭合的清单

最小清单只有两个字段:

{"$schema":"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json","name":"hello-plugin"}

$schema 选定 Agent Plugins 版本和对应的校验契约,客户端据此选本地支持的校验规则。注意一个细节:客户端加载插件时不去网上拉这个 schema,而是用本地的实现匹配 $schema 的值。name 是插件标识,约束很具体:1 到 64 字符,只能用小写 ASCII 字母、数字、连字符和点,首尾必须是字母数字,不能含 -- 或 ..。my-plugin、acme.tools、lint3r 合法;My-Plugin、-start、has--double、too.many..dots 不合法。

可选字段有 version(建议语义化版本)、description、author、homepage、repository、license(建议 SPDX 标识符)、keywords、extensions。extensions 是客户端专属数据的入口,键是反向域名命名空间,值是对象。

这里有个刻意的取舍:清单 schema 是闭合的(closed)。顶层只允许规范定义的字段,客户端实验性数据不能随便占顶层字段,必须塞进 extensions 里的命名空间。好处是能严格校验、能查拼写错误、能做 schema 驱动的补全。坏处是没那么多自由度,但这正是"可移植"要付的代价。

skills/:只定位置,不重造格式

skills/ 下每个直接子目录是一个技能,里面要有 SKILL.md。客户端发现技能的规则很窄:只看 skills/ 的直接子目录里有没有一个叫 SKILL.md 的常规文件,不递归往下挖。SKILL.md 的 frontmatter 和正文指令遵循 Agent Skills 规范,技能里可以有 scripts/、references/、assets/ 等子目录,这些是 Agent Skills 约定的惯例,不是 Agent Plugins 管的事。

一句话:Agent Skills 规范定义技能长什么样,Agent Plugins 定义技能在包里放哪。

mcp.json:显式声明传输

mcp.json 在插件根目录,顶层只能有两个字段:$schema 和 mcpServers。mcpServers 是个对象,键是服务器名,值是配置对象。每个服务器用一个 type 字段声明传输方式,是闭合的三选一:

类型
必需字段
说明
stdiotype, command
本地子进程,可选 args/env/cwd
streamable-httptype, url
当前远程 MCP 传输,可选字面量 headers
ssetype, url
已废弃的 HTTP+SSE 传输,客户端支持是可选的

一个完整示例,含本地和远程两种:

{"$schema":"https://agent-plugins.org/schemas/1.0.0/mcp.schema.json","mcpServers":{"local-validator":{"type":"stdio","command":"./bin/validator","args":["--data","${PLUGIN_DATA}/validator"],"env":{"CONFIG":"${PLUGIN_ROOT}/config.json"},"cwd":"${PLUGIN_ROOT}"},"deployment-api":{"type":"streamable-http","url":"https://deploy.example.com/mcp","headers":{"X-Tenant":"public-tenant"}}}}

两个设计决策值得展开。

第一,type 是显式选传输,不是靠 URL 猜测。streamable-http 选当前的 Streamable HTTP 传输,sse 选 MCP 2024-11-05 规范定义的旧版 HTTP+SSE 传输。两者是分开的,不混为一谈。客户端用 type 声明的传输做首次连接尝试,规范不定义连接失败后的回退行为。为什么要分这么细?因为现有客户端推断传输的方式互相不兼容,Agent Plugins 干脆定义一个显式的闭合 union,让每条配置的含义独立于任何客户端的原生格式。

第二,command 是单个可执行令牌,不是 shell 命令字符串。要么是裸可执行文件名(走平台搜索规则),要么是以 ./ 开头的插件相对路径(相对插件根解析)。command 上不做占位符展开。这条规则省掉了客户端解析、转义用户写的 shell 命令字符串的麻烦,一个令牌就是安全。

插件变量:PLUGIN_ROOT 和 PLUGIN_DATA

客户端启动 stdio MCP 子进程时,必须提供两个环境变量:

  • PLUGIN_ROOT:插件根目录的绝对路径(解析符号链接后的)。
  • PLUGIN_DATA:客户端管理的、专属于这个插件实例的可写数据目录,跨插件更新持久保留。

两个占位符 ${PLUGIN_ROOT} 和 ${PLUGIN_DATA} 在 args、env 的值、cwd 里展开,单次、非递归,替换进来的文本不会再被扫描占位符。env 的键、command、远程 URL、HTTP headers 上不展开。

PLUGIN_DATA 的存在是有意义的。插件更新时包内容会被替换,但有些东西要留着:装好的依赖(node_modules、虚拟环境)、生成的代码、缓存。PLUGIN_DATA 给这些一个确定的位置。PLUGIN_ROOT 则用来引用随包发行的脚本、二进制、配置文件。

一个安全细节:插件的 env 对象里不能出现名为 PLUGIN_ROOT 或 PLUGIN_DATA 的条目,出现了这条 MCP 配置就无效。这两个保留变量由客户端自己提供,插件不能覆盖。

反向域名扩展:客户端特有行为怎么放

可移植层只管技能和 MCP。但有些行为是某个客户端专属的,比如 Claude Code 的 hooks、Cursor 的某种规则。这些不该进可移植核心,否则规范会被各家特例撑爆。

Agent Plugins 的办法是反向域名命名空间。两种放法,可以只用一种,也可以都用:

  • 清单里 extensions 下按命名空间放数据;
  • 顶层放一个以命名空间命名的目录,比如 com.example.client/。
example-plugin/├── plugin.json├── skills/└── com.example.client/    └── hooks/        └── hooks.json

命名空间用客户端控制的域名反写,比如控制 example.com 的客户端用 com.example.client。规范不维护中央客户端名注册表,靠域名避免冲突。关键一句:客户端扩展不是可移植的 Agent Plugins 组件。其他客户端可以忽略它们而不影响合规。一个客户端实现了某个命名空间,就自己定义里面的内容、校验、行为和失败处理。

这种"可移植核心尽量小,特例塞进命名空间"的做法,和清单的闭合 schema 思路一致:核心严格可控,扩展有出口但不污染核心。

失败隔离:一个组件坏了不该连累整个插件

Agent Plugins 的失败处理有一条总原则:组件失败是非致命的。规范用了一整套窄边界来隔离:

  1. plugin.json 解析到插件根之外,拒绝整个插件。
  2. 某个组件类型的固定位置文件系统类型不对或越界,只禁用这个组件类型,其余继续。
  3. 某个技能的 SKILL.md 越界,只跳过这个技能,兄弟技能继续。
  4. 某条 MCP 配置的包路径越界,只跳过这条,其余服务器和组件继续。
  5. 其他越界的包路径,拒绝访问。

具体到 MCP:顶层 mcp.json 无效(JSON 不合法、$schema 不匹配、版本和 plugin.json 对不上),禁用这个插件的 MCP,但技能照常加载。单条服务器配置无效(未知传输、未知字段、缺字段),只跳过这条,其余服务器和技能继续。某台服务器启动/连接/认证/握手失败,继续加载其余。规范要求客户端尽量报告这些失败,而不是静默吞掉。

为什么要这样?规范自己的解释很直接:一个同时提供技能和 MCP 服务器的插件,不该因为一台服务器不可用就整个废掉。把失败边界做窄,插件在部分损坏时仍能部分可用。这和很多插件系统"一处错全盘挂"的做法相反。

谁在背后:开放治理,禁止一家独大

Agent Plugins 是开放许可、公开开发的。技术指导委员会(TSC)由所有核心维护者加上 Lead Core Maintainer 组成。初始 TSC 的核心维护者名单(来自仓库的 MAINTAINERS.md):

  • Clare Liguori(Amazon)
  • Roshan Sadanani(Cursor)
  • Harald Kirschner(Microsoft)
  • Gav Verma(OpenAI)
  • Jonathan Hefner(Vercel),Lead Core Maintainer

治理章程里有一条值得注意的约束:没有任何单一厂商可以占核心维护者席位的多数。所有治理角色由个人担任,不给公司预留席位。提案和技术决策公开,新功能或重大变更从 GitHub Discussions 起步,要先证明有具体的可移植性需求和实现方支持。Lead Core Maintainer 可由核心维护者 75% 超多数票罢免。这套结构明显是想避免规范被某家厂商绑架。

兼容客户端:增量采纳,不必全要

Agent Plugins 允许客户端增量采纳。一个客户端不必支持所有组件类型,只要支持技能或 MCP 服务器至少一种,就算合规。兼容客户端页(截至 2026 年 7 月)列了五个:

客户端
Skills
MCP 传输
VS Code
支持
stdio、streamable-http、sse
Cursor
支持
stdio、streamable-http、sse
GitHub Copilot
支持
stdio、streamable-http、sse
ChatGPT & Codex
支持
stdio、streamable-http
Kiro
支持
stdio、streamable-http、sse

五个客户端都支持技能,MCP 传输支持的广度有别。ChatGPT & Codex 不支持已废弃的 sse,其余四个三种都支持。这种"列清楚每个客户端支持什么"的透明度,对插件作者判断可移植边界有用。

一个细节:规范要求 MCP 客户端至少支持 stdio 或 streamable-http 之一,建议两者都支持。sse 是可选的。客户端遇到不支持的传输类型,跳过那条服务器,继续加载其余,又是失败隔离那条原则在起作用。

v1 没做的:留给未来的清单

Agent Plugins 1.0.0 有意识地收窄了范围。仓库里有一份 FUTURE_CONSIDERATIONS.md,列了未来版本可能考虑、但不承诺的方向。挑几个对落地影响大的说:

权限与审批 UX。v1 不定义信任模型、权限系统或沙箱要求。未来可能加权限声明(文件系统访问、网络访问、工具访问)、客户端按插件限制能力、安装时的用户同意流程、对执行任意命令或访问外部服务的 MCP 服务器的审批 UX、分级信任(沙箱/用户批准/组织批准)。这意味着 v1 的安全责任主要在客户端侧,规范只给失败报告要求。

来源验证。v1 不规定怎么验证插件来源或完整性。未来可能加加密签名验证、把已发布插件和源码仓库/构建关联的 attestation 链、客户端要求受信任发布者签名的策略。

密钥与敏感值。MCP 服务器运行时常常要凭证或 API key。v1 的配置里 headers 和 env 是可见的包数据,明确不能塞凭证。未来可能加 secrets 清单字段或独立密钥配置、客户端中介的密钥注入、防止一个插件访问另一个插件密钥的作用域规则。

企业控制。组织规模部署要的允许/阻止名单、组织级注册表带审批流、集中配置覆盖、合规报告,v1 都没有。

插件间依赖。目前插件不能声明依赖别的插件,未来可能加。

这份清单说明 1.0.0 刻意收窄了范围:先把可移植的包装格式和发现规则定稳,权限、安全、分发这些更难的留到后面。

怎么看 1.0.0

技能和 MCP 的规范已经有了,缺的是一层"怎么打包、放哪、怎么发现、失败了怎么不互相连累"的约定。Agent Plugins 补的就是这一层。对插件作者,一份包能进更多客户端,少做重复摆位;对客户端实现者,有一个明确的合规清单可对照。打包层至少在 TSC 涵盖的那几家主流厂商之间开始往一处靠。

它能不能成气候,看两点:这几家厂商愿意把自家插件格式往规范上靠多少,以及权限、签名、分发这些 v1 没碰的硬骨头后续能不能补上。1.0.0 范围收得很窄,但边界画得清楚。


参考链接

  • 官网:https://agent-plugins.org/[1]
  • 规范仓库:https://github.com/agentplugins/agent-plugins-spec[2]
  • 规范全文:https://agent-plugins.org/specification[3]
  • 示例插件:https://github.com/agentplugins/agent-plugins-example[4]
  • Agent Skills 规范:https://agentskills.io/specification[5]
  • MCP 规范:https://modelcontextprotocol.io/specification[6]

引用链接

[1]https://agent-plugins.org/

[2]https://github.com/agentplugins/agent-plugins-spec

[3]https://agent-plugins.org/specification

[4]https://github.com/agentplugins/agent-plugins-example

[5]https://agentskills.io/specification

[6]https://modelcontextprotocol.io/specification

相关学习资料