-
-
Notifications
You must be signed in to change notification settings - Fork 119
WASM Plugins
CortexPrism's WASM plugin system lets you write high-performance plugins in any language that compiles to WebAssembly — C, Rust, Zig, Go, AssemblyScript, and more.
WASM plugins run in a dedicated sandbox with synchronous host functions. The host provides logging, HTTP requests, state persistence, configuration, time, and randomness. All host ↔ plugin communication uses compiler-agnostic C-compatible function signatures over linear memory.
# Install a WASM plugin from marketplace
cortex plugins install @acme/wasm-plugin
# Or from a local .wasm file
cortex plugins install ./my-plugin/manifest.json
# List to verify it loaded
cortex plugins listManifest for a WASM plugin:
{
"name": "my-wasm-plugin",
"version": "1.0.0",
"description": "A WASM plugin",
"kind": "wasm",
"entryPoint": "./plugin.wasm",
"runtime": "wasm",
"capabilities": ["tools", "network:fetch"]
}Every WASM plugin must declare its ABI version. The host checks this on load and rejects incompatible versions. This ensures forward/backward compatibility as the host API evolves.
Current host ABI version: 1. All plugins must match.
int32_t plugin_get_abi_version(void) { return 1; }The host also exports host_get_abi_version() so plugins can verify at runtime.
Address | Size | Owner | Purpose
─────────────────┼────────┼────────┼────────────────────────────────────
0x000000–0x00FFFF | 64 KB | Host | Scratch area — temporary buffers
0x010000–0x01FFFF | 64 KB | Host | Allocator metadata
0x020000–0x0FFFFF | 896 KB | Host | Managed heap (host_alloc/host_free)
0x100000+ | varies | Plugin | Your data — __heap_base starts here
Default allocation: 256 pages initial (16 MiB), 512 pages max (32 MiB). Grow automatically on demand.
All imported as env.*. Strings are UTF-8 passed as (pointer, length) pairs. Return 0 on
success.
| Function | Signature | Description |
|---|---|---|
host_alloc |
(size: i32) → i32 |
Bump-allocate from host-managed heap. Returns 8-byte aligned pointer or 0 on failure. |
host_free |
(ptr: i32) → void |
Free allocation (current no-op; call for forward compatibility). |
| Function | Signature | Description |
|---|---|---|
host_log |
(ptr: i32, len: i32) → void |
Log a message to the CortexPrism log system. Appears in server logs and Lens audit trail. |
host_get_abi_version |
() → i32 |
Returns host ABI version (currently 1). |
host_get_time_ms |
() → i64 |
Current time in milliseconds since Unix epoch. |
host_random |
(outPtr: i32, len: i32) → void |
Fill len bytes with cryptographically random data. |
| Function | Signature | Description |
|---|---|---|
host_get_config |
(keyPtr, keyLen, outPtr, outLenPtr) → i32 |
Read config. Priority: CORTEX_PLUGIN_{NAME}_{KEY} → CORTEX_WASM_{KEY}. Returns -1 if not found. |
host_set_state |
(keyPtr, keyLen, valPtr, valLen) → void |
Persist key-value state. In-memory cache + async SQLite flush. Survives reloads. |
host_get_state |
(keyPtr, keyLen, outPtr, outLenPtr) → i32 |
Read persisted state. Returns -1 if not found. |
| Function | Signature | Description |
|---|---|---|
host_http_request |
(methodPtr, methodLen, urlPtr, urlLen, bodyPtr, bodyLen, headersPtr, headersLen, outStatusPtr, outBodyPtr, outBodyLenPtr) → i32 |
Synchronous HTTP request. Headers are a JSON object string. 30 s timeout. Requires network:fetch or net:outbound capability. Returns status code and body. |
host_http_request is the most powerful host function. It uses a dedicated Worker thread +
SharedArrayBuffer + Atomics.wait to provide truly synchronous HTTP while keeping the main thread
responsive. The 30-second timeout prevents hung requests from blocking the agent loop.
Headers format: '{"Content-Type":"application/json","Authorization":"Bearer ..."}'
| Export | Signature | Purpose |
|---|---|---|
plugin_get_abi_version |
() → i32 |
Return ABI version (must be 1) |
plugin_get_capabilities |
(outPtr, outLenPtr) → i32 |
Return capabilities JSON |
plugin_execute_tool |
(namePtr, nameLen, argsPtr, argsLen, outPtr, outLenPtr) → i32 |
Execute a tool |
memory |
WebAssembly.Memory |
Linear memory |
| Export | Signature | Purpose |
|---|---|---|
plugin_init |
() → void |
Called once after instantiation |
plugin_destroy |
() → void |
Called on unload — free resources, flush buffers |
plugin_get_capabilities must write a JSON object to outPtr and its length to outLenPtr.
Include full parameter schemas so LLMs understand what arguments your tools expect:
{
"abi_version": 1,
"tools": [
{
"name": "search_docs",
"description": "Search documentation by keyword",
"params": [
{ "name": "query", "type": "string", "description": "Search query", "required": true },
{ "name": "limit", "type": "number", "description": "Max results (1-100)", "required": false }
]
}
]
}Parameter types: string | number | boolean | object | array
Install: fetch .wasm → instantiate → plugin_get_abi_version → plugin_init → plugin_get_capabilities
Enable: (same as install if not already loaded)
Execute: plugin_execute_tool (called per agent tool invocation, up to 120 s)
Disable: plugin_destroy → free memory → clear state cache
Remove: plugin_destroy → delete from plugins.db → remove plugin dir
WASM plugins have no direct filesystem, shell, or database access. Available operations are limited
to the host functions listed above. host_http_request is gated on the network:fetch or
net:outbound capability declared in the manifest.
If a WASM plugin attempts host_http_request without the required capability, it receives HTTP 403.
All other host functions are always available.
WASM binaries undergo specialized scanning during plugin installation:
| Check | Description |
|---|---|
| Magic bytes | Must start with \x00asm
|
| WASM version | Must be version 1 |
| Suspicious imports | Blocks wasi_snapshot_preview1.proc_exit, args_get, environ_get, sock_open, sock_connect
|
| Unknown env imports | Warns on imports not recognized as host functions |
| Memory request | Blocks > 4 GB; warns on > 64 MB |
| Binary size | Warns if > 100 MB |
The standard text-based malware scan (eval, child_process, rm -rf /) is skipped for WASM
binaries since those patterns are meaningless in binary format.
#include "wasm-plugin.h"
int32_t plugin_get_abi_version(void) { return 1; }
void plugin_init(void) {
host_log("Ready", 5);
}
int32_t plugin_get_capabilities(char* out, uint32_t* outLen) {
const char* json = "{\"abi_version\":1,\"tools\":[{\"name\":\"my_tool\","
"\"description\":\"Example\",\"params\":[{\"name\":\"input\","
"\"type\":\"string\",\"description\":\"Input\",\"required\":true}]}]}";
uint32_t len = strlen(json);
memcpy(out, json, len);
*outLen = len;
return 0;
}
int32_t plugin_execute_tool(
const char* namePtr, uint32_t nameLen,
const char* argsPtr, uint32_t argsLen,
char* outPtr, uint32_t* outLen) {
// Parse argsJson, dispatch to tool, write result
const char* result = "{\"ok\":true}";
uint32_t len = strlen(result);
memcpy(outPtr, result, len);
*outLen = len;
return 0;
}
void plugin_destroy(void) { /* cleanup */ }Compile with any WASM toolchain:
# C with clang
clang --target=wasm32 -nostdlib -o plugin.wasm plugin.c
# Rust
cargo build --target wasm32-unknown-unknown --release
# Zig
zig build-exe plugin.zig -target wasm32-freestandingimport { definePlugin, defineTool, generateCapabilitiesJson } from './sdk/client.ts';
const echo = defineTool({
name: 'echo',
description: 'Echoes input back',
params: [{ name: 'message', type: 'string', description: 'The message', required: true }],
execute(args) {
return { echoed: args.message };
},
});
export default definePlugin({ name: 'my-plugin', version: '1.0.0', tools: [echo] });| Symptom | Likely Cause |
|---|---|
Status: error on load |
ABI version mismatch, missing required export, invalid WASM binary |
host_http_request returns 403 |
network:fetch capability not declared in manifest |
| Tool returns "WASM trap" | Plugin crashed — check for null pointer dereference, stack overflow, or infinite recursion |
| State lost after restart | Call host_set_state to persist; in-memory-only data is not saved |
| Install blocked | Supply-chain scan detected suspicious imports or excessive memory request |
Get runtime diagnostics:
import { getWasmDiagnostics } from './wasm-runtime.ts';
const diag = getWasmDiagnostics('my-wasm-plugin');
// { memoryBytes, heapPtr, abiVersion, toolCount }- Plugin System — Architecture overview, lifecycle, security model
- Developing Plugins — Full ESM/MCP/WASM development guide
- Manifest Reference — Complete manifest schema
- Security — Supply-chain verification details
CortexPrism — Open-source AI agent operating system · Discord · Apache 2.0 License · Built with Deno 2.x + TypeScript
- Agent Loop
- Built-in Agents
- Metacognition
- Memory System
- Skills System
- Sub-Agents
- Built-in Tools
- Code Intelligence
- Code Sandbox
- Cross-Agent Context Protocol
- Prompt Lab
- PKM Assistant
- Voice Pipeline
- Computer Use
- Browser Tool
- Git & GitHub
- Scheduler & Jobs
- Dashboard
- Observability
- A2A Protocol
- MCP Gateway
- Distributed Nodes
- Memori Checkpoints
- Eval System
- Workflow Engine
- Triggers
- Projects
- TUI
- Glossary
- Update System
- Chrome Bridge
- Swarm
- AgentLint
- Model Benchmarking
- Smart Context
- Cost Optimizer