One package needs two contracts
The useful promise of Agent Plugins 1.0 is deliberately narrow: an author can put a manifest at the root, Agent Skills under skills/, and MCP configuration in mcp.json; a conformant client knows where to look and how to validate the portable fields. GitHub's August 12 rollout across VS Code, Copilot CLI, and the Copilot app turns that promise into a live developer workflow.
The mistake is to read portable as trusted. The normative specification says path containment applies to files supplied by the package, then states that the rule does not sandbox a plugin subprocess or restrict runtime paths. It also leaves distribution, installation, permissions, credential interaction, and user experience to clients. A valid package can still contain a dangerous skill, start an overpowered local server, contact an unexpected service, or change behavior after an update.
Treat the format as the first of two contracts. The conformance contract answers whether the package uses a recognized schema, fixed layout, valid skills, valid MCP entries, contained package paths, and supported version. The execution policy answers whether this source and revision may run here, with these tools, credentials, network destinations, writable paths, users, approval rules, update channel, and evidence requirements.
Schema validation proves that a package can be interpreted consistently. Local policy decides whether interpreting and executing it is acceptable.
The format now has both ecosystem and implementation signal
The Agent Plugins project describes itself as an open, vendor-neutral specification. Its technical charter puts Amazon, Cursor, Microsoft, OpenAI, and Vercel contributors in the initial governance structure and prevents one vendor from controlling a majority of core-maintainer seats. During this research window, the public specification repository showed roughly 1,000 stars and active issues. That is stronger developer signal than an announcement alone.
GitHub's current CLI documentation supports direct repository, repository subdirectory, Git URL, local path, and marketplace installs. It also documents update behavior, precedence, disabled plugins, marketplace refresh, and same-name component collisions. VS Code's current implementation notes go deeper: discovery can come from configured paths, marketplace installs, extension-contributed packages, and Copilot CLI; duplicate packages are canonicalized and only the highest-priority copy is enabled by default.
Community discussion has converged on the important limitation. A current r/devsecops thread summarized the design well: standardize packaging, not trust. The focused last30days run found the specification across GitHub, Hacker News, and Reddit, while broader GitHub Copilot discussions showed real uncertainty about which clients, hosts, and enterprise settings expose the same capabilities. Portability is valuable, but client behavior remains part of the deployed system.
Version 1 defines a small interoperability floor
A conformant package has one root plugin.json. Its closed portable schema allows identity and metadata fields plus reverse-domain extensions. Unknown top-level fields are reported and ignored when the rest of the manifest is valid; most other schema violations are fatal. The client selects locally supported semantics from the canonical $schema identifier rather than fetching a schema during load.
Component discovery is fixed. Immediate child directories under skills/ may contribute one SKILL.md each, and those skills must conform to the Agent Skills specification. MCP servers live in root mcp.json. Version 1 defines no portable commands, hooks, custom agents, rules, LSP servers, marketplace protocol, OAuth configuration, or secret reference. Clients can extend the package under reverse-domain namespaces without pretending those extensions are portable.
| Concern | Portable in v1 | Still client or operator policy |
| Package identity | Root manifest, schema version, name, metadata | Publisher identity, signatures, reputation, allowlist |
| Skills | Fixed discovery and Agent Skills validation | Instruction trust, activation, tool authority, review |
| MCP | stdio, Streamable HTTP, optional SSE configuration | Secrets, authorization, network policy, process sandbox |
| Filesystem | Package-path and configured working-directory containment | Runtime access outside the package and data directory |
| Distribution | Not standardized | Marketplace, direct install, provenance, pinning, updates |
| Extended behavior | Reverse-domain extension namespace | Hooks, agents, commands, UI, and host-specific semantics |
This boundary is a feature. A larger core would either freeze immature behavior or encode one client's assumptions as a universal standard. The practical consequence is that a compatibility claim must name both the portable version and the target client behavior tested.
Build the portable package first, then add explicit extensions
plugin.jsonIdentity, version, repository, license, keywords, and namespaced client extensions.
skills/*/SKILL.mdImmediate-child skills with their own scripts, references, and assets.
mcp.jsonPortable server definitions with transport, one-token command, arguments, environment, and working directory.
vendor.example/Optional client-owned files whose behavior is not part of portable conformance.
Start with the smallest valid manifest. Use an SPDX license identifier when possible and link the exact source repository. Version the behavior, not only the documentation. If an update changes tool authority, network destinations, data handling, or output contract, treat it as behaviorally breaking even when the file schema still validates.
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "acme.release-review",
"version": "1.0.0",
"description": "Prepare release evidence without publishing",
"repository": "https://github.com/acme/release-review-plugin",
"license": "Apache-2.0",
"keywords": ["release", "evidence", "review"],
"extensions": {
"com.acme.agenthost": {
"defaultNetworkPolicy": "deny"
}
}
}
The namespaced network hint is not portable enforcement. A client that owns com.acme.agenthost may interpret it; every other client must ignore it safely. Put portable behavior only where the specification assigns semantics.
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"release-evidence": {
"type": "stdio",
"command": "./bin/release-evidence",
"args": ["--state", "${PLUGIN_DATA}/state"],
"cwd": "${PLUGIN_ROOT}",
"env": {"MODE": "read-only"}
}
}
}
The command is one executable token, not a shell program. Bundled executables use a ./ path; bare names use client-defined platform search. PLUGIN_ROOT refers to immutable package content, while PLUGIN_DATA is client-managed writable state that survives updates. Neither placeholder is a secret.
Put a policy compiler between discovery and execution
A production client should not jump from “manifest parsed” to “server launched.” Build an install pipeline that produces a human-readable and machine-enforceable capability plan.
1. AcquireResolve source, revision, subdirectory, publisher evidence, license, and archive digest.
2. ValidateCheck schemas, fixed paths, resolved containment, skill structure, MCP variants, and client extensions.
3. AnalyzeInventory scripts, commands, packages, endpoints, headers, writable state, tools, and instructions.
4. Compile policyMap declared behavior to allowed network, filesystem, process, credential, tool, and approval capabilities.
5. TestRun conformance, client compatibility, prompt-injection, failure, and least-privilege tests in an isolated fixture.
6. Approve and pinRecord reviewers, evidence, digest, target clients, granted capabilities, expiry, and update route.
The capability plan should be derived from more than mcp.json. A skill can instruct the model to run bundled scripts or call already available tools. A server can expose tools whose names conceal broad effects. Static analysis cannot infer every consequence, but it can make undeclared behavior visible and deny obvious excess before runtime.
plugin: acme.release-review@sha256:4d8...
targets: [copilot-cli-1.3.2, vscode-1.123]
grant:
filesystem:
read: ["${WORKSPACE}/**"]
write: ["${PLUGIN_DATA}/**"]
network: []
secrets: []
tools: [git_diff_read, test_results_read]
deny:
- shell_unrestricted
- workspace_write
- publish_release
approval:
install: platform-security
update: component-or-capability-diff
Test the client projection, not just the archive
The same portable package can yield different effective behavior. A skills-only client can conform without MCP support. A client can ignore an unsupported extension. VS Code's current notes say strict Agent Plugins contribute immediate-child skills and root MCP configuration, while legacy layouts and synthetic bundles follow separate rules. GitHub Copilot CLI documents broader native plugin fields alongside the portable schema, so authors must distinguish strict v1 behavior from host-specific compatibility.
| Test | Expected evidence | Why it matters |
| Discovery | Which manifest won and from which source/root | Duplicate installs and precedence can select another copy |
| Component projection | Loaded, skipped, unsupported, and invalid skills/servers | Partial support is conformant and must not look complete |
| Name collision | Skill, agent, and MCP conflict report | Existing local configuration may override or be overridden |
| Placeholder expansion | Resolved root/data paths without secret leakage | Runtime paths vary by client and installed instance |
| Failure isolation | A failed MCP server does not hide valid skills | Spec requires narrow failure boundaries |
| Disable/uninstall | Effective removal plus persistent-data disposition | Unregistering a source may not delete files or state |
Publish a tested-target matrix with the plugin. “Agent Plugins 1.0 conformant” is useful; “tested on these client versions with these supported components and limitations” is operationally useful.
Keep five security decisions outside the package's control
- Provenance: the installer verifies source ownership, pinned revision, archive digest, license, and review record. A repository URL inside the manifest is metadata, not proof.
- Authority: policy grants a minimal set of filesystem, process, tool, network, and action capabilities. Plugin declarations cannot grant themselves authority.
- Secrets: the client or approved credential broker obtains credentials interactively or by policy and releases them only to the named server and destination. Package
env and headers are visible data, not secret stores.
- Isolation: stdio servers run with OS-level containment, resource limits, controlled environment, and network policy. Package path containment is not process isolation.
- Updates: a new digest triggers component, dependency, instruction, endpoint, and capability diffs. Production moves through staged testing and named approval.
Remote MCP configuration needs redirect discipline. The specification prohibits forwarding configured headers to another origin through redirects without explicit authorization. A client should also pin permitted origins, separate public metadata from credentials, and show the operator which authorization domain will receive a token.
Skills deserve the same scrutiny as executable code. They shape model behavior, decide which references to read, and can direct tool use. Review trigger conditions, instruction precedence, external content handling, write actions, destructive steps, and any claim that asks the agent to suppress approval or evidence.
Failure modes to exercise before install
| Failure | What passes | Control that catches it |
| Schema-valid malicious skill | Manifest and skill structure | Instruction review, tool allowlist, adversarial tests |
| Contained but overpowered server | Command and working-directory containment | Process sandbox, network deny, credential scoping |
| Dependency drift | Plugin archive digest | Lockfiles, reproducible build, dependency policy |
| Auto-update authority expansion | New version validates | Capability diff and staged reapproval |
| Client extension surprise | Portable core validates | Target-client extension review and test matrix |
| MCP name collision | Each entry validates separately | Effective-config report and conflict gate |
| Secret in package data | String types validate | Secret scan and credential-broker rule |
| Partial load mistaken for success | Valid components remain usable | Required-component declaration in local policy |
A practical install and update checklist
- Record the source, revision, subdirectory, archive digest, publisher, repository, license, and requested version.
- Validate
plugin.json and mcp.json against a locally supported schema; never fetch schema code during package load.
- Resolve every discovered path and reject symlink, junction, or reparse-point escapes outside the plugin root.
- Inventory immediate-child skills, scripts, references, MCP servers, transports, commands, arguments, endpoints, headers, and extensions.
- Scan instructions and code for hidden tool use, destructive actions, secret access, prompt injection, downloads, self-modification, and approval bypass.
- Compile a least-privilege grant and compare it with the plugin's actual needs. Deny undeclared behavior by default.
- Run each server in an isolated environment with controlled PATH, environment, writable state, network, CPU, memory, and lifetime.
- Test discovery, collisions, partial failure, disable, uninstall, state retention, and required components on every supported client version.
- Approve a pinned digest with named reviewers, evidence, expiry, rollback version, and incident contact.
- For updates, show component, instruction, dependency, endpoint, extension, and capability diffs before staging and promotion.
Frequently asked questions
Is Agent Plugins 1.0 final?
The public specification labels version 1.0.0 a working draft. Pin the schema version and repository revision used by your tooling, and expect compatibility work as clients implement it.
Does path containment stop a malicious plugin?
It stops defined package paths from escaping the plugin root and constrains selected working-directory forms. It does not sandbox a running server, constrain every runtime path, or make skill instructions safe.
Can a plugin carry secrets in mcp.json?
It should not. The specification says configured environment and header values are visible package data, and it defines no portable credential field. Let the client or credential broker obtain and scope secrets.
Why not standardize permissions in the manifest?
A declaration can help an installer build a capability diff, but authority depends on the user, workspace, device, client, and organization. The package should not be the source of its own grant.
Sources and further reading
Public sources and current documentation were checked on August 17, 2026.
Related technical guides
Use resource graphs, protected lockfile state, serialized CI, and post-apply verification for managed agents.
Build deterministic fixtures, tool mocks, and failure checks around reusable skill behavior.
Understand the tool and data layer that portable plugins can configure.
Put provenance, validation, and human responsibility in the merge path.