wasmtime with the cranelift compiler to execute WebAssembly (WASM) modules while enforcing strict resource constraints and capability-based security. This runtime is primarily used for executing complex tool logic that requires isolation beyond standard process-level sandboxing.
Architecture and Execution Model
The runtime is divided into the core execution engine (palyra-plugins-runtime) and the integration layer within the daemon (palyra-daemon). The execution follows a “Shared-Nothing” architecture where each plugin run is instantiated in a fresh wasmtime::Store with its own memory and fuel allocation.
Plugin Execution Flow
Therun_wasm_plugin function in palyra-daemon serves as the primary entry point, coordinating module resolution, policy validation, and execution.
- Policy Check: The system verifies if WASM execution is enabled and if the module source (inline vs. artifact) complies with
WasmPluginRunnerPolicycrates/palyra-daemon/src/wasm_plugin_runner.rs#101-106. - Module Resolution: Modules can be loaded from inline Base64/WAT strings or from installed Skill artifacts crates/palyra-daemon/src/wasm_plugin_runner.rs#183-214.
- Store Initialization: A
wasmtime::Storeis created with specificRuntimeLimits(memory, table elements, instances) crates/palyra-plugins/runtime/src/lib.rs#161-172. - Resource Budgeting: “Fuel” is injected into the store to limit total instruction execution crates/palyra-plugins/runtime/src/lib.rs#174-174.
- Capability Binding: Host functions are linked to the module, providing controlled access to HTTP, Secrets, and Storage via handle-based indirection crates/palyra-plugins/runtime/src/lib.rs#193-195.
System Integration Diagram
The following diagram illustrates how theWasmRuntime bridges the palyra-daemon tool protocol to the underlying wasmtime engine.
Sources: [crates/palyra-daemon/src/wasm_plugin_runner.rs#96-126](http://crates/palyra-daemon/src/wasm_plugin_runner.rs#96-126), [crates/palyra-plugins/runtime/src/lib.rs#133-150](http://crates/palyra-plugins/runtime/src/lib.rs#133-150), [crates/palyra-daemon/src/tool_protocol.rs#17-17](http://crates/palyra-daemon/src/tool_protocol.rs#17-17)
Resource Controls and Sandboxing
The runtime enforces strict limits to prevent Denial of Service (DoS) attacks and resource exhaustion. These are defined inRuntimeLimits and enforced at the wasmtime level.
| Control | Description | Implementation |
|---|---|---|
| Fuel Budget | Limits the number of WASM instructions executed. | store.set_fuel() crates/palyra-plugins/runtime/src/lib.rs#174-174 |
| Memory Limit | Maximum linear memory (heap) available to the plugin. | StoreLimitsBuilder::memory_size() crates/palyra-plugins/runtime/src/lib.rs#162-162 |
| Table Elements | Limits the number of elements in WASM tables (prevents recursion/stack bombs). | StoreLimitsBuilder::table_elements() crates/palyra-plugins/runtime/src/lib.rs#163-163 |
| Instance Limit | Maximum number of module instances allowed. | StoreLimitsBuilder::instances() crates/palyra-plugins/runtime/src/lib.rs#164-164 |
| Epoch Timeout | Hard wall-clock timeout for execution. | config.epoch_interruption(true) crates/palyra-plugins/runtime/src/lib.rs#118-118 |
Execution State Machine
This diagram shows the lifecycle of a WASM call and the transition to failure states when limits are exceeded. Sources:[crates/palyra-plugins/runtime/src/lib.rs#152-186](http://crates/palyra-plugins/runtime/src/lib.rs#152-186), [crates/palyra-daemon/src/wasm_plugin_runner.rs#38-51](http://crates/palyra-daemon/src/wasm_plugin_runner.rs#38-51)
Capability-Based Security
Plugins do not have direct access to host resources. Instead, they use a handle-based system where the host grants specific permissions during initialization.Capability Grants
TheCapabilityGrantSet defines what a plugin is allowed to access crates/palyra-plugins/runtime/src/lib.rs#42-48:
http_hosts: Allowed domains for outgoing requests.secret_keys: Specific keys the plugin can read from the vault.storage_prefixes: Filesystem paths (scoped to the skill) the plugin can write to.channels: Messaging channels the plugin can interact with.
Handle Indirection
When a plugin requests a capability, the runtime provides ani32 handle. These handles are offset by base constants to prevent accidental collisions crates/palyra-plugins/runtime/src/lib.rs#16-19:
- HTTP: Starts at
10,000 - Secrets: Starts at
20,000 - Storage: Starts at
30,000 - Channels: Starts at
40,000
HOST_CAPABILITY_HTTP_HANDLE_FN) validates that the requested handle exists in the plugin’s CapabilityHandles before proceeding crates/palyra-plugins/runtime/src/lib.rs#63-81.
Plugin SDK Integration
Thepalyra-plugins-sdk provides the standard interface for authoring plugins in Rust. It defines the DEFAULT_RUNTIME_ENTRYPOINT (usually main or run) that the daemon looks for when executing a module crates/palyra-daemon/src/wasm_plugin_runner.rs#9-9.
Tool Protocol Mapping
In thetool_protocol, WASM plugins are treated as high-capability tools. They are automatically assigned capabilities such as Network, SecretsRead, and FilesystemWrite based on their manifest crates/palyra-daemon/src/tool_protocol.rs#137-138.
When a tool call is initiated:
- The
ToolCallConfigprovides theWasmPluginRunnerPolicycrates/palyra-daemon/src/tool_protocol.rs#25-25. - If the tool is a WASM plugin,
run_wasm_pluginis invoked with the provided JSON input crates/palyra-daemon/src/tool_protocol.rs#17-17. - The result is wrapped in a
ToolExecutionOutcome, including aToolAttestationthat captures the executor used (e.g.,wasmtime) and the resources consumed crates/palyra-daemon/src/tool_protocol.rs#83-88.
[crates/palyra-daemon/src/tool_protocol.rs#19-26](http://crates/palyra-daemon/src/tool_protocol.rs#19-26), [crates/palyra-daemon/src/wasm_plugin_runner.rs#96-126](http://crates/palyra-daemon/src/wasm_plugin_runner.rs#96-126), [crates/palyra-plugins/runtime/src/lib.rs#1-15](http://crates/palyra-plugins/runtime/src/lib.rs#1-15)