Skip to main content
Add an Agent Plugins 1.0 package to plugins/ to give your managed ADK or LangGraph agent reusable skills, MCP servers, or both. Harnest reads its declarations and connects them to the framework’s native runtime. You do not import the plugin or register its components in Python. Advanced-mode applications retain their native composition and must wire equivalent capabilities themselves.
Need Python APIs, SDK dependencies, typed context, or lifecycle behavior? Build a Harnest Extension in extensions/. Application hooks and resource factories belong in lifecycle/.

Add a plugin

From the agent folder, install a reviewed local package into the project:
Harnest validates the Agent Plugins 1.0 manifest without importing or executing package code, then copies ordinary files into plugins/<manifest-name> through same-filesystem staging. It rejects links, special files, and an existing destination. Pass --force only when you intend to replace that complete installed package; a failed final swap restores the previous package. The installer currently accepts local directories. It does not invent a registry or download protocol that the Agent Plugins specification does not define. harnest extensions search remains the separate discovery command for executable Harnest Extensions. Place each package in its own directory. Keep the package’s root plugin.json intact:
plugins/warehouse/plugin.json
The manifest requires the canonical $schema shown above and a name. That name identifies the plugin, even when its enclosing directory has a different name. Both component locations are optional: a skills-only, MCP-only, or manifest-only package is valid. Plugin skills join the agent’s skill registry and load on demand through list_skills, load_skill, and load_skill_resource. Plugin MCP servers join direct connections from mcp/. Use a skill to explain when to call its tools, which inputs they need, and how to interpret their output. Rebuild after adding a package, or use development reload while serving locally.

Attach a plugin after compilation

Agent Desktop can attach Agent Plugins when it creates a session. The desktop client owns discovery and download: it resolves the user-provided Git or marketplace URL, creates a ZIP with plugin.json at its root, and sends that immutable snapshot to Harnest. Harnest does not fetch a plugin URL.
POST /sessions
sha256 is optional. When supplied, it must match the decoded ZIP. Harnest always computes its own digest and returns each plugin’s name and sha256 in the session metadata.plugins array. The archive itself stays in private session application data so a durable session can recover its exact environment after a server restart. The plugin set is fixed when the session is created. Create another session to add, remove, or update a plugin. Dynamic attachment currently requires a managed root Agent; managed Graph and advanced applications retain their compiled capability wiring. Harnest accepts at most 16 plugins per session and regular files only. It rejects encrypted members, links, absolute or parent paths, case-insensitive path collisions, more than 256 files, files larger than 4 MiB, archives larger than 8 MiB, and expanded content larger than 32 MiB. The server’s configured limits.max_request_bytes also applies to the base64 JSON request and may impose a lower effective limit.
Treat the URL as untrusted input in Agent Desktop. Apply download timeouts, redirect and credential policy, and archive size limits before sending the snapshot. Do not forward a URL for Harnest to fetch.

Configure MCP servers

Portable MCP declarations live in root mcp.json, not Python factories. Each server declares its transport explicitly:
plugins/warehouse/mcp.json
Harnest opens connections at runtime through the ADK or LangGraph adapter. Compilation reads configuration without starting an MCP server.

Local processes and persistent data

For a package that includes server.py, a stdio declaration can use:
plugins/warehouse/mcp.json
The server and its dependencies must already be available. Harnest does not turn mcp.json into a dependency installer. command is one executable name, such as python, or a bundled executable path beginning with ./; it is not a shell command string. Harnest supplies both variables to each stdio subprocess. Persistent data lives below $XDG_DATA_HOME/harnest/agent-plugins, or ~/.local/share/harnest/agent-plugins when XDG_DATA_HOME is unset. Set HARNEST_PLUGIN_DATA_DIR to override that base directory. Harnest separates data by installation and plugin; package updates do not erase it. Only ${PLUGIN_ROOT} and ${PLUGIN_DATA} expand, and only in stdio args, env values, and cwd. Other placeholders stay literal. Do not override the reserved variables in env. An omitted cwd uses the package directory. An explicit cwd must start with ./, ${PLUGIN_ROOT}, or ${PLUGIN_DATA} and remain inside the corresponding directory after resolution.
A plugin subprocess runs executable code with the server process’s permissions. Package-path validation does not sandbox that process. Review packages before adding them.

Remote connections and credentials

Remote URLs require HTTPS except for loopback hosts. URL and header values are literal: ${TOKEN} does not read an environment variable. Do not embed secrets in plugin headers or stdio environment declarations. Harnest-owned MCP HTTP clients inherit the process’s standard uppercase and lowercase HTTP(S) and ALL_PROXY variables. Released installs include SOCKS transport support, including socks5h:// proxy URLs. This preserves operator-managed enterprise egress. Remove the relevant proxy variables from the Harnest process when a connection must bypass environment proxy discovery; proxy URLs and credentials are omitted from client-construction diagnostics. Authentication is client-managed; Agent Plugins 1.0 does not define portable credential references or OAuth configuration. When your application needs custom credential resolution, configure a direct MCP client with Harnest’s credential providers.

Validation and diagnostics

Harnest validates the manifest before discovering components. An invalid manifest rejects that plugin. Invalid skill entries or MCP server entries are skipped with diagnostics while valid siblings continue loading. An invalid mcp.json disables that plugin’s MCP component without disabling its skills. Unknown client namespaces in the manifest’s extensions field and matching client-specific directories are ignored. They do not become Harnest Extensions or lifecycle hooks. Harnest does not import arbitrary Python modules from a standard plugin.

Author Agent Skills

Write focused instructions and load supporting resources on demand.

Build a Harnest Extension

Package Python functionality, lifecycle behavior, and typed context.