Community Perk$300 in Akamai Cloud credits for buildersClaim your credits
ai

Sandboxed Agentic Tools with Rust and Spin

The AI ecosystem is moving fast; whether you are using Claude, Cursor, or building an internal agentic workflow, models don’t just generate text anymore—they call tools to inspect data, execute calculations, query APIs, and take real-world actions. With Model Context Protocol (MCP), we have a standardized, open specification for how LLMs can discover and invoke tools.

But as soon as you let an LLM invoke code, you run into the elephant in the room: security and runtime isolation. What happens when an adversarial prompt injection tricks an agent into reading local system files, executing destructive commands, or exfiltrating environment variables to an external server?

In this post, we will explore why Rust and WebAssembly (Wasm) powered by Spin are the ideal architecture for running agent tools—and how you can take them from your local machine to Akamai Functions.


The Agent Tool Dilemma: Containers vs. Native Execution

When giving an agent access to tools, teams generally choose between two extremes:

Running tools natively on the host machine: Fast, but terrifying from a security perspective. A prompt injection attack or an errant model hallucination has full access to the host file system, environment variables, and local network.

Spinning up Docker containers or microVMs: Secure, but operationally heavy. Instantiating a container introduces seconds of cold-start latency, consumes hundreds of megabytes of RAM, and creates orchestration headaches when agents need to fire bursts of ephemeral tool calls.

We need a third path: microsecond instantiation, near-native execution speed, and a deny-by-default security boundary. This is exactly what the WebAssembly Component Model and Spin provide.


Why Spin and Rust are the Sweet Spot for Agent Tools

WebAssembly was built from day one as a secure, sandboxed bytecode format. When coupled with Spin 4.0 and WASI Preview 2 (wasm32-wasip2), you get distinct architectural superpowers:

  1. Zero Ambient Authority

Unlike traditional server processes that inherit full access to the host’s network and disk, Spin components operate under a strict capability-based security model. If your spin.toml doesn’t explicitly declare allowed_outbound_hosts, your Wasm component physically cannot touch the network.

Even if an attacker gains arbitrary code execution inside your tool via a malicious prompt, they are trapped in a sterile sandbox with nowhere to go.

  1. Sub-Millisecond Cold Starts

Agents invoke tools sequentially or in parallel bursts. Spin components instantiate in microseconds. There is no daemon to keep warm, no container runtime to initialize, and zero idle cost.

  1. Deterministic Performance in Rust

Large language models are probabilistic by nature and notoriously unreliable at deterministic compute tasks: cryptographic hashing, precision arithmetic, or high-throughput regex filtering. Rust gives you memory safety, zero-cost abstractions, and blazing-fast execution for the exact workloads LLMs struggle with.


The Sample Application: sandboxed-agentic-tools

To demonstrate this pattern, I built sandboxed-agentic-tools, a simple MCP-compliant HTTP application built with Spin and Rust.

Open sourceReady to RunGrab the full sample code and run it yourself!akamai-developers/sandboxed-agentic-tools

Reusing the Protocol: mcp-types

Instead of hand-rolling bespoke JSON-RPC request/response structs, the project leverages the mcp-types crate. Because mcp-types is generated directly from the official MCP JSON schema specification using typify, it provides type-safe protocol structs (Tool, ListToolsResult, CallToolResult, InitializeResult) while remaining 100% pure data contracts that compile to wasm32-wasip2 with no OS socket dependencies at all.

The Tools

The application exposes two security-focused tools that an AI agent can invoke:

  1. calculate_hash: Computes deterministic SHA-256 checksums of input data (something LLMs cannot reliably do).
  2. redact_secrets: High-throughput regex masking that scrubs API keys, bearer tokens, passwords, and email addresses before context is logged or forwarded.

Here is the core tool execution dispatcher in src/lib.rs:

#[derive(Deserialize)]
struct HashArgs { data: String }

#[derive(Deserialize)]
struct RedactArgs { text: String }

pub fn execute_tool(name: &str, raw_args: &str) -> Result<String, String> {
    match name {
        "calculate_hash" => {
            let args: HashArgs = serde_json::from_str(raw_args)
                .map_err(|e| format!("Invalid arguments for calculate_hash: {e}"))?;
            let mut hasher = Sha256::new();
            hasher.update(args.data.as_bytes());
            let digest = format!("{:x}", hasher.finalize());
            Ok(json!({ "sha256": digest }).to_string())
        }
        "redact_secrets" => {
            let args: RedactArgs = serde_json::from_str(raw_args)
                .map_err(|e| format!("Invalid arguments for redact_secrets: {e}"))?;
            let key_pattern = r"(?i)(api[_-]?key|token|secret|password)\s*[:=]\s*\S+";
            let key_re = Regex::new(key_pattern).map_err(|e| e.to_string())?;
            let email_re = Regex::new(r"[\w.+-]+@[\w-]+\.[\w.-]+").map_err(|e| e.to_string())?;
            let clean = key_re.replace_all(&args.text, "$1=[REDACTED]");
            let clean = email_re.replace_all(&clean, "[REDACTED_EMAIL]");
            Ok(json!({ "sanitized": clean }).to_string())
        }
        unknown => Err(format!("Unknown tool: '{unknown}'")),
    }
}

The Sandbox Guarantee in spin.toml

The real security story lives in spin.toml:

[[trigger.http]]
route = "/..."
component = "sandboxed-agentic-tools"

[component.sandboxed-agentic-tools]
source = "target/wasm32-wasip2/release/sandboxed_agentic_tools.wasm"
allowed_outbound_hosts = []

[component.sandboxed-agentic-tools.build]
command = "cargo build --target wasm32-wasip2 --release"
watch = ["src/**/*.rs", "Cargo.toml"]

There are no external outbound hosts permitted, and no other capabilities granted. The WebAssembly runtime strictly enforces this boundary at the capability level, resulting in physically no access to environment variables, file system, host memory, or sockets. Just computation in pure isolation.


Running and Testing Locally

Clone the repo and run spin build + spin up

# Clone the GitHub repo
git clone https://github.com/thorstenhans/sandboxed-agentic-tools --depth=1
cd sandboxed-agentic-tools

# Compile down to wasm32-wasip2
spin build

# Launch the app locally
spin up

Spin spins up the HTTP server at http://127.0.0.1:3000. You can verify the MCP tool discovery endpoint using curl:

curl -X POST http://127.0.0.1:3000 \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list"
  }'

The response returns the strongly-typed schema generated by mcp-types:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "calculate_hash",
        "description": "Calculates the deterministic SHA-256 checksum of the provided text data.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "data": { "type": "string", "description": "The input data to hash." }
          },
          "required": ["data"]
        }
      },
      {
        "name": "redact_secrets",
        "description": "Scans and redacts sensitive API keys, tokens, and email addresses from untrusted text.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "text": { "type": "string", "description": "The input text to sanitize." }
          },
          "required": ["text"]
        }
      }
    ]
  }
}

Let’s ask the sandboxed tool to redact sensitive credentials:

curl -X POST http://127.0.0.1:3000 \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "redact_secrets",
      "arguments": {
        "text": "Alert: Database admin alice@corp.internal leaked api_key=sk-proj-99881122aabb"
      }
    }
  }'

Result:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"sanitized\":\"Alert: Database admin [REDACTED_EMAIL] leaked api_key=[REDACTED]\"}"
      }
    ]
  }
}

Going Serverless: Deploying to Akamai Functions

Running your sandboxed tools locally during development is great. But in production, your AI agents run in the cloud or across distributed edge services. You want your tools hosted in an environment that:

  • Scales instantly to zero when idle (no monthly server bills).
  • Boots in sub-milliseconds without container startup delays.
  • Runs close to your users and LLM endpoints.

This is where Akamai Functions comes in. Akamai Functions provides native serverless execution for Spin applications across Akamai’s globally distributed network.

From inside the sandboxed-agentic-tools directory, deploy the application:

# Deploy sandboxed-agentic-tools
spin aka deploy \
  --build \
  --create-name sandboxed-agentic-tools \\
  --no-confirm

It takes roughly a minute to deploy an application to Akamai Functions. Once all service regions have received your application, the command comes back and points you to the unique endpoint of your application

Uploading sandboxed-agentic-tools version 0.1.0...
Deploying to Akamai Functions...
Application deployed successfully!

Available at: https://{unique-id}.fwf.app

With the tools now being publicly accessible, you can point Claude Desktop, Cursor, or your custom agent framework directly to your Akamai Functions endpoint over HTTPS.

For example, in an MCP-aware client configuration:

{
  "mcpServers": {
    "security-tools": {
      "url": "https://{unique-id}.fwf.app"
    }
  }
}

Whenever your agent decides to hash an artifact or sanitize user input before logging, the request is routed to the closest service region, executes inside the Wasm sandbox in single-digit milliseconds, and returns safely.


As AI agents gain autonomy, security cannot remain an afterthought. Delegating critical tool execution to arbitrary shell scripts or unconstrained native processes is an unacceptable risk in production environments.By combining Spin, WebAssembly and Akamai Functions you get microsecond cold starts, the strict deny-by-default sandbox and global distribution.

Check out the full source code and give it a star on GitHub.

Happy coding!

Open sourceReady to RunGrab the full sample code and run it yourself!akamai-developers/sandboxed-agentic-tools
Thorsten Hans
Thorsten Hans
Sr. Developer Advocate

Thorsten Hans is a Senior Developer Advocate at Akamai, Docker Captain, and Wasm enthusiast. He thrives on pushing the limits of WebAssembly and Edge Computing to help developers build high-performance distributed systems. Thorsten shares his technical deep-dives via his blog and on global stages to shape the cloud's future.