Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions examples/wasm-code-sandboxing-go/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# WASM-based Code Sandboxing in Go with Monty-Go

This example demonstrates WASM-based Python code sandboxing using [Monty-Go](https://github.com/fugue-labs/monty-go), a Go library that runs Python code in a WebAssembly sandbox using [wazero](https://github.com/tetratelabs/wazero) (pure Go, zero CGO).

## Container vs WASM Sandboxing

E2B and Monty-Go represent two complementary approaches to code sandboxing:

| | E2B (Container-based) | Monty-Go (WASM-based) |
|---|---|---|
| **Environment** | Full OS with filesystem, network, packages | Minimal Python interpreter in WASM |
| **Startup time** | ~150ms (cloud sandbox) | Sub-millisecond (in-process) |
| **Capabilities** | Install packages, run shell commands, access network | Pure computation, external functions via Go callbacks |
| **Isolation** | VM-level isolation in the cloud | WASM memory sandbox, in-process |
| **Best for** | Complex multi-step code execution, data analysis, system tasks | Lightweight expression eval, formula execution, tight Go integration |

### When to Use Each

**Use E2B when you need:**
- Full Python package ecosystem (pandas, numpy, matplotlib)
- File system access, network requests, or shell commands
- Long-running or resource-intensive computations
- Complete OS-level isolation

**Use Monty-Go when you need:**
- Sub-millisecond startup for high-throughput evaluation
- Embedded Python execution inside a Go service
- Deterministic, resource-limited execution with strict memory/time caps
- Zero external dependencies (no containers, no cloud, no CGO)

## Setup

### 1. Install Go

Ensure you have [Go 1.22+](https://go.dev/dl/) installed.

### 2. Clone and run

```bash
cd examples/wasm-code-sandboxing-go
go run main.go
```

No API keys, containers, or external services required.

## How it works

Monty-Go embeds a Python interpreter compiled to WebAssembly. Each `Execute` call creates an isolated WASM instance with its own memory, so multiple executions cannot interfere with each other. Go functions can be exposed to Python code via callbacks, enabling sandboxed Python to interact with your Go backend.

## Next steps

- Combine both approaches: use Monty-Go for fast inline evaluations and E2B for heavy-lift tasks
- See the [Monty-Go documentation](https://github.com/fugue-labs/monty-go) for the full API reference
- See [E2B docs](https://e2b.dev/docs) for cloud sandbox capabilities
10 changes: 10 additions & 0 deletions examples/wasm-code-sandboxing-go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module github.com/e2b-dev/e2b-cookbook/examples/wasm-code-sandboxing-go

go 1.25.1

require github.com/fugue-labs/monty-go v0.1.0

require (
github.com/tetratelabs/wazero v1.11.0 // indirect
golang.org/x/sys v0.38.0 // indirect
)
6 changes: 6 additions & 0 deletions examples/wasm-code-sandboxing-go/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
github.com/fugue-labs/monty-go v0.1.0 h1:4N0ztIWWNju2bkGCLg68RKZa/AdsW6pENO1f5WnMBAM=
github.com/fugue-labs/monty-go v0.1.0/go.mod h1:/IEDxFEvHB+vxZCdJTF3pMv6HwSd5LYLthYIH4uI7gg=
github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA=
github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
83 changes: 83 additions & 0 deletions examples/wasm-code-sandboxing-go/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package main

import (
"context"
"fmt"
"log"
"time"

montygo "github.com/fugue-labs/monty-go"
)

func main() {
// Create a WASM-sandboxed Python runner.
// The WASM module is compiled once and reused across Execute calls.
runner, err := montygo.New()
if err != nil {
log.Fatal(err)
}
defer runner.Close()

ctx := context.Background()

// Example 1: Execute Python code with resource limits
result, err := runner.Execute(ctx,
`
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)

result = [fibonacci(i) for i in range(10)]
result
`,
nil, // no inputs
montygo.WithLimits(montygo.Limits{
MaxDuration: 5 * time.Second,
MaxMemoryBytes: 10 * 1024 * 1024, // 10MB
MaxRecursionDepth: 100,
}),
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Fibonacci sequence: %v\n", result)

// Example 2: Pass inputs from Go into Python
result2, err := runner.Execute(ctx,
`
total = sum(values)
f"Processed {len(values)} items, total = {total}"
`,
map[string]any{
"values": []int{10, 20, 30, 40, 50},
},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Result: %v\n", result2)

// Example 3: Expose Go functions to Python via external function callbacks
result3, err := runner.Execute(ctx,
`
data = fetch_data("users")
len(data)
`,
nil,
montygo.WithExternalFunc(
func(ctx context.Context, call *montygo.FunctionCall) (any, error) {
// In production, this would call your Go backend, database, or API
return []map[string]any{
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25},
}, nil
},
montygo.Func("fetch_data", "endpoint"),
),
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("User count: %v\n", result3)
}