Sandbox API

Purpose and Scope

The Sandbox API is the public adapter boundary for giving a Flue agent an execution workspace without coupling the agent harness to a specific sandbox provider. A sandbox, in this context, is the environment where an agent can run shell commands and perform file operations while it works on a task. The API page is written for adapter authors: someone integrating a third-party sandbox provider, remote container system, Cloudflare-style workspace, or local execution environment into Flue. Instead of teaching general sandbox usage, it defines how provider capabilities become the shape Flue expects during harness initialization.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

A key design point is that an adapter is intentionally small and pure. The adapter does not own the agent definition, does not decide the agent working directory, and does not destroy the provider infrastructure when a harness closes. It maps an already-initialized provider sandbox into a session environment rooted at the provider-owned base directory. That separation matters because Flue may initialize harnesses repeatedly for later requests or workflow runs, while the application remains responsible for creating, reusing, and deleting provider resources according to that provider’s lifecycle rules.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

Relevant Source Files

  • apps/docs/src/content/docs/api/sandbox-api.md — Canonical reader-facing API document for sandbox adapter authors, including the high-level adapter shape, public runtime imports, the visible TypeScript contracts, and implementation guidance for filesystem and command methods.

Core Primitives

The public shape starts with a factory function exported from one TypeScript file under the application source tree. The documentation uses a provider-named function as the pattern: a function such as a Daytona adapter receives an already-created provider sandbox and returns a factory object. Flue then calls the factory once per initialized harness with a session identifier. The returned session environment is the object the rest of the harness uses for all command execution and filesystem access during that harness lifetime.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

The adapter author implements the sandbox-facing API, then passes that implementation to the helper that constructs the runtime-facing session environment. The helper takes two values: the provider-specific API implementation and the provider-owned base current working directory. The base directory is important. It is not the same as an agent definition’s working directory. Flue resolves the agent’s configured working directory against the adapter base directory when the root harness is initialized, which prevents adapters from accidentally applying path semantics twice.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

Several names form the public vocabulary for this page. The sandbox API is the interface an adapter class implements. The sandbox factory is the object returned by the exported provider function. The session environment is created by the public helper and should not be hand-built by adapter code. The file stat type describes the result of inspecting a path. The optional session tool factory type supports custom model-facing tools for a sandbox. The unsupported operation error is for rejecting filesystem options that a provider cannot implement faithfully.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

Adapter Shape and Lifecycle

A typical adapter file has three layers. First, it imports public types and helpers from the runtime package. Second, it defines a provider-specific class that implements each filesystem and command method by delegating to the provider SDK. Third, it exports a factory function that captures the provider sandbox instance and returns an object with a method for creating the session environment. That method constructs the adapter class, chooses the provider base directory, and wraps both in the public session environment helper.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

// <source-dir>/sandboxes/<provider>.ts
import { createSandboxSessionEnv } from '@flue/runtime';
import type { SandboxApi, SandboxFactory, SessionEnv, FileStat } from '@flue/runtime';
import type { Sandbox as ProviderSandbox } from '<provider-sdk>';
 
class ProviderSandboxApi implements SandboxApi {
  constructor(private sandbox: ProviderSandbox) {}
  // Implement every method on SandboxApi.
}
 
export function provider(sandbox: ProviderSandbox): SandboxFactory {
  return {
    async createSessionEnv(): Promise<SessionEnv> {
      const sandboxCwd = '/workspace';
      const api = new ProviderSandboxApi(sandbox);
      return createSandboxSessionEnv(api, sandboxCwd);
    },
  };
}

This lifecycle gives applications an explicit ownership boundary. The factory may be called multiple times, so it should be safe for repeated harness initialization. Closing a harness should close or release only what the session environment owns; it should not assume that the provider sandbox itself must be deleted. For example, a remote workspace may be expensive to create and may be intentionally reused across requests. Conversely, an application may choose to create a short-lived provider sandbox before calling the adapter factory and tear it down after the surrounding task completes.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

API Contract Reference

The visible contract requires every adapter to implement text file reads, binary file reads, writes, stat information, directory listing, existence checks, directory creation, removal, and command execution. These methods are deliberately generic so the same harness can drive an in-memory workspace, a local trusted filesystem, a remote container, or another provider-backed environment. The adapter should translate Flue’s path, content, environment, timeout, and cancellation requests into the closest exact provider SDK calls, returning normalized results to the runtime.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

export interface SandboxApi {
  readFile(path: string): Promise<string>;
  readFileBuffer(path: string): Promise<Uint8Array>;
  writeFile(path: string, content: string | Uint8Array): Promise<void>;
  stat(path: string): Promise<FileStat>;
  readdir(path: string): Promise<string[]>;
  exists(path: string): Promise<boolean>;
  mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;
  rm(path: string, options?: { recursive?: boolean; force?: boolean }): Promise<void>;
  exec(
    command: string,
    options?: {
      cwd?: string;
      env?: Record<string, string>;
      timeoutMs?: number;
      signal?: AbortSignal;
    },
  ): Promise<{ stdout: string; stderr: string; exitCode: number }>;
}

Command execution has two cancellation-related inputs with different expectations. The timeout value is the primary cancellation contract, and every adapter should honor it by forwarding to the provider’s native timeout support when available. The abort signal is optional support for providers that can cancel work in flight. If a provider SDK cannot observe an abort signal, the adapter may ignore that option, but it should still respect the timeout. This keeps the common behavior reliable while allowing richer providers to expose better cancellation semantics.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

Filesystem options should be treated as behavioral promises, not casual hints. If recursive directory creation or forced recursive removal is requested, the adapter should only report success when the provider performed the same semantics. If the provider cannot implement an option exactly, the documentation points adapter authors to the public unsupported operation error rather than silently doing something weaker. That guidance is especially important for agents, because the model may continue its plan based on an incorrect assumption that a file tree was created or deleted.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

Implementation Guidance

Use the runtime package as the only import surface for Flue types and helpers. Adapter files should not import internal runtime paths because those paths are not part of the public compatibility contract. The documentation is explicit that adapter authors should typecheck against the real runtime types, and if the documentation ever drifts from the package, the package wins. In practice, that means an adapter should be developed inside a TypeScript project that depends on the same runtime version used by the application.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

Path handling is the most common source of adapter mistakes. The factory should pass a provider-owned base directory to the session environment helper. After that, Flue applies the agent’s working directory once. Adapter methods should then receive paths that are already in the coordinate system Flue expects for the session. Avoid combining the provider base directory, the agent directory, and the method path multiple times. A good mental model is that the adapter exposes a rooted workspace, while the harness handles user-facing working-directory policy above that root.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

Content handling should also preserve the distinction between string files and binary files. The contract includes both a text read method and a buffer read method, while writes may receive either text or bytes. Providers that expose only one content representation need careful conversion at the adapter layer. Text reads should return strings without inventing binary encodings, and buffer reads should return byte arrays suitable for files that are not valid text. That split lets agents edit source files while workflows can still stage and retrieve generated artifacts.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

Usage Flow for Adapter Authors

Start by creating the provider sandbox outside the adapter. That might involve authenticating to a hosted workspace service, choosing a container image, creating a Cloudflare-oriented workspace, or selecting a trusted local environment. Then create one adapter file that accepts the initialized provider object. Inside the file, implement the filesystem and command methods directly against the provider SDK. Finally, return a factory whose session creation method wraps the adapter in the runtime helper with the provider base directory.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

When testing an adapter, exercise the same operations an agent will rely on during real work: write a file, read it back as text, read a binary value, list a directory, inspect file metadata, create nested directories, remove files with supported options, and run a command with a working directory and environment variables. Include at least one timeout test for command execution. These tests are not merely provider smoke tests; they verify that the adapter has normalized the provider SDK into the semantics the Flue harness assumes.

Sources: apps/docs/src/content/docs/api/sandbox-api.md

The next pages to read depend on the role of the reader. Application authors who only need to choose between virtual, local, and remote environments should read the Sandboxes guide before writing an adapter. Runtime extension authors should pair this page with the Agent API and Workflow API, because those explain where harness sessions are created and consumed. Deployment-oriented readers should then follow the target-specific Cloudflare or Node material to understand which sandbox providers make sense in each runtime environment.