Skip to main content
A plugin is a WebAssembly component that exports tools to the agent. Plugins run inside the runtime’s Wasmtime sandbox, with no filesystem and no network unless the package is granted them. They are how a builder gives a machine its own actions.

Create a package

The directory name becomes the plugin name. It must start with a lowercase letter or underscore, use only lowercase letters, digits, and underscores, and be at most 64 characters. The command refuses to overwrite an existing path. The starter package contains two working tools, ping and note, a one-step SOP, a skill, a record schema, and the WIT interface files. Each file starts with a note saying what to replace.

The manifest

manifest.toml
string[]
required
What the package provides. tool for tools, skill for a skills/ directory. The runtime also understands channel, memory, and observer.
string[]
What the tools may use: state_read, state_write, config_read, http_client, websocket_client, socket_client, memory_read, memory_write, file_read, file_write. Anything not listed is denied at the host boundary.
string[]
Hosts the plugin intends to reach, exact names or *.suffix patterns. A declaration is not a grant. The effective allowlist lives in the operator’s config (plugins.entries[].egress_hosts). On first install it is seeded from this list and printed, and a reinstall never widens an existing grant.
object
JSON Schema for the plugin’s own config section. A top-level string property with x-secret = true is withheld from public config and served only through the secrets import. Add config_read to permissions together with a schema.

Write tools

A multi-tool package implements the tools-plugin world. The host calls list-tools once at load time and registers each name, then calls execute per invocation.
src/lib.rs
A single-tool component can export the older tool interface from the tool-plugin world instead. Both are supported.
Do not return chat ids, wallet addresses, access codes, or other personal data in tool output or store them in state. Tool output goes to the model, and the model can put it in a record.

Build

kinetic build runs the system Cargo for the wasm32-wasip2 target, copies the component to wasm_path, and writes its SHA-256 into the manifest:
The build machine needs Rust. The device does not: you can build on a laptop and copy the package over.

Install a package

Install is one transaction across several pieces of device state. If any step fails, everything before it is rolled back.
1

Verify the component

The component is copied into the plugins directory and loaded against this host’s WIT. A component built against a different interface is refused. --no-verify skips this check, and a plugin that does not load is then skipped at startup.
2

Seed config and egress

A [[plugins.entries]] row is created for the plugin. Declared egress hosts are granted and printed. Plugin config values are set with kinetic config set plugins.entries.<name>.config.<key>.
3

Install the procedure

If the package has sop/SOP.toml and SOP is enabled, the procedure is copied to <sops_dir>/<name>/. An existing procedure with the same name is left in place.
4

Write the record schema

If the package has records.example.toml, its fields replace [records] in the device config. Comments elsewhere in the config are kept.
Restart the runtime after installing so the agent loads the new tools.

Manage plugins

Plugin tools are not attested automatically. Attest completed operations explicitly with monad_attest, usually as the last step of a SOP.