npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@langchain/modal

v0.1.3

Published

Modal Sandbox backend for deepagents

Downloads

206

Readme

@langchain/modal

Modal Sandbox backend for deepagents. This package provides a ModalSandbox implementation of the SandboxBackendProtocol, enabling agents to execute commands, read/write files, and manage isolated container environments using Modal's serverless infrastructure.

npm version License: MIT

Features

  • Isolated Execution: Run commands in secure, isolated containers on Modal's serverless infrastructure
  • GPU Support: Access NVIDIA GPUs (T4, L4, A10G, A100, H100) for ML/AI workloads
  • Custom Images: Use any Docker image from public registries
  • File Operations: Upload and download files with full filesystem access
  • Volume Mounts: Mount Modal Volumes for persistent storage
  • Secrets Injection: Securely inject Modal Secrets as environment variables
  • BaseSandbox Integration: All inherited methods (read, write, edit, ls, grep, glob) work out of the box
  • Factory Pattern: Compatible with deepagents' middleware architecture
  • Full SDK Access: Access the underlying Modal SDK via the sandbox property for advanced features

Installation

# npm
npm install @langchain/modal

# yarn
yarn add @langchain/modal

# pnpm
pnpm add @langchain/modal

Authentication Setup

The package requires Modal authentication:

Environment Variables (Recommended)

  1. Go to https://modal.com/settings/tokens
  2. Create a new token and set the environment variables:
export MODAL_TOKEN_ID=your_token_id
export MODAL_TOKEN_SECRET=your_token_secret

Explicit Credentials in Code

const sandbox = await ModalSandbox.create({
  auth: {
    tokenId: "your-token-id",
    tokenSecret: "your-token-secret",
  },
});

Basic Usage

import { createDeepAgent } from "deepagents";
import { ChatAnthropic } from "@langchain/anthropic";
import { ModalSandbox } from "@langchain/modal";

// Create and initialize the sandbox
const sandbox = await ModalSandbox.create({
  imageName: "python:3.12-slim",
  timeoutMs: 600_000, // 10 minutes
});

try {
  const agent = createDeepAgent({
    model: new ChatAnthropic({ model: "claude-sonnet-4-20250514" }),
    systemPrompt: "You are a coding assistant with access to a sandbox.",
    backend: sandbox,
  });

  const result = await agent.invoke({
    messages: [
      { role: "user", content: "Create a hello world Python app and run it" },
    ],
  });
} finally {
  await sandbox.close();
}

Configuration Options

ModalSandboxOptions extends the Modal SDK's SandboxCreateParams directly, so you can use any SDK option. We only wrap volumes and secrets to accept names instead of objects.

interface ModalSandboxOptions extends SandboxCreateParams {
  /** Modal App name. @default "deepagents-sandbox" */
  appName?: string;

  /** Docker image to use. @default "alpine:3.21" */
  imageName?: string;

  /** Initial files to populate the sandbox with. */
  initialFiles?: Record<string, string | Uint8Array>;

  /** Authentication credentials (or use env vars). */
  auth?: { tokenId?: string; tokenSecret?: string };

  /** Modal Volume names to mount (keys are mount paths). */
  volumes?: Record<string, string>;

  /** Modal Secret names to inject. */
  secrets?: string[];

  // All SandboxCreateParams options are available:
  timeoutMs?: number; // Max lifetime in milliseconds
  idleTimeoutMs?: number; // Idle timeout in milliseconds
  workdir?: string; // Working directory
  gpu?: string; // GPU type (e.g., "T4", "A100")
  cpu?: number; // CPU cores (fractional allowed)
  memoryMiB?: number; // Memory in MiB
  regions?: string[]; // Regions to run in
  env?: Record<string, string>; // Environment variables
  blockNetwork?: boolean; // Block network access
  cidrAllowlist?: string[]; // Allowed CIDRs
  verbose?: boolean; // Enable verbose logging
  name?: string; // Sandbox name (unique within app)
}

GPU Support

Modal supports various NVIDIA GPUs for ML/AI workloads:

const sandbox = await ModalSandbox.create({
  imageName: "python:3.12-slim",
  gpu: "T4", // NVIDIA T4 (16GB VRAM)
  // gpu: "L4",    // NVIDIA L4 (24GB VRAM)
  // gpu: "A10G",  // NVIDIA A10G (24GB VRAM)
  // gpu: "A100",  // NVIDIA A100 (40/80GB VRAM)
  // gpu: "H100",  // NVIDIA H100 (80GB VRAM)
});

Using Volumes

Mount Modal Volumes for persistent storage:

// Volume must be created in Modal first
const sandbox = await ModalSandbox.create({
  imageName: "python:3.12-slim",
  volumes: {
    "/data": "my-data-volume",
    "/models": "my-models-volume",
  },
});

// Files in /data and /models persist across sandbox restarts
await sandbox.execute("echo 'Hello' > /data/test.txt");

Using Secrets

Inject Modal Secrets as environment variables:

// Secrets must be created in Modal first
const sandbox = await ModalSandbox.create({
  imageName: "python:3.12-slim",
  secrets: ["my-api-keys", "database-credentials"],
});

// Secrets are available as environment variables
await sandbox.execute("echo $API_KEY");

Initial Files

Pre-populate the sandbox with files during creation:

const sandbox = await ModalSandbox.create({
  imageName: "python:3.12-slim",
  initialFiles: {
    // String content
    "/app/main.py": `
import json

def main():
    print("Hello from Python!")

if __name__ == "__main__":
    main()
`,
    // JSON configuration
    "/app/config.json": JSON.stringify(
      { name: "my-app", version: "1.0.0" },
      null,
      2,
    ),

    // Uint8Array content also supported
    "/app/data.bin": new Uint8Array([0x00, 0x01, 0x02]),
  },
});

// Files are ready to use immediately
const result = await sandbox.execute("python /app/main.py");
console.log(result.output); // "Hello from Python!"

This is especially useful for:

  • Setting up project scaffolding before agent execution
  • Providing configuration files
  • Pre-loading test data or fixtures
  • Creating initial source code files

Accessing the Modal SDK

For advanced features not exposed by BaseSandbox, you can access the underlying Modal SDK directly:

  • .client - The ModalClient instance for accessing other Modal resources
  • .instance - The Sandbox instance for direct sandbox operations
const modalSandbox = await ModalSandbox.create();

// Access the Modal client for other Modal resources
const client = modalSandbox.client;

// Access the raw Modal Sandbox for direct operations
const instance = modalSandbox.instance;

// Execute commands with specific options
const process = await instance.exec(["python", "-c", "print('Hello')"], {
  stdout: "pipe",
  stderr: "pipe",
});

// Open files for reading/writing
const writeHandle = await instance.open("/tmp/file.txt", "w");
await writeHandle.write(new TextEncoder().encode("Hello"));
await writeHandle.close();

Reconnecting to Existing Sandboxes

Resume working with a sandbox that is still running:

// First session: create a sandbox
const sandbox = await ModalSandbox.create({
  imageName: "python:3.12-slim",
  timeout: 3600, // 1 hour
});
const sandboxId = sandbox.id;

// Later: reconnect to the same sandbox by ID
const reconnected = await ModalSandbox.fromId(sandboxId);
const result = await reconnected.execute("ls -la");

// Or reconnect by name (if sandbox has a name)
const sandbox2 = await ModalSandbox.create({
  appName: "my-app",
  sandboxName: "my-sandbox",
  imageName: "python:3.12-slim",
});

const reconnected2 = await ModalSandbox.fromName("my-app", "my-sandbox");

Error Handling

import { ModalSandboxError } from "@langchain/modal";

try {
  await sandbox.execute("some command");
} catch (error) {
  if (error instanceof ModalSandboxError) {
    switch (error.code) {
      case "NOT_INITIALIZED":
        await sandbox.initialize();
        break;
      case "COMMAND_TIMEOUT":
        console.error("Command took too long");
        break;
      case "AUTHENTICATION_FAILED":
        console.error("Check your Modal token credentials");
        break;
      default:
        throw error;
    }
  }
}

Error Codes

| Code | Description | | ------------------------- | ------------------------------------------- | | NOT_INITIALIZED | Sandbox not initialized - call initialize() | | ALREADY_INITIALIZED | Cannot initialize twice | | AUTHENTICATION_FAILED | Invalid or missing Modal tokens | | SANDBOX_CREATION_FAILED | Failed to create sandbox | | SANDBOX_NOT_FOUND | Sandbox ID/name not found or expired | | COMMAND_TIMEOUT | Command execution timed out | | COMMAND_FAILED | Command execution failed | | FILE_OPERATION_FAILED | File read/write failed | | RESOURCE_LIMIT_EXCEEDED | CPU, memory, or storage limits exceeded | | VOLUME_ERROR | Volume operation failed |

Inherited BaseSandbox Methods

ModalSandbox extends BaseSandbox and inherits these convenience methods:

| Method | Description | | ------------ | ----------------------------- | | read() | Read a file's contents | | write() | Write content to a file | | edit() | Replace text in a file | | lsInfo() | List directory contents | | grepRaw() | Search for patterns in files | | globInfo() | Find files matching a pattern |

Limits and Constraints

| Constraint | Value | | --------------- | --------------------------------------- | | Max timeout | 86400 seconds (24 hours) | | Default timeout | 300 seconds (5 minutes) | | Network access | Full (by default, can be blocked) | | File API | Alpha (up to 100 MiB read, 1 GiB write) |

Environment Variables

| Variable | Description | | -------------------- | ---------------------- | | MODAL_TOKEN_ID | Modal API token ID | | MODAL_TOKEN_SECRET | Modal API token secret |

License

MIT