Install & publish plugins (git URLs)
Plugins can live in their own GitHub repo and be installed by URL — so you can make one and share it, and pull others in. A plugin repo is a full bundle: it can contribute tools, subagents, SKILL.md skills, workflows, console views, routes, MCP servers, and config — all from the one repo. See ADR 0027 for the design + safety model.
Install one
CLI:
python -m server plugin install https://github.com/owner/protoagent-plugin-x --ref v1.0
python -m server plugin list
python -m server plugin uninstall protoagent-plugin-x # code + lock + enabled ref
python -m server plugin uninstall protoagent-plugin-x --purge # also config section + secrets
python -m server plugin sync # re-clone the locked set (CI / fresh checkout)
python -m server plugin install-deps protoagent-plugin-x # explicit, separateUninstall removes the plugin's code, its plugins.lock entry, and its plugins.enabled reference (so nothing dangles). It keeps the plugin's config section + secrets by default (a reinstall restores your settings); pass --purge to remove those too. Declared pip deps are never auto-removed (shared venv) — they're reported so you can pip uninstall them if unused.
Console: Settings → Integrations → Plugins — paste the URL, review the manifest + capabilities, install, uninstall.
Either way, install fetches code only — it does not enable or run it. To enable: add the plugin's id to plugins.enabled in your config and restart.
plugins:
enabled: [protoagent-plugin-x]Install pins the resolved commit SHA and records it in a committed plugins.lock, so plugin sync reproduces the exact set. The code itself is gitignored (re-cloned from the lock).
Publish one
Start from the devkit. Enable the bundled
plugin-devkitplugin (plugins: { enabled: [plugin-devkit] }) — it's the canonical full-bundle example and it gives the agent ascaffold_plugintool, aplugin-architectsubagent +design-pluginworkflow, and thebuilding-pluginsskill. With it on, just ask the agent to "build a plugin that …" and it scaffolds a working skeleton for you to fill in.
A plugin is a directory (its own repo) with a manifest + a register(). The conventional layout — everything here is picked up when the plugin is enabled:
my-plugin/
protoagent.plugin.yaml # manifest (id, name, version, requires_pip, views, …)
__init__.py # def register(registry): … — tools, subagents, etc.
skills/ # SKILL.md skills — auto-discovered (data, no code)
my-skill/SKILL.md
workflows/ # *.yaml workflow recipes — auto-discovered (data)
my-recipe.yamlregister(registry) contributes the code extensions:
def register(registry):
registry.register_tool(my_tool) # a LangChain tool
registry.register_subagent(my_subagent) # a SubagentConfig
registry.register_router(my_router) # FastAPI routes at /plugins/<id>
registry.register_mcp_server(my_factory) # a managed MCP server
# skills/ and workflows/ are auto-discovered — no call needed. For a
# non-standard location: registry.register_workflow_dir("recipes")skills/ and workflows/ are data, so they're auto-discovered from those conventional subdirs — no boilerplate. Console views (a rail icon + page) are declared in the manifest — see Plugin console views.
Declare pip dependencies (they are not auto-installed — see Safety):
# protoagent.plugin.yaml
id: my-plugin
name: My Plugin
version: 1.0.0
repository: https://github.com/owner/my-plugin
requires_pip: ["httpx>=0.27"]
min_protoagent_version: "0.20.0"Get listed in the directory
Anyone can install your plugin from its git URL once it's a public repo. To make it discoverable and feature it on the plugin directory:
- Tag the repo with the
protoagent-pluginGitHub topic — that surfaces it in the topic search across GitHub. - Open a PR adding an entry to
sites/marketing/data/plugins.json(name,tagline,adds,install= your git URL,links). It renders as a card on the directory.
Safety
The model is informed trust + a verifiable supply chain, not a sandbox — an enabled plugin runs in-process as the agent (like a pip dependency). So:
- Install ≠ enable ≠ trust. Installing only fetches code + reads the manifest (data); it never imports the plugin. Enabling (
plugins.enabled) is the trust decision — review the manifest + capabilities first. - Deps are explicit.
requires_pipis declared, never auto-installed (pip runs arbitrary build code). Runplugin install-deps <id>after reviewing them; a missing dep gives a clear "run install-deps" message on enable. - Pinned + reproducible. Installs pin a commit SHA in
plugins.lock. - Optional source allowlist. Lock installs down to trusted orgs:yaml
plugins: sources: allow: ["github.com/yourorg/*"] - Audited. install / uninstall / install-deps are written to the audit log.
- Untrusted code? Use MCP instead — it runs out-of-process and is sandboxable. Git plugins are for code you've reviewed and trust.