WASM Tools
Run tools in isolated WebAssembly sandboxes with Extism for security, speed, and portability.
Overview
The @cogitator-ai/wasm-tools package provides tools that execute inside WebAssembly sandboxes powered by Extism. Compared to Docker-based sandboxing, WASM tools offer:
- 100-500x faster cold start than Docker containers
- ~20x lower memory footprint per tool instance
- Memory-safe execution in an isolated linear memory space
- No network access by default -- tools cannot make outbound calls unless WASI is enabled
import { createCalcTool, createHashTool, createCsvTool } from '@cogitator-ai/wasm-tools';
const agent = new Agent({
name: 'data-processor',
model: 'openai/gpt-4o',
tools: [createCalcTool(), createHashTool(), createCsvTool()],
});Pre-built WASM Tools
The package ships with 14 ready-to-use WASM tool factories. Each returns a Tool instance backed by a compiled .wasm module.
| Factory | Tool Name | Description |
|---|---|---|
createCalcTool() | calculate | Evaluate math expressions (+, -, *, /, %, parens) |
createJsonTool() | process_json | Parse JSON and query with JSONPath |
createHashTool() | hash_text | Cryptographic hashes (SHA-256, SHA-1, MD5) |
createBase64Tool() | base64 | Encode/decode Base64 (standard and URL-safe) |
createSlugTool() | slug | Convert text to URL-safe slugs with transliteration |
createValidationTool() | validate | Validate email, URL, UUID, IPv4, IPv6 |
createDiffTool() | diff | Generate diffs between texts (Myers algorithm) |
createRegexTool() | regex | Regex operations with ReDoS protection |
createCsvTool() | csv | Parse/generate CSV data (RFC 4180) |
createMarkdownTool() | markdown | Convert Markdown to HTML (GFM subset) |
createXmlTool() | xml | Parse XML to JSON with XPath-like queries |
createDatetimeTool() | datetime | Parse, format, manipulate dates (UTC + offsets) |
createCompressionTool() | compression | Gzip compress/decompress data |
createSigningTool() | signing | Ed25519 keypair generation, sign, and verify |
Every factory accepts an optional { timeout } config:
const calc = createCalcTool({ timeout: 10000 });Defining Custom WASM Tools
Use defineWasmTool() to wrap any .wasm module as a Cogitator tool:
import { defineWasmTool } from '@cogitator-ai/wasm-tools';
import { z } from 'zod';
const imageProcessor = defineWasmTool({
name: 'process_image',
description: 'Resize and crop images in a WASM sandbox',
wasmModule: './plugins/image-proc.wasm',
wasmFunction: 'process',
parameters: z.object({
imageData: z.string().describe('Base64-encoded image'),
operation: z.enum(['resize', 'crop', 'rotate']),
width: z.number().optional(),
height: z.number().optional(),
}),
category: 'utility',
tags: ['image', 'processing'],
timeout: 10000,
wasi: false,
});WasmToolConfig
| Field | Type | Description |
|---|---|---|
name | string | Tool name for LLM function calling |
description | string | What the tool does (shown to the LLM) |
wasmModule | string | Path or URL to the .wasm file |
wasmFunction | string | Exported function to call (default: run) |
parameters | ZodType | Zod schema for input validation |
category | ToolCategory | Optional category for grouping |
tags | string[] | Optional tags for discovery |
timeout | number | Execution timeout in ms (default: 5000) |
wasi | boolean | Enable WASI for filesystem/env access |
memoryPages | number | WASM linear memory pages to allocate |
WasmToolManager
For dynamic loading, hot-reloading, and managing multiple WASM modules at runtime, use WasmToolManager:
import { WasmToolManager } from '@cogitator-ai/wasm-tools';
const manager = new WasmToolManager({ debounceMs: 100, useWasi: false });
const tool = await manager.load('./plugins/calc.wasm');
const agent = new Agent({
name: 'dynamic-agent',
model: 'openai/gpt-4o',
tools: manager.getTools(),
});File Watching
The manager can watch a glob pattern for .wasm files and automatically load, reload, or unload modules as they change on disk:
await manager.watch('./plugins/*.wasm', {
onLoad: (name, path) => console.log(`Loaded: ${name}`),
onReload: (name, path) => console.log(`Reloaded: ${name}`),
onUnload: (name, path) => console.log(`Unloaded: ${name}`),
onError: (name, path, error) => console.error(`Error: ${name}`, error),
});When a .wasm file is modified, the manager closes the old plugin instance and loads the new one -- zero-downtime hot reload for agent tools.
Manager API
const tool = await manager.load('./path/to/module.wasm');
const allTools = manager.getTools();
const specific = manager.getTool('calc');
const mod = manager.getModule('calc');
// { name, path, plugin, tool, loadedAt }
await manager.close();How WASM Sandboxing Works
Each WASM tool runs inside an Extism plugin -- a lightweight WebAssembly runtime with strict isolation:
- Loading: The
WasmLoaderreads the.wasmbinary from disk or URL and instantiates it via the Extism SDK - Execution: Input parameters are JSON-serialized and passed to the exported WASM function via
plugin.call(functionName, input) - Output: The WASM function returns a byte buffer, which is parsed as JSON (or returned as raw text if parsing fails)
- Isolation: Each plugin has its own linear memory space -- it cannot access the host process memory, file system, or network unless WASI is explicitly enabled
┌─────────────────────────────────────┐
│ Host Process (Node.js) │
│ │
│ params ──► JSON.stringify ──────┐ │
│ │ │
│ ┌───────────────────────────────▼─┐ │
│ │ Extism WASM Sandbox │ │
│ │ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ Linear Memory (64MB) │ │ │
│ │ │ No host access │ │ │
│ │ │ No network │ │ │
│ │ │ No filesystem │ │ │
│ │ └─────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────┬─┘ │
│ │ │
│ result ◄── JSON.parse ◄────────┘ │
└─────────────────────────────────────┘Security Benefits
- No
evalor dynamic code execution -- computation is compiled ahead of time into WASM bytecode - Memory bounds checking -- buffer overflows in WASM trap instead of corrupting host memory
- Deterministic execution -- same input always produces same output (no ambient authority)
- Timeout enforcement -- long-running computations are killed after the configured timeout
- ReDoS protection -- regex tools in WASM are immune to catastrophic backtracking in the host runtime
WASM vs Docker Sandboxing
| Aspect | WASM (Extism) | Docker |
|---|---|---|
| Cold start | < 5 ms | 500 ms - 2 s |
| Memory overhead | ~2 MB per instance | ~50 MB per container |
| Isolation | Linear memory | Full OS-level |
| Network access | None (unless WASI) | Configurable |
| File system | None (unless WASI) | Mountable volumes |
| Best for | Pure computation | I/O-heavy, multi-process |
Use WASM tools when you need fast, lightweight sandboxing for pure computation (hashing, parsing, math, text processing). Use Docker sandboxing when tools need file system access, network calls, or a full OS environment.