Sandboxing AI

Ethan LewisEthan Lewis
11 min read

Overview

Artificial intelligence (AI) is not just transforming technology—it’s reshaping how the world builds, thinks, and operates. As large language models (LLMs) become more capable and accessible, we’re seeing a profound shift: Developers can now create intelligent, dynamic systems that were previously unimaginable. Barriers are dropping. Innovation is accelerating. The edge of what’s possible is being redrawn daily.

At the heart of this revolution lies software. While AI models can be viewed as the engine, software is the infrastructure enabling them to connect, execute, and deliver value.

As teams race to integrate LLMs into real-world systems, one trend is increasingly clear: building, testing, deploying, and securing AI-driven applications demands a new architecture pattern.

Many of today’s applications weren’t built with AI-native execution in mind. Integrations are often brittle, one-off, and tightly coupled to specific models or runtimes. Furthermore, once AI enters the loop, traditional workflows give way to nondeterministic paths, unpredictable behaviors, and execution contexts that defy conventional security assumptions.

It’s a thrilling time to be a developer. A single prompt can unlock functionality that once took months to build. Rigid APIs dissolve. Interfaces fade. However, with this power comes uncertainty. When AI is part of the execution path, much of the system is no longer deterministic—it’s probabilistic. The black box of inference becomes a black hole of potential outcomes. Even with predictable AI responses, user interaction within your application and its underlying data is drastically changing.

To address this, developers have turned to tool calling and agent frameworks—ways to let LLMs interact with real systems through structured protocols. These efforts are promising, but today’s approaches often sacrifice security, portability, and interoperability for speed. While LLMs are generating more code than ever, few systems are built to execute that code safely, consistently, or at scale.

Today, we’re introducing Hayride, our approach for standardizing AI agent execution using WebAssembly.

At Hayride, we believe the next era of AI development hinges on how we sandbox AI systems. This means rethinking the infrastructure that powers agentic systems and establishing trusted runtimes that are secure, composable, and built for the multimodal future.

This isn’t just about running code. It’s about establishing an execution layer for AI—one that’s open, safe, and built to scale.

In this post, we’ll walk through the limitations of today’s frameworks, examine emerging standards such as model context protocol (MCP), smolagents, and CodeAct, and share how WebAssembly and various WebAssembly proposals unlock a path to portable, secure, and interoperable agent execution.

Let’s dig in!

Protocols/Frameworks

The pace of innovation around AI agents is accelerating. Across the ecosystem, we’re seeing three dominant interaction patterns emerge:

  1. LLMs are directly trained for solving end-to-end tasks

  2. LLMs selecting from a set of tools and passing arguments for execution

  3. LLMs generate code that must be executed in a secure runtime

Despite these advances, one thing remains constant: Language models do not execute anything themselves. Execution still requires a trusted environment—be it a local runtime, server, or secure sandbox.

To bridge the gap between generative reasoning and real-world action, developers have introduced protocols that allow LLMs to invoke structured functions, often referred to as tool calling. These protocols represent a critical layer in AI architecture: the interface between intelligence and execution.

In this section, we’ll explore several influential and emerging open frameworks defining the future of agentic AI, including:

  • Meta’s Llama 3.1+ Tool Calling—prompt-based mechanisms that enable code interpretation and limited tool invocation

  • Anthropic’s Model Context Protocol (MCP)—a structured, JSON-RPC-based interface between models and tools

  • CodeAct—a research-driven extension of ReAct that emphasizes direct code generation and execution

While other agent frameworks like Google’s Agents-to-Agents (A2A) aim to facilitate interagent messaging and coordination, our priority is the execution layer, where LLMs interact with structured tools. In a future post, we’ll unpack how A2A fits within the Hayride runtime.

Meta Llama 3.1+: Code Interpretation and Tool Use

Meta’s latest LLM, Llama 3.3, extends features introduced in Llama 3.1, offering code interpretation and various forms of tool use. While not a formal protocol, Meta uses special prompt tokens to guide behavior such as code execution. For example, setting Environment: ipython in the system prompt enables the model to emit code responses intended for execution in a Jupyter-style environment.

<|begin_of_text|><|start_header_id|>system<|end_header_id|>
Environment: ipython<|eot_id|><|start_header_id|>user<|end_header_id|>

Write code to check if a number is prime...

This causes the model to return code like:

def is_prime(n):

    ...

print(is_prime(7))  # True

However, Meta’s models don’t execute the code themselves—this must be handled by external infrastructure such as llama-stack-apps or iPython runtimes. While convenient, this execution model lacks isolation and security by default, requiring additional sandboxing layers to run arbitrary code safely.

In addition to code interpretation, Llama supports three tool-calling modes:

  1. Built-In Tools (e.g., Brave search, Wolfram Alpha)

  2. JSON-Based Tool Calling

  3. User-Defined Custom Tools via structured prompt instructions

What’s Missing?

Llama’s capabilities are embedded deeply in model weights and token streams, creating a brittle integration surface. There’s no shared protocol or interface for tool execution across runtimes or models. If you switch from Llama to another model, your tool infrastructure often needs to change as well.

Meta’s system is powerful but lacks portability, extensibility, and language-agnostic standards for integrating tools or ensuring secure execution at scale.

Anthropic’s Model Context Protocol (MCP)

Anthropic’s MCP (Model Context Protocol) is an emerging open standard designed to bring structured, contextual, and secure interaction between LLMs and their toolchains.

At its core, MCP is a JSON-RPC 2.0-based protocol for bidirectional communication between:

  • Hosts: Apps running the LLM

  • Clients: Tool connectors

  • Servers: Services that expose tools, resources, and prompts to the model

The protocol formalizes several interaction primitives:

  • Prompts: Customizable templates to guide model output

  • Resources: Structured external data for richer context

  • Tools: Executable functions that the model can call dynamically

Anthropic’s MCP emphasizes authentication, validation, and portability. It supports both local execution via STDIO and remote execution via server-sent events (SSE), with transport layer security (TLS) and access control as recommended practices.

Projects like Docker’s MCP integration and mcp.run show how containers and WebAssembly plugins can be packaged and exposed via MCP-compatible servers. These projects are pushing AI forward in a meaningful way and are fantastic examples of sandboxed environments.

What’s Missing?

MCP excels at interoperability and safety, but often introduces latency and complexity due to its middleware nature. The need to round-trip tool calls over JSON protocols can increase the number of actions required for an agent to solve a task, especially compared to in-process code generation and execution.

This overhead is highlighted in recent work, like Executable Code Actions Elicit Better LLM Agents (CodeAct)

CodeAct: Direct Code Generation and Execution

CodeAct is an extension of the ReAct pattern that allows LLMs to write and execute code inline during reasoning. Instead of describing tools via JSON or expecting the model to reason through text, CodeAct gives the LLM full access to generate, execute, and revise Python code as part of the task-solving loop.

Compared to JSON-based tool calling, CodeAct achieves:

FeatureCodeAct for LLM ActionJSON or Text for LLM Action
Availability of DataA large quantity of code is available for pre-trainingData curation is required for a particular format
Complex OperationNatively supported via control and data flowRequires careful engineering if feasible (e.g., define new tools to mimic if-statement)
Availability of ToolsCan directly use existing software packagesRequires human effort to curate tools from scratch or existing software
Automated FeedbackFeedback mechanism (e.g., traceback) is already implemented as an infrastructure for most programming languagesRequires human effort to provide feedback or reroute feedback from the underlying program

( https://arxiv.org/pdf/2402.01030 - table 1 )

The source code and datasets are available on GitHub.

As shown in CodeAct’s benchmarks, this approach often reduces the number of steps needed to complete a task while improving task success rate.

What’s Missing?

While CodeAct increases performance and flexibility, it introduces significant security risks. Executing arbitrary generated code means trusting both the generation pipeline and its runtime environment.

There are no standardized sandboxing or language-agnostic methods to ensure that this process is secure by default.

Hugging Face Smolagents: Lightweight Code Agents

Smolagents, an open-source library from Hugging Face, implements CodeAct-like behavior in Python. It supports two execution modes:

  • ToolCallingAgent: Traditional structured tool invocation

  • CodeAgent: Direct generation and execution of Python code

Smolagents focuses on:

  • Code consistency between LLM generation and execution

  • Seamless tool registration and usage

  • Sandboxing through platforms like E2B.dev

To define an agent, developers provide:

agent = CodeAgent(
    tools=[DuckDuckGoSearchTool()],
    model=LLMWrapper()
)

The agent can write Python code, use external tools, and solve tasks by chaining logic and execution without predefined templates.

What’s Missing?

Smolagents excel at agile code agent composition, but it is currently Python-only and leaves runtime trust and security concerns to external systems (e.g., E2B or local VMs).

It's a compelling foundation for CodeAct-style agent systems, but not yet portable, secure, or language-independent—all key criteria for running agents at scale across diverse environments.

Purpose-Built for the Future: Why We Built Hayride

As we’ve explored, modern AI agents rely on a growing constellation of tool-calling frameworks—from JSON-based protocols like MCP to dynamic code-generation libraries like smolagents and CodeAct. Each of these systems brings powerful capabilities to language models, enabling them to interact with tools, generate code, and operate across local and remote environments. However, each also introduces difficult tradeoffs around security, portability, and interoperability.

With Hayride, we asked a foundational question:

What if AI agent execution could be secure by design, portable by default, and interoperable across tools, languages, and runtimes—without sacrificing performance or control?

To answer that, we turned to WebAssembly.

Why WebAssembly?

WebAssembly (Wasm) is a fast, safe, and language-agnostic binary format for executing code across platforms. Originally designed for web browsers, it’s now evolving rapidly into a general-purpose runtime for secure sandboxed execution—ideal for the demands of modern AI workloads.

What makes Wasm uniquely suited for agentic systems?

  • Secure by default: Sandboxed execution prevents privilege escalation and system-level access.

  • Portable: Wasm modules run consistently across environments—from browsers to edge to cloud.

  • Composable: Through the WebAssembly Component Model, modules written in different languages can interoperate seamlessly.

  • Language-agnostic: Wasm supports Rust, TinyGo, Python, C/C++, JavaScript, and more.

The power of Wasm is unlocked by WASI (WebAssembly System Interface), a standards-based suite of APIs that make Wasm suitable for real-world applications, from filesystem access to machine learning.

Enter WASI 0.2 and the Component Model

WASI 0.2, released in 2024, introduces the Component Model—a breakthrough architecture that makes WebAssembly truly modular and interoperable. Instead of monolithic binaries, developers can now build reusable components that import and export standardized interfaces.

These interfaces are defined using WIT (WebAssembly Interface Types)—a simple language for specifying data types and function signatures across languages and runtimes.

Example WIT definition:

package docs:adder@0.1.0;

interface add {
  add: func(a: u32, b: u32) -> u32;
}

world adder {
  export add;
}

WIT doesn’t implement behavior; it defines contracts. This creates a shared surface area between independently developed components, much like MCP describes JSON-RPC tools, but closer to the compiled code and inherently cross-language.

Standardizing AI Inference with WebAssembly

The power of the Component Model extends beyond basic function calls. Projects like wasi-nn are defining standardized interfaces for AI inference, allowing Wasm components to serve or consume ML models using backends like TensorFlow, ONNX, PyTorch, and Llama.cpp.

Here’s a brief look at the wasi-nn WIT interface:

  • tensor: Typed multidimensional data

  • graph: A loaded ML model (e.g., ONNX, TensorFlow)

  • Inference: Compute APIs for executing models

  • errors: Robust handling and diagnostics

world ml {
  import tensor;
  import graph;
  import inference;
  import errors;
}

This enables any WASI 0.2-compatible language (Rust, TinyGo, Python, C++, etc.) to implement or consume AI workloads in a sandboxed, modular way, free from language bindings, OS dependencies, or container bloat.

Hayride: The Execution Layer for Agentic AI

Building on these principles, Hayride is our proposed execution architecture for next-generation AI agents.

Our thesis is simple: Secure execution is the missing layer of AI agent infrastructure.

Prompting and function calling are not enough. LLMs need a trusted, deterministic environment to execute actions, whether tool invocations, API requests, or AI-generated code.

With Hayride, we combine:

  • 🧱 WASI 0.2 components for defining, importing, and composing tools

  • 🛡️ Sandboxed WebAssembly runtimes for secure execution of agent actions

  • 🔁 Standard interfaces (via WIT) for pluggable, reusable functions

  • 🔄 Language interoperability so agents can execute in Rust, Go, Python, and more

  • 🔌 Extensibility through protocol adapters and LLM orchestration layers

Much of Hayride builds on the existing WebAssembly ecosystem. Using WebAssembly Interface Types, we are releasing our AI Interfaces, which aim to help compose WebAssembly components for agentic workloads.

Using Hayride, agents can execute code compiled into a WebAssembly component. When an LLM instructs agents to execute code, the component is loaded and launched in a new WebAssembly sandbox.

These interface definitions can be found on our GitHub. In future articles, we will deep dive into each of the AI interfaces.

A New Standard for AI Execution

Hayride isn’t just a runtime. It’s a step toward a formal execution protocol for agentic AI—one where function calls, tool orchestration, and even model inference can be described, sandboxed, and deployed as modular Wasm components.

This unlocks:

  • 🔐 Security through isolated execution and memory safety

  • 📦 Portability across cloud, edge, and local environments

  • 🧩 Composability via reusable, language-agnostic toolchains

  • 🚀 Performance through near-native execution speed

  • 🤖 Agent readiness for LLM orchestration, simulation, and autonomy

Standards-Compatible, Extensible by Design

Hayride is not a closed system. While the architecture is WebAssembly-first, it is protocol-agnostic. We are actively building adapters and bindings for:

  • Anthropic’s Model Context Protocol (MCP)

  • Agents2Agents (A2A) collaborative LLM frameworks

This allows Hayride components to be invoked as part of an existing MCP flow, exposed via A2A, or called directly via language models that support structured tool calling.

Call to Action

At Hayride, we’re building a secure AI runtime designed for agentic systems—and we’re betting on WebAssembly. We’re actively exploring:

  • Registry support for WASI components

  • WIT-based agent orchestration

  • LLM code generation alignment with the WebAssembly’s Component Model

  • Sandboxed inference and agent code execution

If you’re building agentic AI, secure runtimes, or composable dev tools, we’d love to talk!

Check out our GitHub and Developer Docs to get started today!

0
Subscribe to my newsletter

Read articles from Ethan Lewis directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ethan Lewis
Ethan Lewis

CTO at Kochava, previously a software engineer at IBM. I make grave mistakes all the time... everything seems to work out. Wasm, Wasm, Wasm...Wasm