Back to Articles
πŸ“„
6.2%96.6%40.2%

Agent Plugins v1.0 and the Illusion of Portability

On 24 July 2026, the Agent Plugins v1.0.0 specification emerged to standardize installable bundles of skills and Model Context Protocol (MCP) servers across heterogeneous coding agents. Yet empirical analysis across 68,072 plugin bundles from 30,655 repositories in the AgentPluginZoo corpus (Sahu, arXiv:2609.23809) reveals that standardizing a package format does not solve multi-plugin composition. Only 6.2% of wild bundles strictly validate, 40.2% suffer silent field loss when conforming hosts discard undeclared top-level capability fields, 95.6% of multi-manifest bundles drift out of sync, and 81% of capability-exporting bundles collide on shared names. This article examines the empirical failure modes of the Agent Plugins ecosystem and outlines the architectural requirements for true cross-runtime interoperability.

Agent Plugins v1.0 and the Illusion of Portability

On 24 July 2026, the agentic tooling ecosystem reached what looked like a decisive milestone: the publication of the Agent Plugins v1.0.0 specification by the Agent Plugins Working Group. Across coding agents such as GitHub Copilot, Claude Code, OpenAI Codex, and Cursor, the unit of extension had already converged on a recognizable shape: a directory containing a manifest alongside some combination of skills (markdown instruction files loaded when a task matches), sub-agents, slash commands, lifecycle hooks, and Model Context Protocol (MCP) servers exposing tools. Until July 2026, however, each vendor defined its own client-specific directory layout, forcing authors to restructure or duplicate their bundles for every target host.

The promise of Agent Plugins v1.0.0 was simple: place a single plugin.json manifest at the bundle root, follow fixed path conventions for components, and let any conforming coding agent load the package without out-of-band instructions.

Two months later, the empirical reality of the open-source plugin ecosystem tells a far more sobering story. In a comprehensive census of 68,072 plugin bundles across 30,655 public GitHub repositories (AgentPluginZoo, Tezan Sahu, arXiv:2609.23809, September 2026), alongside 157,062 standalone skills and 1,379 standalone MCP configurations, two structural truths emerge. First, strict conformance in the wild is rare (6.2%), though the barrier is shallow (96.6% of parseable manifests load once a single missing $schema boilerplate declaration is added). Second, and far more consequentially, even 100% schema conformance would not make plugins work reliably together: 40.2% of loadable manifests have author-written fields silently discarded by conforming clients, 95.6% of multi-vendor manifest copies drift out of semantic sync, and 81% of capability-exporting bundles collide on a capability name claimed by another plugin.

Standardizing a single-package layout without a formal model for multi-plugin composition and execution isolation merely turns fragmentation into packaged chaos.


The Anatomy of an Agent Plugins v1.0.0 Bundle

To understand why conforming plugins still fail in practice, we have to examine what Agent Plugins v1.0.0 actually standardizes and what it deliberately omits. The specification standardizes a package layout, not a runtime API or a composition model. Its portability claim rests on two design decisions:

  1. A single closed root manifest (plugin.json): Exactly one plugin.json sits at the package root, carrying identity and provenance metadata ($schema, name, version, description, author, license, repository).
  2. Convention-based component discovery: A conforming client does not read plugin.json to learn what capabilities a plugin ships. Instead, it walks fixed paths on disk, specifically skills/*/SKILL.md for skills and mcp.json (or .mcp.json) for MCP tool servers.
my-plugin/
β”œβ”€β”€ plugin.json               # Closed identity manifest ($schema, name, version, ...)
β”œβ”€β”€ skills/                   # Convention-discovered skills
β”‚   └── code-review/
β”‚       └── SKILL.md
β”œβ”€β”€ mcp.json                  # Convention-discovered MCP server definitions
└── com.example.client/       # Reverse-domain directory for vendor-specific files

A strictly conforming v1.0.0 plugin.json manifest looks like this:

{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "Automated architectural conformance and security review plugin.",
  "author": {
    "name": "Example Maintainer"
  },
  "license": "MIT",
  "extensions": {
    "com.example.client": {
      "customSetting": true
    }
  }
}

Version 1.0.0 standardizes only two component types: skills and MCP servers. Slash commands, lifecycle hooks, sub-agents, rules, and language servers were deferred as too client-specific to standardize in v1.0.0. To accommodate vendor-specific features, the specification sanctions a top-level reverse-domain directory (com.example.client/) and a matching extensions object inside plugin.json, but explicitly assigns no portable discovery, validation, loading, or failure semantics to either.

Crucially, the JSON Schema (Draft 2020-12) governing plugin.json enforces three asymmetric validation rules that drive the failure modes observed in the wild:

  • The schema is closed (additionalProperties: false): Any top-level field not explicitly named in the v1.0.0 schema is a schema violation.
  • $schema is mandatory alongside name: Omitting $schema is a fatal violation; a conforming client must reject the plugin and refuse to discover or execute any of its components.
  • Unknown top-level fields are non-fatal but silently discarded: If a manifest includes an unrecognized top-level field (such as skills, commands, hooks, or agents), a conforming client must report and ignore the unknown field and continue loading the plugin.

What 68,072 Plugins Reveal: Five Empirical Failure Modes

By scoring all 68,072 bundles in AgentPluginZoo (assembled across 30,655 repositories from 22,901 distinct owners) against the normative v1.0.0 schema and loading rules, Sahu (2026) decomposed ecosystem failures into five distinct phenomena:

AgentPluginZoo Conformance & Composition Breakdown (68,072 Bundles)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Strictly validate against v1.0.0 JSON Schema        4,237   (6.2%)    β”‚
β”‚ Loadable as-is by a conforming v1.0.0 client        4,357   (6.4%)    β”‚
β”‚ Place plugin.json at the portable bundle root      13,417  (19.7%)    β”‚
β”‚ Loadable after adding missing $schema boilerplate  65,729  (96.6%)    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Silent field loss (host discards top-level fields) 27,291  (40.2%*)   β”‚
β”‚ Multi-manifest bundles with semantic drift          3,822  (95.6%**)  β”‚
β”‚ Capability-exporting bundles with name collisions  25,840  (81.0%***) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
 *  Among manifests that load after adding $schema.
 ** Among a random sample of 3,998 multi-manifest bundles (out of 9,857 total).
 *** Among the 31,901 bundles that export at least one named capability.

1. The $schema Cliff vs. Silent Field Loss

At first glance, strict schema validation paints a bleak picture: only 4,237 bundles (6.2%) validate end-to-end, and a conforming client would load only 6.4% as-is while rejecting 93.6% outright. Yet when every parseable manifest is granted a single missing $schema declaration without changing anything else, 96.6% load. Only 2,343 bundles (3.4%) fail for deeper structural reasons, two-thirds of which are naming-constraint violations (such as uppercase characters in the 1-to-64 lowercase character name field).

The deeper hazard lies in what happens after those 96.6% load. Among manifests that load once $schema is present, 40.2% (27,291 bundles) contain at least one top-level field that the closed specification obliges the client to discard. Even more revealingly, 32% of bundles explicitly write top-level fields such as skills, mcpServers, commands, hooks, or agents into plugin.json so that a human or registry reading the manifest can see what the plugin ships. Others add dependencies (declaring that one plugin requires another) or userConfig (declaring required runtime settings).

Although the specification provides the extensions object for non-standard fields, only 1.9% of manifests across 129 reverse-domain namespaces actually use it, compared with 43% that write forbidden fields at the top level. Because unknown top-level fields are non-fatal, the plugin appears to load cleanly while the host silently throws away the author's capability declarations, dependencies, and configuration requirements.

2. The Portability Tax and Multi-Manifest Drift

If a vendor-neutral format exists, the portable choice is to place one plugin.json at the bundle root. In practice, only 19.7% (13,417 bundles) do so; the remaining 80.3% keep their manifests inside vendor-specific directories (such as .claude-plugin/ or .cursor/). Recomputing this metric over the 36,157-bundle sub-corpus discovered without vendor-path queries confirms that the pattern is genuine rather than a search artifact.

Vendor lock-in strongly suppresses standards adoption:

  • Bundles using no vendor directory conform at 23.2% ($n = 10,511$).
  • Bundles locked into exactly one vendor directory conform at just 2.0% ($n = 49,309$).
  • Bundles spanning two or more vendor directories recover to 9.7% ($n = 8,252$).

To support $k$ coding agents today, maintainers frequently pay a portability tax by maintaining $k$ copies of the manifest across client-specific folders. Within AgentPluginZoo, 9,857 bundles (14.5%) ship two or more manifest files. Across a random sample of 3,998 such multi-manifest bundles, 95.6% had copies that were no longer semantically identical, and 7.3% disagreed on the plugin's own name. Depending on which coding agent opens the repository, the exact same bundle announces itself under different identities or capability sets.

3. Adoption Trajectory: Growing, Yet Blind to Composition

By tracing the specification repository's commit history to the signed commit "Publish Agent Plugins Specification 1.0.0" on 24 July 2026, Sahu (2026) measured whether the ecosystem is converging over time. Splitting the corpus by repository creation date shows conformance rising more than sixfold, from 3.2% before 24 July 2026 ($n = 55,881$) to 19.9% after ($n = 12,191$). Among the 45,796 bundles in repositories pushed to after publication, conformance stands at 9.3%, reaching 10.4% (with 15.5% declaring $schema) among the 38,331 bundles touched in the final 30 days of the census window.

While adoption of the packaging envelope is accelerating, roughly nine out of ten actively maintained bundles still fail strict validation, and the specification's progress is confined entirely to single-bundle formatting.

4. The Capability Name Collision Crisis

Users rarely install a single plugin in isolation, and host runtimes already strain under multi-plugin loads. Visual Studio Code caps agent mode requests at 128 tools (a ceiling easily hit by enabling a few MCP servers), OpenAI Codex budgets the skill list to 2% of the context window before silently omitting skills, and controlled evaluations by Repantis et al. (2026, arXiv:2605.24660) show that LLM tool-selection accuracy drops from 93.1% to 87.1% as the offered tool list grows.

Extracting every capability exported across AgentPluginZoo (skills, sub-agents, commands, and hooks) yielded 409,935 capability records spanning 94,837 distinct skill names:

Capability Collision Metrics Across AgentPluginZoo (409,935 Records)
  β€’ Distinct skill names claimed by >1 plugin:            28.0% (of 94,837 names)
  β€’ Individual skill instances carrying a contested name: 78.0%
  β€’ Capability-exporting bundles with β‰₯1 name collision:  81.0% (of 31,901 bundles)
  β€’ Cross-owner collision rate (excluding same-org forks): 74.0%

Most Contested Capability Names by Distinct Repository Owners:
  1. code-reviewer          (claimed by 300 distinct repository owners)
  2. systematic-debugging   (claimed by 221 distinct repository owners)

Because popular task names attract independent authors, 78% of all individual skills carry a name that another plugin also claims, and 81% of the 31,901 capability-exporting bundles (74% when requiring the conflicting claim to come from a different repository owner) collide on at least one capability name.

When a developer installs two plugins that both export code-reviewer or systematic-debugging, Agent Plugins v1.0.0 defines no namespace and no precedence rule. Resolution is left entirely to client quirks: Claude Code forcibly prefixes plugin skills by vendor convention, GitLab Duo resolves collisions by selecting "the first one it encounters" in directory traversal order, and other hosts silently overwrite earlier registrations.

5. Unbounded Execution and Security Drift

Beyond naming and manifest loss, empirical security studies on the underlying components show why packaging without runtime isolation is hazardous:

  • Skill vulnerabilities at scale: Mining 42,447 agent skills in the wild, Liu et al. (2026, arXiv:2601.10338) documented widespread prompt-injection surfaces, unchecked shell execution patterns, and credential exposure in community skill files.
  • MCP server drift and maintainability flaws: Hasan et al. (2025, arXiv:2506.13538) identified pervasive security and maintainability defects across public MCP servers, while Kraishan (2026, arXiv:2609.14119) demonstrated "same name, different server" silent drift across MCP server versions and registries.

Architectural Patterns for Real Interoperability

As Sahu (2026) argues, the community standardized a packaging format (checkable on a single directory sitting on disk) when multi-plugin installations require a composition model (rules governing plugins in relation to one another and to the host runtime). Reconciling portability with safety requires four architectural upgrades, three of which fit cleanly into an additive v1.1 profile of the specification alongside host-level sandboxing:

Unbounded v1.0.0 Loading (Flat Namespace & Silent Field Loss):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Agent Host ───────────────────────┐
β”‚  Plugin A (code-reviewer) ──┐                           β”‚
β”‚                             β”œβ”€β”€> Traversal-Order Clash  β”‚
β”‚  Plugin B (code-reviewer) β”€β”€β”˜    (Host-dependent winner)β”‚
β”‚  plugin.json ("dependencies", "hooks") ──> Silently     β”‚
β”‚                                            Discarded    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

v1.1 Composition Model + Sandboxed Host Runtime:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Agent Host ───────────────────────┐
β”‚  1. Declared Surface & Dependency Check (Pre-Install)   β”‚
β”‚  2. Qualified Identity Router:                          β”‚
β”‚       plugin_a:code-reviewer   vs  plugin_b:code-reviewerβ”‚
β”‚  3. Deterministic Precedence / Disambiguation Policy    β”‚
β”‚  4. Container / Wasm Sandbox for MCP & Hook Execution   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Pattern 1: Qualified Capability Identity (plugin:capability)

A capability must never exist solely in a flat global namespace. Every skill, command, sub-agent, and tool should carry a qualified canonical identity of the form plugin_name:capability_name, treating the bare name (code-review) only as a convenience alias when unambiguous:

from typing import Any, Callable


class QualifiedPluginRegistry:
    """Enforces qualified plugin:capability identity and explicit conflict policy."""

    def __init__(self) -> None:
        self._capabilities: dict[str, Callable[..., Any]] = {}
        self._aliases: dict[str, list[str]] = {}

    def register(
        self,
        plugin_name: str,
        capability_name: str,
        handler: Callable[..., Any],
    ) -> str:
        qualified_id = f"{plugin_name}:{capability_name}"
        if qualified_id in self._capabilities:
            raise ValueError(f"Duplicate capability within plugin: {qualified_id}")

        self._capabilities[qualified_id] = handler
        self._aliases.setdefault(capability_name, []).append(qualified_id)
        return qualified_id

    def resolve(self, identifier: str) -> Callable[..., Any]:
        # 1. Exact qualified lookup ("sentinel:code-reviewer")
        if identifier in self._capabilities:
            return self._capabilities[identifier]

        # 2. Bare alias lookup ("code-reviewer") with deterministic ambiguity error
        matches = self._aliases.get(identifier, [])
        if len(matches) == 1:
            return self._capabilities[matches[0]]
        if len(matches) > 1:
            raise RuntimeError(
                f"Ambiguous capability '{identifier}' claimed by multiple plugins: "
                f"{matches}. Use a qualified 'plugin:capability' identifier."
            )
        raise KeyError(f"Unknown capability: '{identifier}'")

Pattern 2: Declared Capability Surface and Composition Relations in plugin.json

Instead of forcing 32% of authors to write illegal top-level fields that conforming clients silently discard, the manifest schema should allow an optional declared capability surface alongside inter-plugin relations (dependencies, conflicts, and required userConfig). Declaring exported capabilities in plugin.json enables registries, CI pipelines, and host installers to detect name collisions and resolve dependency graphs (an NP-complete problem in non-trivial component models; Abate et al., 2020) before downloading and walking the bundle tree.

Until the v1.1.0 specification incorporates these fields at the top level, authors targeting v1.0.0 hosts should place client-specific and composition metadata inside the sanctioned extensions reverse-domain object and generate any required vendor-specific manifest copies from a single source of truth in CI so the 95.6% multi-manifest drift rate cannot occur.

Pattern 3: Sandboxed MCP and Hook Execution

Finally, even a conflict-free composition model must bound what a plugin can execute on the host. Rather than spawning MCP servers or hook scripts as unisolated host processes inheriting ambient credentials and filesystem access, agent runtimes should execute tool servers inside declarative container or WebAssembly sandboxes with explicit environment allowlists and fail-closed lifecycle hook timeouts:

{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "isolated-code-reviewer",
  "version": "1.0.0",
  "description": "Sandboxed static analysis plugin with explicit capability scoping.",
  "author": { "name": "Arne Burk" },
  "license": "Apache-2.0",
  "extensions": {
    "io.agentruntime.sandbox": {
      "engine": "oci-container",
      "image": "ghcr.io/org/agent-linter:1.0.0",
      "read_only_rootfs": true,
      "required_env": ["LINTER_TOKEN"],
      "hook_policy": "fail_closed"
    }
  }
}

Conclusion: From Package Format to Composition Model

The Agent Plugins v1.0.0 specification solved a real problem: it gave a single plugin bundle an agreed layout on disk. Yet the empirical evidence from 68,072 bundles in AgentPluginZoo proves that standardizing how one extension is shipped does not standardize what happens when several run together.

Turning portable packaging into reliable operational interoperability requires closing both halves of the gap:

  1. For plugin authors today: Always place plugin.json at the bundle root with an explicit $schema declaration (eliminating the cause of 93.6% of load rejections), prefix capability names rather than shipping generic names like code-reviewer, put non-standard metadata inside extensions so hosts do not silently drop 40.2% of manifests' fields, and generate any legacy vendor manifests automatically in CI.
  2. For the specification and host runtimes: Evolve v1.1 from a single-package format into a true composition model with qualified plugin:capability identities, a declared capability surface in plugin.json, deterministic collision and precedence rules, and sandboxed runtime execution boundaries.

Sources & References

  1. [1]
  2. [2]
  3. [3]
  4. [4]
  5. [5]
  6. [6]
  7. [7]
  8. [8]
  9. [9]
  10. [10]
  11. [11]
  12. [12]

Comments (0)

Loading comments...