Skip to main content
The WASM Plugin Runtime provides a secure, sandboxed execution environment for Palyra skills using the wasmtime engine. It implements a “Capability-Based Security” model where plugins are isolated from the host system and must explicitly request access to external resources like networking, secrets, or storage.

Architecture and Execution Flow

The runtime is divided into two primary layers: the Host Runtime (responsible for resource management and safety) and the SDK Interface (the bridge between WASM guest and Rust host).

Plugin Execution Lifecycle

When a tool call is dispatched to a WASM plugin, the WasmRuntime in palyra-plugins-runtime initializes a fresh wasmtime::Store with strict RuntimeLimits.
  1. Instantiation: The runtime compiles the WASM module and links host functions via a wasmtime::Linker.
  2. Capability Granting: A CapabilityGrantSet is converted into numeric handles that the guest can reference.
  3. Fuel Injection: A specific amount of “fuel” is allocated to the store to prevent infinite loops.
  4. Entrypoint Invocation: The runtime calls the exported function (defaulting to palyra_plugin_main).
  5. Result Capture: The exit code and any state changes are returned to the daemon.

System Sequence: Plugin Invocation

The following diagram illustrates the data flow from the palyra-daemon through the runtime crate into the wasmtime engine. Title: WASM Execution Data Flow Sources: crates/palyra-plugins/runtime/src/lib.rs#133-186, crates/palyra-daemon/src/wasm_plugin_runner.rs#124-154

Runtime Security and Limits

Security is enforced through two primary mechanisms: RuntimeLimits for compute resources and CapabilityGrantSet for external resource access.

Resource Quotas (RuntimeLimits)

The RuntimeLimits struct defines the boundaries of the WASM sandbox to prevent Denial of Service (DoS) attacks on the host daemon.
LimitDescriptionDefault Value
fuel_budgetMaximum instructions allowed per execution.10,000,000
max_memory_bytesMaximum linear memory allocation.64 MiB
max_table_elementsLimit on WASM table size.100,000
max_instancesMaximum concurrent instances allowed.256
Sources: crates/palyra-plugins/runtime/src/lib.rs#24-40

Capability Grants (CapabilityGrantSet)

Plugins operate in a “shared-nothing” environment. Access to the outside world is mediated through handles. The CapabilityGrantSet contains the raw allowlists (e.g., domain names, secret keys), which the runtime maps to CapabilityHandles.
  • HTTP Hosts: Only allowed domains can be contacted via the SDK’s fetch interface.
  • Secrets: Specific keys in the palyra-vault that the plugin is authorized to read.
  • Storage: Filesystem prefixes (roots) where the plugin has write/read access.
  • Channels: Communication handles for interacting with specific Palyra nodes or connectors.
Sources: crates/palyra-plugins/runtime/src/lib.rs#42-60, crates/palyra-daemon/src/wasm_plugin_runner.rs#71-82

Host Function Interface (SDK)

The runtime exports a set of host functions that the WASM guest imports. These functions are registered in the wasmtime::Linker under the module name defined by HOST_CAPABILITIES_IMPORT_MODULE.

Handle Mapping

To prevent the guest from guessing resource locations, the runtime uses base offsets for different resource types:
  • HTTP: 10,000 (HTTP_HANDLE_BASE)
  • Secrets: 20,000 (SECRET_HANDLE_BASE)
  • Storage: 30,000 (STORAGE_HANDLE_BASE)
  • Channels: 40,000 (CHANNEL_HANDLE_BASE)

Implementation Detail: register_capability_bindings

The register_capability_bindings function maps these handles so the guest can query how many resources it has and retrieve their handles. Title: Host Capability Mapping Sources: crates/palyra-plugins/runtime/src/lib.rs#16-21, crates/palyra-plugins/runtime/src/lib.rs#206-215

Daemon Integration and Policy

The palyra-daemon wraps the low-level runtime in a WasmPluginRunnerPolicy. This policy determines if inline modules (WAT/Base64) are allowed and enforces global maximums that override individual skill manifests.

Execution Policy Configuration

The WasmPluginRunnerPolicy struct mirrors the runtime limits but adds daemon-level controls.
pub struct WasmPluginRunnerPolicy {
    pub enabled: bool,
    pub allow_inline_modules: bool,
    pub max_module_size_bytes: u64,
    pub fuel_budget: u64,
    // ... handles, memory, and allowlists
}
Sources: crates/palyra-daemon/src/wasm_plugin_runner.rs#18-30

Error Handling

The runtime maps internal wasmtime traps and resource exhaustion to WasmPluginRunErrorKind:
  • QuotaExceeded: Triggered when fuel is exhausted or memory limits are hit.
  • CapabilityDenied: Triggered if a plugin attempts to access a resource not in its CapabilityGrantSet.
  • RuntimeFailure: General WASM trap or compilation error.
Sources: crates/palyra-daemon/src/wasm_plugin_runner.rs#43-51, crates/palyra-plugins/runtime/src/lib.rs#89-103