Cogitator
Tools

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.

FactoryTool NameDescription
createCalcTool()calculateEvaluate math expressions (+, -, *, /, %, parens)
createJsonTool()process_jsonParse JSON and query with JSONPath
createHashTool()hash_textCryptographic hashes (SHA-256, SHA-1, MD5)
createBase64Tool()base64Encode/decode Base64 (standard and URL-safe)
createSlugTool()slugConvert text to URL-safe slugs with transliteration
createValidationTool()validateValidate email, URL, UUID, IPv4, IPv6
createDiffTool()diffGenerate diffs between texts (Myers algorithm)
createRegexTool()regexRegex operations with ReDoS protection
createCsvTool()csvParse/generate CSV data (RFC 4180)
createMarkdownTool()markdownConvert Markdown to HTML (GFM subset)
createXmlTool()xmlParse XML to JSON with XPath-like queries
createDatetimeTool()datetimeParse, format, manipulate dates (UTC + offsets)
createCompressionTool()compressionGzip compress/decompress data
createSigningTool()signingEd25519 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

FieldTypeDescription
namestringTool name for LLM function calling
descriptionstringWhat the tool does (shown to the LLM)
wasmModulestringPath or URL to the .wasm file
wasmFunctionstringExported function to call (default: run)
parametersZodTypeZod schema for input validation
categoryToolCategoryOptional category for grouping
tagsstring[]Optional tags for discovery
timeoutnumberExecution timeout in ms (default: 5000)
wasibooleanEnable WASI for filesystem/env access
memoryPagesnumberWASM 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:

  1. Loading: The WasmLoader reads the .wasm binary from disk or URL and instantiates it via the Extism SDK
  2. Execution: Input parameters are JSON-serialized and passed to the exported WASM function via plugin.call(functionName, input)
  3. Output: The WASM function returns a byte buffer, which is parsed as JSON (or returned as raw text if parsing fails)
  4. 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 eval or 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

AspectWASM (Extism)Docker
Cold start< 5 ms500 ms - 2 s
Memory overhead~2 MB per instance~50 MB per container
IsolationLinear memoryFull OS-level
Network accessNone (unless WASI)Configurable
File systemNone (unless WASI)Mountable volumes
Best forPure computationI/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.

On this page