Agent Plugins
Rho loads Agent Plugins 1.0.0 packages from explicit local roots. A plugin is a directory with a plugin.json manifest. It contributes skills, MCP servers, or both. Plugin skills join the ordinary metadata-first skill flow. Plugin MCP servers run on the same native runtime as ordinary [mcp.servers] entries.
The Agent Plugins 1.0.0 specification is a Working Draft. Rho selects the validation contract from the manifest $schema identifier and never fetches schemas at runtime.
Package layout
my-plugin/
├── plugin.json
├── skills/
│ └── summarize/
│ ├── SKILL.md
│ └── references/
│ └── checklist.md
└── mcp.jsonplugin.json is required and loads before any component. skills/ and mcp.json are optional; a missing location is not an error.
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "my-plugin",
"version": "1.0.0",
"description": "Brief plugin description"
}The manifest schema is closed. Rho reports and ignores unknown top-level fields, and reports and ignores a non-object extensions field. Any other schema violation rejects the plugin before component discovery. Plugin names use 1-64 characters from a-z, 0-9, -, and ., and start and end with a letter or digit.
Discovery roots
Rho checks explicit roots only. It never searches arbitrary directories.
<project>/.agents/plugins/<plugin>/plugin.json (nearest directory first, up to the repository root)
~/.agents/plugins/<plugin>/plugin.jsonOnly immediate child directories, and immediate child symlinks whose resolved targets contain a plugin.json, are plugins. When two roots contain the same plugin name, the nearer root wins and Rho reports the shadowed copy. Installed and linked packages use these same roots.
Supported component types in the current build: skills, and MCP servers with the stdio and streamable-http transports. Legacy sse entries are skipped per server. Rho implements no client extension namespaces.
Skills
Each immediate child directory of skills/ with a regular SKILL.md is one skill. Rho does not recurse for nested skills. Frontmatter follows the Agent Skills specification, and the skill name must match its directory name. An invalid skill is skipped and reported; valid siblings and the plugin's MCP servers still load.
Plugin skills sit below every loose skill location in skill precedence:
built-in > loose user > loose project > project plugins > user pluginsDuplicate skill names across sources keep the higher-precedence copy and log the selected and ignored sources.
MCP servers
mcp.json at the plugin root declares servers. Rho validates the top-level document first, then each server independently, and translates valid entries into the ordinary native MCP configuration. Transport setup, handshake, tool discovery, namespacing, permissions, and shutdown all reuse the path documented in Model Context Protocol. A plugin server appears in inventories as <plugin-name>/<server-name>.
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"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" }
}
}
}Rules Rho enforces:
mcp.jsonmust target the same Agent Plugins version asplugin.json.- A stdio
commandis one token: a bare executable name resolved through the platform search path, or a plugin-relative path starting with./. cwddefaults to the plugin root. An explicitcwdis plugin-relative,${PLUGIN_ROOT}-rooted, or${PLUGIN_DATA}-rooted, and must stay inside that directory.${PLUGIN_ROOT}and${PLUGIN_DATA}expand inargs, environment values, andcwdonly. Expansion is single-pass and non-recursive. Unrecognized placeholder-like text stays literal. Placeholders never apply tocommand, URLs, headers, or environment variable names.- Rho provides
PLUGIN_ROOTandPLUGIN_DATAin each stdio subprocess environment. The data directory lives at<plugins-root>/data/<plugin>and persists across plugin updates. Plugins cannot override either variable. - Remote URLs are absolute HTTP or HTTPS URLs without user information or fragments, and non-loopback endpoints must use HTTPS. Headers are literal package data. Rho disables HTTP redirects for these transports, so configured headers never cross origins.
An invalid top-level mcp.json disables MCP for that plugin only. An invalid server entry disables only that entry. A plugin with no valid MCP servers adds no MCP startup work.
Containment and failure isolation
Every package-supplied path Rho reads or executes must resolve inside the filesystem-resolved plugin root. Symlinks that escape the root are rejected at the narrowest boundary: the plugin for plugin.json, the component type for a fixed location, the skill for a SKILL.md, or the server entry for a command or working directory.
Install roots and lifecycle
Rho manages packages in the same explicit roots it discovers:
~/.agents/plugins/<name>/ user scope (default for install and link)
<repository>/.agents/plugins/<name>/ project scope (`--scope project`)Lifecycle commands:
rho plugins list
rho plugins inspect <name>
rho plugins install <path> [--scope user|project] [--force]
rho plugins link <path> [--scope user|project] [--force]
rho plugins enable <name>
rho plugins disable <name>
rho plugins remove <name> [--yes]Behavior:
installvalidatesplugin.jsonfirst, then copies the package into the managed root. It never executes package code.linkvalidates first, then creates a directory symlink in the managed root.inspectandlistread manifests and component metadata only. They do not connect MCP servers or run skill scripts. Userho mcp list//mcpfor live MCP status.disablekeeps package files on disk and drops the package's skills and MCP servers from new sessions.removedeletes only the package directory or symlink under a managed root. It does not delete<plugins-root>/data/<plugin>runtime data.--forceis required to replace an existing package at the destination.- Destination paths must be immediate children of a managed root. The reserved
data/directory is never a package slot.
Activation state
Enable and disable state is Rho policy, not part of the Agent Plugins package format. State files live outside package directories:
$RHO_HOME/plugins.toml user scope (default `~/.rho/plugins.toml`)
<repository>/.rho/plugins.toml project scopeA missing file means every discovered plugin is enabled. Disabling writes enabled = false for that package name in the matching scope file. Package contents are never modified.
Precedence
Discovery order and conflict rules:
project plugins (nearest ancestor first) > user pluginsWithin that order:
- The first valid package for a given plugin name wins.
- Later packages with the same name are reported as shadowed.
- Disabled packages stay visible in
rho plugins list/inspectbut do not contribute skills or MCP servers. - Loose skills still outrank every plugin skill (
built-in > loose user > loose project > project plugins > user plugins). - Ordinary
[mcp.servers]identities stay separate from plugin-scoped<plugin>/<server>identities.
When the same plugin name exists in more than one root, enable, disable, and remove act on the higher-precedence match.
Diagnostics
- Session logs report rejected plugins, shadowed duplicates, disabled packages, invalid skills, invalid MCP entries, unsupported transports, and plugins with no usable components.
/doctorincludes an Agent Plugins check with loaded, disabled, and problem counts.rho plugins listandrho plugins inspectshow package inventory, scope, origin (local,install, orlink), enablement, component names, and diagnostics without executing package code./mcpandrho mcp listshow live plugin servers alongside ordinary servers, with status, errors, and exported tool names.- Plugin-owned skills keep their owner in the skill source model (
plugin <name> (...)), so inventory and skill listings can show which package contributed a skill.
Trust
- Manifest inspection, install validation, and list/inspect never execute package code.
- Skills can still direct the agent to run scripts and touch resources through ordinary Rho permissions after a package is enabled and loaded into a session.
- MCP servers from enabled packages use the same permission, cancellation, and output paths as ordinary MCP configuration. Remote registry install, automatic updates, and package signatures are not implemented yet.
Relationship to ordinary configuration
Ordinary [mcp.servers] entries and loose skills keep working unchanged. Plugin servers merge with ordinary servers under their namespaced identities, and ordinary config keeps full precedence for its own identities.
What comes from Agent Plugins versus Rho policy:
| Behavior | Source |
|---|---|
Package layout, plugin.json, skills/, mcp.json, path containment | Agent Plugins |
| Explicit discovery roots and component loading | Agent Plugins, with Rho root choices |
| Install, link, enable, disable, remove commands | Rho policy |
| Enablement state files and managed install roots | Rho policy |
| Skill and MCP runtime behavior after load | Rho |
Remote registry distribution and automatic updates remain unsupported.