How Maka Handles Tool Execution Sandbox Boundary Crossings

Maka handles tool execution that requires sandbox boundary crossings through a deterministic six-step workflow where tools return a sandbox_boundary_required failure object, the runtime raises an expansion request via request_sandbox_boundary, and the SandboxManager selects a platform-specific backend (Seatbelt, bubblewrap, or AppContainer) only after explicit approval.

Apache Maka separates tool execution from sandbox-boundary management to enforce security without ambiguity. When a tool operation—such as a file write or shell command—attempts to cross the current ExecutionBoundary, the runtime does not execute it immediately. Instead, the system pauses execution and initiates a structured request-and-approval workflow that ensures clear separation between permission handling and OS-level process isolation.

The Six-Step Boundary Crossing Workflow

When a tool detect that it would cross a sandbox boundary, Maka follows this deterministic sequence:

  1. Detect the boundary crossing – The tool returns a failure object containing the flag sandbox_boundary_required and a concrete expansion describing the sandbox profile that would satisfy the request.
  2. Raise a boundary-expansion request – The runtime kernel calls request_sandbox_boundary with the proposed expansion, creating a sandbox-boundary event sent to the user interface and the SandboxManager.
  3. Pause execution – The current turn stops at a deterministic position while the system awaits approval. No partial results are emitted, ensuring the UI shows a clear "waiting for sandbox approval" state.
  4. Approve or deny – The SandboxManager (or the user via the UI) decides whether the requested sandbox profile is allowed. The decision is recorded in the session’s ExecutionBoundary.
  5. Transform and run – If approved, the selected platform sandbox backend—macOS Seatbelt, Linux bubblewrap, Windows AppContainer, or a "none" fallback—is invoked by SandboxManager. It translates the tool request into a platform-specific command line, mounts, or policy bundle, then spawns the process inside the sandbox.
  6. Return the result – The tool’s output (or error) is streamed back to the model, and the session resumes normally.

Core Architectural Components

ExecutionBoundary: The Authority Record

The ExecutionBoundary is the authority that records whether the current session is inside a sandbox and which profile is active. According to the Runtime sandbox boundary documentation, this object tracks the current security context and validates whether requested operations—such as file writes or network access—are permitted within the existing boundary.

Tools check the boundary before execution using methods like allowsWrite(). If the check fails, the boundary remains unchanged and the tool signals the need for expansion rather than attempting unauthorized access.

SandboxManager: Backend Selection and Transformation

The SandboxManager, implemented in packages/runtime/src/sandbox/sandbox-manager.ts, serves as the central authority for sandbox decisions. It determines whether a profile requires a sandbox, selects the appropriate platform backend, and performs command transformation. Notably, the manager does not spawn processes itself; it delegates to platform-specific implementations.

The manager evaluates the expansion payload from the boundary request and translates high-level sandbox profiles into concrete platform commands. For example, it converts a "workspace-write" profile into sandbox-exec arguments on macOS or bubblewrap bind-mounts on Linux.

Code-Level Implementation

Detecting Boundary Violations in Tools

Tools implement boundary checks directly in their execution logic. When a tool determines it cannot complete an operation within the current ExecutionBoundary, it returns a structured failure payload rather than throwing an error or attempting the operation.

// Example: a filesystem-write tool
export async function writeFile(path: string, data: string, ctx: ExecutionContext) {
  if (!ctx.boundary.allowsWrite(path)) {
    // Signal that a sandbox with a broader profile is needed
    return {
      sandbox_boundary_required: true,
      expansion: { profile: "workspace-write", reason: "write to workspace" },
    };
  }
  // Normal execution path (no boundary crossing)
  return await ctx.fsWorker.write(path, data);
}

When the allowsWrite check fails, the tool returns the failure payload containing sandbox_boundary_required: true and the specific expansion profile required. This triggers the expansion workflow in the runtime kernel.

Runtime Kernel Handling

The runtime kernel intercepts tool results and manages the pause-resume cycle. When it detects a boundary requirement, it pauses execution and waits for the SandboxManager decision.

async function handleToolResult(result: any, ctx: ExecutionContext) {
  if (result?.sandbox_boundary_required) {
    await ctx.requestSandboxBoundary(result.expansion);
    // Execution pauses here – UI shows "awaiting sandbox approval"
    await ctx.waitForBoundaryDecision();   // resolves when approved/denied
    // After approval, the original tool call is re-invoked automatically.
    return await ctx.retryOriginalTool();
  }
  return result; // normal successful result
}

The kernel ensures no partial execution occurs during the approval phase. After waitForBoundaryDecision() resolves, the original tool call is automatically retried within the newly approved sandbox context.

Platform Backend Selection

The SandboxManager selects the appropriate sandbox implementation based on the host platform and the requested profile requirements.

// sandbox-manager.ts (simplified)
export async function selectBackend(expansion: SandboxProfile) {
  if (expansion.requiresSandbox) {
    switch (process.platform) {
      case "darwin":  return new MacOSSeatbelt(expansion);
      case "linux":   return new LinuxBubblewrap(expansion);
      case "win32":   return new WindowsAppContainer(expansion);
    }
  }
  return new NoSandboxBackend(); // "none" – runs on host
}

This architecture ensures that tool execution sandbox boundary crossings are handled consistently across macOS, Linux, and Windows, with each platform backend translating the abstract SandboxProfile into native isolation mechanisms—Seatbelt profiles, bubblewrap namespaces, or AppContainer ACLs.

Summary

  • ExecutionBoundary tracks the current sandbox state and validates tool permissions before execution.
  • Tools signal boundary violations by returning { sandbox_boundary_required: true, expansion: ... } rather than attempting unauthorized operations.
  • The runtime kernel pauses execution deterministically at requestSandboxBoundary() and resumes only after SandboxManager approval.
  • SandboxManager in packages/runtime/src/sandbox/sandbox-manager.ts selects between MacOSSeatbelt, LinuxBubblewrap, and WindowsAppContainer backends based on the platform.
  • The "none" fallback allows execution on the host when sandboxing is not required, maintaining flexibility for trusted operations.

Frequently Asked Questions

What happens when a tool tries to cross a sandbox boundary without permission?

The tool returns a failure payload with sandbox_boundary_required: true and an expansion object describing the required profile. The runtime kernel catches this payload, pauses execution via requestSandboxBoundary(), and waits for the SandboxManager or user to approve the expansion. The tool never executes outside its authorized boundary.

How does the SandboxManager choose between Seatbelt, bubblewrap, and AppContainer?

The SandboxManager examines process.platform and instantiates the appropriate backend class—MacOSSeatbelt, LinuxBubblewrap, or WindowsAppContainer—as implemented in packages/runtime/src/sandbox/sandbox-manager.ts. Each backend translates the generic SandboxProfile into platform-specific policies, command-line arguments, or container configurations.

Can tools execute partially before hitting a sandbox boundary?

No. Maka ensures atomic boundary checking: tools validate the ExecutionBoundary before performing any state-changing operations. If the boundary is insufficient, the tool returns immediately with the expansion request, leaving the system state unchanged and preventing partial execution.

Where is the boundary state stored during a session?

The boundary state is maintained in the session’s ExecutionBoundary object, which acts as the central authority for the current security context. The SandboxManager updates this object when approvals are granted, ensuring all subsequent tool calls reference the correct, updated sandbox profile.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →