This example demonstrates how to use Rust tools compiled to WebAssembly with AgentMesh, both directly and integrated with a ReAct agent.
OverviewThis example demonstrates how to use Rust tools compiled to WebAssembly with AgentMesh's sandboxing.
The calculator tool is a Rust library that performs arithmetic calculations. When compiled to WASM and executed through AgentMesh's WASMTool, it runs in a completely isolated sandbox with:
-
β No network access - Cannot make HTTP requests## OverviewThis example demonstrates how to use Rust tools compiled to WebAssembly with AgentMesh's sandboxing.This example demonstrates how to use Python tools compiled to WebAssembly with AgentMesh's sandboxing.
-
β No filesystem access - Cannot read or write files
-
β No environment access - Cannot read environment variables
-
β Memory limits - Restricted to 200MB by default
-
β Timeout enforcement - Kills execution after 10 secondsThe calculator tool is a Rust library that performs arithmetic calculations. When compiled to WASM and executed through AgentMesh's
WASMTool, it runs in a completely isolated sandbox with: -
β Memory safety - Rust's safety guarantees carry through to WASM
-
β Tiny binaries - Only 128KB (vs 800KB+ for Go)
-
src/lib.rs- Rust calculator implementation- β No filesystem access - Cannot read or write files -
Cargo.toml- Rust configuration with WASM optimization -
main.go- Example showing direct tool calls and ReAct agent integration- β No environment access - Cannot read environment variables -
build.sh- Script to build Rust to WASM using Docker -
calculator.wasm- Compiled WASM module (generated after build)- β Memory limits - Restricted to 200MB by default
Why Rust?- β
Timeout enforcement - Kills execution after 10 secondsThe calculator tool is a Rust library that performs arithmetic calculations. When compiled to WASM and executed through AgentMesh's WASMTool, it runs in a completely isolated sandbox with:The calculator tool is a simple Python script that performs arithmetic calculations. When compiled to WASM and executed through AgentMesh's WASMTool, it runs in a completely isolated sandbox with:
Rust is the gold standard for WebAssembly:- β Memory safety - Rust's safety guarantees carry through to WASM
-
First-class WASM support - Built into the language and toolchain- β Tiny binaries - Only 128KB (vs 800KB+ for Go)
-
Tiny binaries - 128KB optimized (6.8x smaller than TinyGo)
-
Memory safety - Zero-cost abstractions with guaranteed safety
-
Fast compilation - Aggressive optimization with LTO
-
Production ready - Used by Cloudflare Workers, Fastly Compute@Edge, etc.## Files- β No network access - Cannot make HTTP requests- β No network access - Cannot make HTTP requests
-
Full WASI support - Via
wasm32-unknown-unknowntarget
src/lib.rs- Rust calculator implementation- β No filesystem access - Cannot read or write files - β No filesystem access - Cannot read or write files
No installation required! The build script uses Docker with the official Rust image.
Cargo.toml- Rust configuration with WASM optimization
For the ReAct agent testing, you'll need an OpenAI API key.
main.go- Example showing how to use the WASM tool with AgentMesh- β No environment access - Cannot read environment variables- β No environment access - Cannot read environment variables
build.sh- Script to build Rust to WASM using Docker
calculator.wasm- Compiled WASM module (generated after build)- β Memory limits - Restricted to 200MB by default- β Memory limits - Restricted to 200MB by default
# Simple: Use the build script
./build.sh
## Why Rust?- β
**Timeout enforcement** - Kills execution after 10 seconds- β
**Timeout enforcement** - Kills execution after 10 seconds
# Or manually with Docker:
docker run --rm -v $(pwd):/usr/src/app -w /usr/src/app rust:1.83 \
bash -c "rustup target add wasm32-unknown-unknown && \
cargo build --release --target wasm32-unknown-unknown && \Rust is the gold standard for WebAssembly:- β
**Memory safety** - Rust's safety guarantees carry through to WASM
cp target/wasm32-unknown-unknown/release/calculator.wasm ."
Local Installation- First-class WASM support - Built into the language and toolchain- β Tiny binaries - Only 128KB (vs 800KB+ for Go, 75MB+ for Python)## Files
If you have Rust installed:- Tiny binaries - 128KB optimized (6.8x smaller than TinyGo)
rustup target add wasm32-unknown-unknown
cargo build --release --target wasm32-unknown-unknown- **Fast compilation** - Aggressive optimization with LTO
cp target/wasm32-unknown-unknown/release/calculator.wasm .
```- **Production ready** - Used by Cloudflare Workers, Fastly Compute@Edge, etc.## Files- `calculator.py` - Original Python tool (for reference)
Install Rust: https://rustup.rs/- **Full WASI support** - Via `wasm32-unknown-unknown` target
## Running the Example- `calculator.go` - Go implementation compiled to WASM
The example demonstrates two ways to use the WASM calculator:## Prerequisites
1. **Direct tool calls** - Call the WASM tool directly with JSON input- `src/lib.rs` - Rust calculator implementation- `main.go` - Example showing how to use the WASM tool with AgentMesh
2. **ReAct agent integration** - Use the tool with an AI agent that reasons about when to use it
**No installation required!** The build script uses Docker with the official Rust image.
```bash
# Set your OpenAI API key for agent testing- `Cargo.toml` - Rust configuration with WASM optimization- `build.sh` - Script to build Go to WASM using TinyGo in Docker
export OPENAI_API_KEY=sk-...
## Building the WASM Module
# Run the example
go run main.go- `calculator.py` - Original Python tool (for reference)- `calculator.wasm` - Compiled WASM module (generated after build)
Expected output:
```- main.go - Example showing how to use the WASM tool with AgentMesh
Tool Definition:
{```bash
"type": "function",
"function": {# Simple: Use the build script- build.sh - Script to build Rust to WASM using Docker## Why Go instead of Python?
"name": "calculator",
"description": "Performs arithmetic calculations",./build.sh
"parameters": { ... }
}- calculator.wasm - Compiled WASM module (generated after build)
}
=== Direct Tool Testing ===
Input: {"expression": "2 + 2"}docker run --rm -v $(pwd):/usr/src/app -w /usr/src/app rust:1.83 \While Python-to-WASM compilers exist (like py2wasm), they're experimental and have limitations. TinyGo provides a production-ready solution for compiling to WASM with:
Output: {"result": 4}
bash -c "rustup target add wasm32-unknown-unknown && \
Input: {"expression": "10 * 5 + 3"}
Output: {"result": 53} cargo build --release --target wasm32-unknown-unknown && ## Why Rust?- Small binary sizes (typically <100KB)
=== ReAct Agent Testing === cp target/wasm32-unknown-unknown/release/calculator.wasm ."
Question: What is 15 multiplied by 8?
Answer: The result of 15 multiplied by 8 is 120.```- Fast compilation
Question: Calculate 100 divided by 4 plus 10
Answer: The result is 35.
Question: What's the result of (5 + 3) * 2?
Answer: The result is 16.
If you have Rust installed:- Easy integration with AgentMesh
## How It Works
### 1. Rust Implementation (src/lib.rs)
```bash- **First-class WASM support** - Built into the language and toolchain
The calculator exports functions that the Go host can call:
rustup target add wasm32-unknown-unknown
```rust
#[no_mangle]cargo build --release --target wasm32-unknown-unknown- **Tiny binaries** - 128KB optimized (6.8x smaller than TinyGo, 600x smaller than Python)The calculator logic from Python has been ported to Go for reliability.
pub extern "C" fn allocate(size: usize) -> *mut u8 {
// Allocate memory for inputcp target/wasm32-unknown-unknown/release/calculator.wasm .
}
```- **Memory safety** - Zero-cost abstractions with guaranteed safety
#[no_mangle]
pub extern "C" fn execute(input_ptr: *const u8, input_len: usize) {
// Parse JSON, evaluate expression, store result
}Install Rust: https://rustup.rs/- **Fast compilation** - Aggressive optimization with LTO## Prerequisites
#[no_mangle]
pub extern "C" fn get_result_ptr() -> *const u8 {
// Return pointer to result## Running the Example- **Production ready** - Used by Cloudflare Workers, Fastly Compute@Edge, etc.
}
#[no_mangle]
pub extern "C" fn get_result_len() -> usize {```bash- **Full WASI support** - Via `wasm32-unknown-unknown` target**No installation required!** Uses Docker with TinyGo to build WASM.
// Return length of result
}go run main.go
The calculator:
1. Reads JSON input from WASM memory
2. Parses arithmetic expressions using a recursive descent parser
3. Evaluates expressions with support for +, -, *, /, and parenthesesExpected output:## Prerequisites## Building the WASM Module
4. Returns JSON output via global state
Tool Definition:
The Cargo.toml is optimized for small WASM binaries:
{
[lib] "type": "function",**No installation required!** The build script uses Docker with the official Rust image.### Using Docker (Recommended)
crate-type = ["cdylib"] # Dynamic library for WASM
"function": {
[profile.release]
opt-level = "z" # Optimize for size "name": "calculator",
lto = true # Link-time optimization
strip = true # Strip debug symbols "description": "Performs arithmetic calculations",
panic = "abort" # Smaller panic handler
codegen-units = 1 # Better optimization "parameters": { ... }## Building the WASM Module```bash
}
These settings reduce the binary from ~400KB to ~128KB.
}# Simple: Use the build script
The example shows two usage patterns:
Input: {"expression": "2 + 2"}### Using Docker (Recommended)./build.sh
Direct tool calls:
tool, err := wasm.NewWASMTool(
ctx,
"calculator",
"Performs arithmetic calculations",Input: {"expression": "10 * 5 + 3"}
wasmBytes,
wasm.WithPolicy(wasm.ComputeOnlyPolicy()),Output: {"result": 53}```bash# Or manually with Docker:
wasm.WithSchema(schema),
)...
result, err := tool.Call(ctx, `{"expression": "2 + 2"}`)```# Simple: Use the build scriptdocker run --rm -v $(pwd):/src -w /src tinygo/tinygo:0.33.0 \
ReAct agent integration:
reactAgent, err := agent.NewReAct(
openai.NewModel(),
agent.WithTools(tool),
)### 1. Rust Implementation (src/lib.rs)```
system := message.NewSystemMessageFromText(
"You are a helpful math assistant. Use the calculator tool.",
)The calculator exports functions that the Go host can call:# Or manually with Docker:
human := message.NewHumanMessageFromText("What is 15 multiplied by 8?")
result, err := graph.Last(reactAgent.Run(ctx, []message.Message{system, human}))
``````rustdocker run --rm -v $(pwd):/usr/src/app -w /usr/src/app rust:1.83 \### Local Installation
The agent will:#[no_mangle]
1. Analyze the user's question
2. Decide to use the calculator toolpub extern "C" fn allocate(size: usize) -> *mut u8 { bash -c "rustup target add wasm32-unknown-unknown && \
3. Call the WASM tool with the appropriate expression
4. Generate a natural language response with the result // Allocate memory for input
## Security Features} cargo build --release --target wasm32-unknown-unknown && \If you have TinyGo installed locally:
The WASM sandbox provides kernel-level isolation:
1. **Memory Isolation** - WASM has its own linear memory, isolated from the host#[no_mangle] cp target/wasm32-unknown-unknown/release/calculator.wasm ."
2. **No System Calls** - Cannot make syscalls unless explicitly granted
3. **Deterministic Execution** - Same input always produces same outputpub extern "C" fn execute(input_ptr: *const u8, input_len: usize) {
4. **Resource Limits** - Memory and timeout enforced by the runtime
5. **Cannot Be Bypassed** - Enforced by the Wazero runtime, not user-space code // Parse JSON, evaluate expression, store result``````bash
The example uses `ComputeOnlyPolicy()`:}
- β No filesystem access
- β No network access tinygo build -o calculator.wasm -target=wasi calculator.go
- β No stdin/stdout/stderr
- β
Deterministic mode enabled#[no_mangle]
- β
200MB memory limit
- β
10 second timeoutpub extern "C" fn get_result_ptr() -> *const u8 {### Local Installation```
## Architecture // Return pointer to result
```}
βββββββββββββββββββββββββββββββββββββββββββ
β AgentMesh (Go) β
β β
β βββββββββββββββββββββββββββββββββ β#[no_mangle]If you have Rust installed:This creates a compact `calculator.wasm` file (typically ~50KB) that can be loaded by the AgentMesh WASM tool.
β β ReAct Agent (Optional) β β
β β βββββββββββββββββββββββββ β βpub extern "C" fn get_result_len() -> usize {
β β β WASMTool β β β
β β β βββββββββββββββββββ β β β // Return length of result
β β β β Wazero Runtime β β β β
β β β β β β β β}
β β β β ββββββββββββ β β β β
β β β β β WASM β β β β β``````bash## Quick Start
β β β β β Module β β β β β
β β β β β (Rust) β β β β β
β β β β ββββββββββββ β β β β
β β β βββββββββββββββββββ β β βThe calculator:rustup target add wasm32-unknown-unknown
β β βββββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββ β1. Reads JSON input from WASM memory
βββββββββββββββββββββββββββββββββββββββββββ
```2. Parses arithmetic expressions using a recursive descent parsercargo build --release --target wasm32-unknown-unknown```bash
## Troubleshooting3. Evaluates expressions with support for +, -, *, /, and parentheses
### Build fails with "cargo: command not found"4. Returns JSON output via global statecp target/wasm32-unknown-unknown/release/calculator.wasm .# 1. Build the WASM module using Docker
Use the Docker method (recommended), or install Rust from https://rustup.rs/
### Docker not running
Make sure Docker is installed and running:### 2. Cargo Configuration```./build.sh
```bash
docker info
The Cargo.toml is optimized for small WASM binaries:
Check that:
-
You built with
--target wasm32-unknown-unknown -
The
[lib] crate-type = ["cdylib"]is set in Cargo.toml```tomlInstall Rust: https://rustup.rs/# 2. Run the example -
Functions are marked with
#[no_mangle]andextern "C" -
Global state is properly managed (see
RESULTvariable)[lib]
Make sure you have set the OPENAI_API_KEY environment variable:
export OPENAI_API_KEY=sk-...
```[profile.release]## Running the Example```
### Warning: "creating a shared reference to mutable static"opt-level = "z" # Optimize for size
This is expected and safe in our single-threaded WASM context. The warning can be suppressed by using `&raw const` in future Rust versions.
lto = true # Link-time optimization
## Extending the Example
strip = true # Strip debug symbols
To create your own Rust WASM tools:
panic = "abort" # Smaller panic handler```bashExpected output:
1. **Create a new Rust library:**
```bashcodegen-units = 1 # Better optimization
cargo new --lib my_tool
``````go run main.go```
2. **Configure Cargo.toml:**
```toml
[lib]These settings reduce the binary from ~400KB to ~128KB.```Tool Definition:
crate-type = ["cdylib"]
[dependencies]
serde = { version = "1.0", features = ["derive"] }### 3. Go Integration (main.go){
serde_json = "1.0"
[profile.release]
opt-level = "z"The Go code:Expected output: "type": "function",
lto = true
strip = true1. Loads the WASM binary
panic = "abort"
codegen-units = 12. Creates a `WASMTool` with schema and security policy``` "function": {
-
Calls the tool like any other AgentMesh tool
-
Implement required exports in src/lib.rs:
```rust4. The
WASMToolhandles all memory management and sandboxingTool Definition: "name": "calculator",#[no_mangle]
pub extern "C" fn allocate(size: usize) -> *mut u8 { ... }
#[no_mangle]## Security Features{ "description": "Performs arithmetic calculations on mathematical expressions",
pub extern "C" fn execute(input_ptr: *const u8, input_len: usize) { ... }
#[no_mangle]
pub extern "C" fn get_result_ptr() -> *const u8 { ... }The WASM sandbox provides kernel-level isolation: "type": "function", "parameters": {
#[no_mangle]
pub extern "C" fn get_result_len() -> usize { ... }
-
**Build to WASM:**2. No System Calls - Cannot make syscalls unless explicitly granted
rustup target add wasm32-unknown-unknown3. **Deterministic Execution** - Same input always produces same output "name": "calculator", "properties": { cargo build --release --target wasm32-unknown-unknown ```4. **Resource Limits** - Memory and timeout enforced by the runtime
-
**Use with AgentMesh:**5. Cannot Be Bypassed - Enforced by the Wazero runtime, not user-space code "description": "Performs arithmetic calculations", "expression": {
// Direct usage tool, err := wasm.NewWASMTool( wasmBytes,The example uses `ComputeOnlyPolicy()`: "parameters": { ... } "type": "string", schema, wasm.ComputeOnlyPolicy(),- β No filesystem access ) - β No network access } "description": "A mathematical expression to evaluate (e.g., '2 + 2', '10 * 5 - 3')" // Or with a ReAct agent agent, err := agent.NewReAct(- β No stdin/stdout/stderr openai.NewModel(), agent.WithTools(tool),- β Deterministic mode enabled} } ) ```- β 200MB memory limit
While this example uses Rust, you can compile many languages to WASM:
| Language | Binary Size | Maturity | Recommendation |## ArchitectureInput: {"expression": "2 + 2"} "required": ["expression"]
|----------|-------------|----------|----------------|
| Rust | ~100-200KB | βββββ | Best choice |
| Go (TinyGo) | ~800KB | ββββ | Good alternative |
| C/C++ | ~50-150KB | βββββ | Great for existing code |```Output: {"result": 4} }
| AssemblyScript | ~50-100KB | βββ | TypeScript-like syntax |
βββββββββββββββββββββββββββββββββββββββββββ
β AgentMesh (Go) β }
Benchmark on Apple M1:
β β
-
Binary size: 128KB (optimized)
-
Load time: ~2-5ms (first time), <1ms (cached)β βββββββββββββββββββββββββββββββββ βInput: {"expression": "10 * 5 + 3"}}
-
Execution time: <1ms for simple expressions
-
Memory usage: <1MB for typical operationsβ β WASMTool β β
-
Agent overhead: +100-500ms for LLM reasoning
β β βββββββββββββββββββββββββββ β βOutput: {"result": 53}
β β β Wazero Runtime β β β
-
wasm32-unknown-unknown targetβ β β β β β...Input: {"expression": "2 + 2"}
-
AgentMesh WASM Designβ β β ββββββββββββββββββββ β β β
β β β β WASM Module β β β β```Output: {
β β β β (Rust code) β β β β
β β β β β β β β "result": 4
β β β β - Isolated mem β β β β
β β β β - No syscalls β β β β## How It Works}
β β β β - Enforced caps β β β β
β β β ββββββββββββββββββββ β β β
β β β β β β
β β βββββββββββββββββββββββββββ β β### 1. Rust Implementation (src/lib.rs)Input: {"expression": "10 * 5 + 3"}
β βββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββOutput: {
The calculator exports functions that the Go host can call: "result": 53
## Troubleshooting
}
### Build fails with "cargo: command not found"
Use the Docker method (recommended), or install Rust from https://rustup.rs/```rust```
### Docker not running#[no_mangle]
Make sure Docker is installed and running:
```bashpub extern "C" fn allocate(size: usize) -> *mut u8 {## How It Works
docker info
``` // Allocate memory for input
### WASM execution errors}1. **Python Source** β The `calculator.py` script reads JSON from stdin, performs calculation, writes JSON to stdout
Check that:
1. You built with `--target wasm32-unknown-unknown`2. **Compilation** β Pyodide compiles Python to WebAssembly bytecode
2. The `[lib] crate-type = ["cdylib"]` is set in Cargo.toml
3. Functions are marked with `#[no_mangle]` and `extern "C"`#[no_mangle]3. **Loading** β `wasm.NewWASMTool()` loads and validates the WASM module
4. Global state is properly managed (see `RESULT` variable)
pub extern "C" fn execute(input_ptr: *const u8, input_len: usize) {4. **Schema** β We provide the tool schema externally via `WithSchema()`
### Warning: "creating a shared reference to mutable static"
This is expected and safe in our single-threaded WASM context. The warning can be suppressed by using `&raw const` in future Rust versions. // Parse JSON, evaluate expression, store result5. **Execution** β `tool.Call()` instantiates the module, passes JSON input, reads JSON output
## Extending the Example}6. **Isolation** β Wazero enforces the sandbox policy at the kernel level
To create your own Rust WASM tools:
1. **Create a new Rust library:**#[no_mangle]## Security
```bash
cargo new --lib my_toolpub extern "C" fn get_result_ptr() -> *const u8 {
// Return pointer to resultThe WASM tool runs with `ComputeOnlyPolicy()`:
-
Configure Cargo.toml:
[lib] crate-type = ["cdylib"]```go [dependencies]#[no_mangle]policy := wasm.ComputeOnlyPolicy() serde = { version = "1.0", features = ["derive"] } serde_json = "1.0"pub extern "C" fn get_result_len() -> usize {// - Timeout: 10 seconds [profile.release] // Return length of result// - Max Memory: 200MB opt-level = "z" lto = true}// - No network strip = true panic = "abort"```// - No filesystem codegen-units = 1 ```// - No environment variables -
**Implement required exports in src/lib.rs:**The calculator:// - Stdout/stderr allowed for debugging
#[no_mangle]1. Reads JSON input from WASM memory``` pub extern "C" fn allocate(size: usize) -> *mut u8 { ... } 2. Parses arithmetic expressions using a recursive descent parser #[no_mangle] pub extern "C" fn execute(input_ptr: *const u8, input_len: usize) { ... }3. Evaluates expressions with support for +, -, *, /, and parenthesesThis ensures that even if the Python code is malicious, it cannot: #[no_mangle]4. Returns JSON output via global state- Exfiltrate data over the network pub extern "C" fn get_result_ptr() -> *const u8 { ... } - Read sensitive files #[no_mangle] pub extern "C" fn get_result_len() -> usize { ... }### 2. Cargo Configuration- Execute arbitrary system commands
- Consume excessive resources
-
Build to WASM:
```bashThe
Cargo.tomlis optimized for small WASM binaries:rustup target add wasm32-unknown-unknown
cargo build --release --target wasm32-unknown-unknown## Customizing the Policy
5. **Use with AgentMesh:**
```go[lib]```go
tool, err := wasm.NewWASMTool(
wasmBytes,crate-type = ["cdylib"] # Dynamic library for WASM// Create a custom policy
schema,
wasm.ComputeOnlyPolicy(),policy := wasm.DefaultSandboxPolicy()
)
```[profile.release]policy.Timeout = 30 * time.Second
## Other Languagesopt-level = "z" # Optimize for sizepolicy.MaxMemory = 500 * 1024 * 1024 // 500MB
While this example uses Rust, you can compile many languages to WASM:lto = true # Link-time optimizationpolicy.AllowStdout = false // Disable output
| Language | Binary Size | Maturity | Recommendation |strip = true # Strip debug symbols
|----------|-------------|----------|----------------|
| **Rust** | ~100-200KB | βββββ | **Best choice** |panic = "abort" # Smaller panic handlertool, err := wasm.NewWASMTool(ctx, "calculator", "...", wasmBytes,
| Go (TinyGo) | ~800KB | ββββ | Good alternative |
| C/C++ | ~50-150KB | βββββ | Great for existing code |codegen-units = 1 # Better optimization wasm.WithPolicy(policy),
| AssemblyScript | ~50-100KB | βββ | TypeScript-like syntax |
```)
## Performance
Benchmark on Apple M1:
These settings reduce the binary from ~400KB to ~128KB.
-
Binary size: 128KB (optimized)
-
Load time: ~2-5ms (first time), <1ms (cached)## Creating Your Own Python WASM Tools
-
Execution time: <1ms for simple expressions
-
Memory usage: <1MB for typical operations### 3. Go Integration (main.go)
-
Rust and WebAssembly BookThe Go code: - Reads JSON from
sys.stdin.read() -
Wazero Runtime1. Loads the WASM binary - Processes the input
-
Creates a
WASMToolwith schema and security policy - Writes JSON result tostdout -
Calls the tool like any other AgentMesh tool
-
The
WASMToolhandles all memory management and sandboxing2. Compile to WASM using TinyGo:
docker run --rm -v $(pwd):/src -w /src tinygo/tinygo:0.33.0 \
The WASM sandbox provides kernel-level isolation: tinygo build -o your_tool.wasm -target=wasi your_tool.go
-
Memory Isolation - WASM has its own linear memory, isolated from the host # Or locally if TinyGo is installed
-
No System Calls - Cannot make syscalls unless explicitly granted tinygo build -o your_tool.wasm -target=wasi your_tool.go
-
Deterministic Execution - Same input always produces same output ```
-
Resource Limits - Memory and timeout enforced by the runtime
-
Cannot Be Bypassed - Enforced by the Wazero runtime, not user-space code3. Load in Go:
The example uses ComputeOnlyPolicy(): wasmBytes, _ := os.ReadFile("your_tool.wasm")
-
β No filesystem access tool, _ := wasm.NewWASMTool(ctx, "tool_name", "description", wasmBytes,
-
β No network access wasm.WithSchema(schema),
-
β No stdin/stdout/stderr wasm.WithPolicy(wasm.ComputeOnlyPolicy()),
-
β Deterministic mode enabled )
-
β 200MB memory limit ```
-
β 10 second timeout
- Use with LLM agents:
// The tool implements the tool.Tool interface
βββββββββββββββββββββββββββββββββββββββββββ agent := agent.NewReAct(model, []tool.Tool{tool})
β AgentMesh (Go) β ```
β β
β βββββββββββββββββββββββββββββββββ β## Troubleshooting
β β WASMTool β β
β β βββββββββββββββββββββββββββ β β**WASM module fails to load:**
β β β Wazero Runtime β β β- Ensure the WASM file is compiled with Pyodide or compatible runtime
β β β β β β- Check that the module exports the required functions
β β β ββββββββββββββββββββ β β β
β β β β WASM Module β β β β**Execution timeout:**
β β β β (Rust code) β β β β- Increase the timeout in the policy
β β β β β β β β- Optimize your Python code
β β β β - Isolated mem β β β β
β β β β - No syscalls β β β β**Memory errors:**
β β β β - Enforced caps β β β β- Increase MaxMemory in the policy
β β β ββββββββββββββββββββ β β β- Reduce memory usage in your Python script
β β β β β β
β β βββββββββββββββββββββββββββ β β## Next Steps
β βββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββ- Explore other sandbox policies: `NetworkOnlyPolicy()`, `FileProcessingPolicy()`
```- Create more complex tools (API clients, data processors, etc.)
- Integrate with AgentMesh agents for autonomous task execution
## Troubleshooting
### Build fails with "cargo: command not found"
Use the Docker method (recommended), or install Rust from https://rustup.rs/
### Docker not running
Make sure Docker is installed and running:
```bash
docker info
Check that:
- You built with
--target wasm32-unknown-unknown - The
[lib] crate-type = ["cdylib"]is set in Cargo.toml - Functions are marked with
#[no_mangle]andextern "C" - Global state is properly managed (see
RESULTvariable)
This is expected and safe in our single-threaded WASM context. The warning can be suppressed by using &raw const in future Rust versions.
To create your own Rust WASM tools:
-
Create a new Rust library:
cargo new --lib my_tool
-
Configure Cargo.toml:
[lib] crate-type = ["cdylib"] [dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" [profile.release] opt-level = "z" lto = true strip = true panic = "abort" codegen-units = 1
-
Implement required exports in src/lib.rs:
#[no_mangle] pub extern "C" fn allocate(size: usize) -> *mut u8 { ... } #[no_mangle] pub extern "C" fn execute(input_ptr: *const u8, input_len: usize) { ... } #[no_mangle] pub extern "C" fn get_result_ptr() -> *const u8 { ... } #[no_mangle] pub extern "C" fn get_result_len() -> usize { ... }
-
Build to WASM:
rustup target add wasm32-unknown-unknown cargo build --release --target wasm32-unknown-unknown
-
Use with AgentMesh:
tool, err := wasm.NewWASMTool( wasmBytes, schema, wasm.ComputeOnlyPolicy(), )
While this example uses Rust, you can compile many languages to WASM:
| Language | Binary Size | Maturity | Recommendation |
|---|---|---|---|
| Rust | ~100-200KB | βββββ | Best choice |
| Go (TinyGo) | ~800KB | ββββ | Good alternative |
| C/C++ | ~50-150KB | βββββ | Great for existing code |
| AssemblyScript | ~50-100KB | βββ | TypeScript-like syntax |
| Python | 75MB+ | ββ | Experimental, large binaries |
Benchmark on Apple M1:
- Binary size: 128KB (optimized)
- Load time: ~2-5ms (first time), <1ms (cached)
- Execution time: <1ms for simple expressions
- Memory usage: <1MB for typical operations