Agent Plugins and the open standards
The formats AI coding assistants read are converging on open standards. OpenCastle writes them wherever an assistant reads them, uses any Agent Plugin in every assistant — including the ones that do not read Agent Plugins yet — and publishes your team's standard as one.
The Standards
Four open standards now cover most of what an assistant is given. Three are stewarded by the Linux Foundation's Agentic AI Foundation; Agent Skills started at Anthropic and is read by dozens of tools.
| Standard | Covers | What OpenCastle does with it |
|---|---|---|
| AGENTS.md | Project instructions | Writes it for Codex CLI and OpenCode, and Antigravity reads it beside GEMINI.md; Claude Code gets the same content in CLAUDE.md, Copilot and Windsurf in their own instruction and rule files, and Cursor in its rule files unless it already reads them from CLAUDE.md or AGENTS.md |
Agent Skills (SKILL.md) | Procedures an agent loads when a task matches | Every skill — OpenCastle's, your baseline's, your project's — is compiled as a SKILL.md folder named as the skill, where each assistant reads skills |
| MCP | Tools and data an agent can call | Writes every server in each assistant's own config, in its own variable syntax — JSON for six, .codex/config.toml for Codex |
| Agent Plugins 1.0 | A package of skills and MCP servers | Uses any Agent Plugin as a baseline, publishes yours as one, and ships each of its 33 integrations as one |
What none of them covers yet — custom agents, commands, hooks, scoped rules, a policy for which servers may run — OpenCastle still compiles assistant by assistant. Agent Plugins gives that a place to live inside a standard package: a client's own namespace.
What an Agent Plugin Is
Agent Plugins 1.0 was published in August 2026 by maintainers from Amazon, Cursor, Microsoft, OpenAI and Vercel. A plugin is a directory:
my-plugin/
├── plugin.json the manifest — $schema and name are required
├── skills/
│ └── summarize/
│ ├── SKILL.md an Agent Skill, named as its directory
│ └── references/
├── mcp.json MCP servers: stdio, streamable-http or sse
└── com.example.client/ anything one assistant adds, under its own namespace
The manifest is closed: ten fields, two required. Skills follow the Agent Skills spec, and a skill
whose name does not match its directory is skipped. MCP servers are a closed union of three
transports. Anything a single assistant adds goes under a reverse-domain namespace — OpenCastle's is
dev.opencastle.
| Assistant | Reads Agent Plugins | Marketplace file |
|---|---|---|
| GitHub Copilot (VS Code, CLI) | Yes, plugin.json at the root | .github/plugin/marketplace.json or .claude-plugin/marketplace.json |
| Cursor | Yes | .cursor-plugin/marketplace.json |
| Codex CLI | Yes | .agents/plugins/marketplace.json |
| Kiro | Yes | — |
| Claude Code | Its own manifest, .claude-plugin/plugin.json, and .mcp.json — opencastle plugin build writes both | .claude-plugin/marketplace.json |
| Windsurf (Devin Desktop), OpenCode, Antigravity | Not as plugins — OpenCastle compiles a plugin's skills and servers into their own files | — |
Use One Everywhere
Any Agent Plugin can be a baseline. Install it as a devDependency — or keep it in the repository — and extend it:
// .opencastle/config.json
{
"extends": ["@acme/ai-standard"] // an installed package, or a path from this file: "../plugins/ai-standard"
} opencastle sync then compiles its skills and its servers into every assistant the project compiles for,
held to your policy and recorded in the lock, like any baseline's. No OpenCastle declaration is
needed in its package.json: a plugin.json at its root is enough.
- Skills are compiled as they are. One the Agent Skills spec would have an assistant skip — a name that does not match its directory — is reported.
- Servers in
mcp.jsonbecome the project's:./and${PLUGIN_ROOT}become the plugin's path from the project root, where assistants start a project's servers. - A server that uses
${PLUGIN_DATA}, a working directory of its own, or the legacy SSE transport is left out with the reason: those need an assistant that installs the plugin itself. - A manifest a conformant client would reject — a missing name, a field of the wrong type — is an error, and nothing is written.
Publish Your Standard
opencastle baseline init creates a baseline that is also an Agent Plugin. Assistants that
read Agent Plugins can install its skills and servers as they are; OpenCastle compiles all of it —
including what the standard does not cover — into every assistant, in every repository that extends it.
ai-standard/
├── package.json "opencastle": { "baseline": "." }
├── README.md
├── plugin.json the Agent Plugins manifest
├── mcp.json servers every assistant can start as they are
├── skills/
│ └── code-review/
│ └── SKILL.md
├── dev.opencastle/ OpenCastle's namespace: what the standard does not cover yet
│ ├── config.json the policy, and servers that need ${NAME} variables
│ └── instructions/
│ └── engineering-standards.md
├── .github/workflows/
│ └── check.yml runs opencastle baseline check on every push and pull request
├── .claude-plugin/
│ └── plugin.json Claude Code's copy — opencastle plugin build writes it
└── .mcp.json Claude Code's copy of mcp.json, once mcp.json has a server {
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "acme.ai-standard",
"version": "0.1.0",
"description": "Our AI assistant standard: compiled by OpenCastle into every assistant …",
"license": "UNLICENSED"
}
A server every assistant can start as it is — a remote server with OAuth, a pinned local one — goes
in mcp.json. One that needs a token or another value from the developer goes in
dev.opencastle/config.json, written as ${NAME}: the standard has no
way to name a secret yet, and OpenCastle spells the variable the way each assistant expects.
The scaffold's policy in dev.opencastle/config.json allows only its example servers.
Add a new server's name to policy.mcp.allow, and a remote server's host to
policy.mcp.remoteHosts, or opencastle baseline check fails on it.
Claude Code reads its own manifest, so opencastle plugin build writes
.claude-plugin/plugin.json and .mcp.json from the portable files, and
check fails when they fall behind:
$ npx opencastle plugin check ai-standard
🏰 Agent Plugin acme.ai-standard 0.1.0 · Agent Plugins 1.0.0
Skills: code-review
MCP servers: internal-docs
dev.opencastle/: OpenCastle content — check it with opencastle baseline check
✗ .mcp.json does not match plugin.json and mcp.json — run opencastle plugin build
1 problem(s) to fix.
$ npx opencastle plugin build ai-standard
✓ Wrote .mcp.json
$ npx opencastle plugin check ai-standard
…
✓ Loads in GitHub Copilot, VS Code, Cursor, Codex and Kiro as it is, and in Claude Code.
A skill someone wrote for their own assistant joins the standard with
opencastle promote skill <name> --to ai-standard, checked against the Agent Skills spec
and for credentials on the way in. See Team Memory.
Distribute It
For developers who install plugins in their assistant rather than through a repository, keep your
plugins in one repository and let opencastle plugin index write the file each assistant
reads a marketplace from:
agent-plugins/
├── package.json
├── plugins/
│ ├── ai-standard/ an Agent Plugin
│ └── payments/ another
├── .claude-plugin/marketplace.json Claude Code, Copilot CLI
├── .cursor-plugin/marketplace.json Cursor team marketplaces
└── .agents/plugins/marketplace.json Codex $ npx opencastle plugin index
✓ Listed 2 plugin(s) in .claude-plugin/marketplace.json, .cursor-plugin/marketplace.json, .agents/plugins/marketplace.json
… {
"name": "acme.agent-plugins",
"owner": { "name": "Acme Platform" },
"metadata": { "description": "Acme's plugins for every assistant" },
"plugins": [
{
"name": "acme.ai-standard",
"source": "./plugins/ai-standard",
"description": "Our AI assistant standard: …"
},
…
]
}
Claude Code, Copilot CLI and Cursor read the same shape; Codex reads its own. Each developer adds the
repository once — claude plugin marketplace add acme/agent-plugins,
copilot plugin marketplace add acme/agent-plugins,
codex plugin marketplace add acme/agent-plugins, or in Cursor under Dashboard → Plugins →
Team Marketplaces → Import. Run opencastle plugin index --check in CI so a new plugin is never
missing from the list.
Integrations
Each of OpenCastle's 33 integrations is an Agent Plugin directory, checked against the spec in OpenCastle's own tests:
src/orchestrator/plugins/supabase/
├── plugin.json compiled from config.ts; OpenCastle's own data under extensions."dev.opencastle"
├── mcp.json the Supabase remote server, as streamable-http
├── skills/
│ └── supabase-database/
│ └── SKILL.md
└── config.ts detection, agent tools, earlier defaults — what only OpenCastle reads
Their skills are compiled under the skill's own name — supabase-database, not
supabase — so an assistant that follows the Agent Skills spec loads them. A team config
that excludes skills/supabase still works, with a warning naming the new spelling.
What check Checks
opencastle plugin check loads a plugin the way the 1.0.0 spec says a conformant client
must, and reports what such a client would refuse, skip or ignore. baseline check runs the
same checks on a baseline that is a plugin.
- Manifest — a
$schemanaming a published version; a name of lowercase letters, digits, hyphens and periods; the types of every field;authorholding only name, email and url. An unknown field is reported and ignored, as a client does. - Skills — each immediate child of
skills/with aSKILL.md: a name matching its directory, a description of at most 1,024 characters,compatibilityandmetadatain their shapes. - MCP servers — a
mcp.jsonon the same version as the manifest; a command that is one executable, bare or./; noPLUGIN_ROOTinenv; https unless the host is loopback; no credentials in the URL; no header given twice. - Containment — the manifest and every skill resolve inside the plugin, links followed.
- Claude Code's copies — that
.claude-plugin/plugin.jsonand.mcp.jsonmatch the portable files.
Limits
- Agent Plugins 1.0 covers skills and MCP servers only. Instructions, agents, prompts, workflows and policy travel in
dev.opencastle/, which only OpenCastle reads; an assistant that installs the plugin natively gets its skills and portable servers. - No secrets in the standard yet. A portable server that needs a token reads it from the environment the assistant runs in; one that needs a value spelled into its config belongs in
dev.opencastle/config.json. - Distribution is not standardised. Each assistant indexes a marketplace in its own file, which is why
plugin indexwrites three. - OpenCastle does not fetch plugins. As with any baseline, your package manager installs and pins it;
extendsnames an installed package or a path.