Better E2B Sandbox · emploidai Marketplace
emploidai Marketplace
Add-onsAppletsPlugins
Search tools, teams, and capabilitiesPublish
MarketplacePluginsBetter E2B Sandbox
Plugin
Limited listing

Better E2B Sandbox

by lysonober · v0.0.3

Create and manage E2B sandboxes for Dify workflows, with Claude Code and Next.js tooling.

186 installsUpdated Feb 14, 2026
Publisher information is incomplete

This community listing does not yet include every recommended support, privacy, pricing, and permission disclosure. Review the available package permissions before installing.

Capabilities

Tools

Available inside your emploidai workspace after installation.

Data sources

Available inside your emploidai workspace after installation.

Category

tool

Version

0.0.3lysonober

Requirements

Maximum memory 256MB

Pricing

Not disclosed by publisher

Security & access

Review before installing

CompatibleRequires emploidai 1.0.0+

Permissions

  • Uses tool capability
  • Requires encrypted tool credentials

Dependencies

No additional dependencies

Resources

Privacy policy
emploidai Marketplace

Discover capabilities. Review access. Install inside your workspace.

DocumentationSecuritySupportPrivacyTerms

Better E2B Sandbox Plugin for Dify

Author: lysonober

Version: 0.0.3

Type: Tool

Better E2B Sandbox creates and manages E2B cloud sandboxes inside Dify workflows. It supports Claude Code integration, Next.js project scaffolding (npm and Bun), stateful interactive shell sessions, common package installation, file operations, template building, and full sandbox lifecycle management with pause, resume, and kill capabilities.

Security Warning: Disable Public Access to Your Workflow

When you create a new workflow in Dify, the Web App and Backend Service API access points are enabled by default. This means anyone with the URL can trigger your workflow, which in turn can create sandboxes, run commands, read files, and consume your E2B and Anthropic API credits.

Before publishing or sharing your workflow, you must:

  1. Go to your workflow settings in Dify.
  2. Disable Web App access if you do not need a public-facing interface.
  3. Disable Backend Service API access if you do not need external API calls.
  4. If you do need these access points enabled, add authentication (API keys, OAuth, or IP whitelisting) to prevent unauthorized access.

Without these precautions, a leaked workflow URL allows anyone to create sandboxes under your E2B account, run arbitrary code via Claude Code, and access any credentials (GitHub tokens, Vercel tokens, Anthropic keys) that you configured in the plugin. E2B bills per second for running sandboxes, so unauthorized usage can result in unexpected charges.

This is not a limitation of this plugin. It is a standard Dify workflow security consideration that applies to any plugin that manages external resources.

Quick Start Workflow

How Sandbox Timeout Actually Works (Read This First)

The single most confusing concept in E2B is the sandbox timeout. If you do not understand this, you will waste money or lose work. Here is how it works.

When you create a sandbox, you set a timeout. For example, Create Claude Code Sandbox with timeout_preset=1800 gives you a 30-minute sandbox. This means the sandbox will automatically shut down 30 minutes after creation, regardless of what is running inside it.

Here is the critical part: every time you call Sandbox.connect(), the timeout resets. Every tool in this plugin that talks to an existing sandbox (Send Sandbox Input, Install Packages, Read Sandbox File, Write Sandbox File, Start Shell Session, Pause Sandbox, and so on) internally calls Sandbox.connect(). That connect call resets the sandbox timeout to whatever value the tool passes.

Story: The 24-hour sandbox that died in 30 minutes

You create a Claude Code sandbox with sandbox_timeout_seconds=86400 (24 hours). The sandbox starts with a 24-hour clock. You store the sandbox_id. Five minutes later, you call Send Sandbox Input with the default timeout_preset=1800 (30 minutes). At that moment, the 24-hour clock is thrown away and replaced with a 30-minute clock. The sandbox will now die 30 minutes after that Send Sandbox Input call, not 24 hours after creation.

What you should do: If you need a long-lived sandbox, make sure every subsequent tool call also uses a long timeout. If you created a 24-hour sandbox, set timeout_preset=86400 (or use sandbox_timeout_seconds=86400) on every Send Sandbox Input call too. Or better yet, use Pause Sandbox between interactions, which preserves state indefinitely (up to 30 days) without consuming compute.

Story: Using extend_lifecycle to keep a sandbox alive

You have a sandbox running a background task. The user has not sent a message in 25 minutes, and the 30-minute timeout is about to expire. You call Send Sandbox Input with action=extend_lifecycle_1h. This action does not run any command. It just connects with timeout=3600 (1 hour), which resets the sandbox clock to 1 hour from now. The background task keeps running.

Story: The heartbeat pattern for long-running tasks

You want Claude Code to monitor an API endpoint every 5 minutes for the next 6 hours. You call Setup Sandbox Heartbeat with task_description="Check https://api.example.com/health every 5 minutes and log the response to /tmp/health.log", suggested_interval="5 minutes", estimated_duration="6 hours", and sandbox_timeout_seconds=21600 (6 hours). The tool sends a specialized prompt to Claude Code that tells it to create a background script with nohup while true; do curl ...; sleep 300; done &. Claude Code creates the script and starts it. The sandbox stays alive for 6 hours because of the timeout you set.

But what if your E2B plan only allows 1-hour sandboxes? Then you need a different approach: set the sandbox timeout to 1 hour, and have your Dify workflow call Send Sandbox Input with action=extend_lifecycle_1h every 50 minutes. Each call resets the clock. The background task survives because the sandbox never expires.

The Tools (Detailed)

This plugin provides 18 tools. Here is what each one does, when to use it, and how its parameters work.

Create Sandbox

The most basic creation tool. It starts a new sandbox from a template alias (or the default base template if you leave template_alias empty).

Parameters that matter:

  • template_alias: The template to use. Leave empty for a bare Linux sandbox. Use claude-code if you want Claude Code pre-installed (but Create Claude Code Sandbox is better for that). Use any custom alias you built with Build Template.
  • envs_json: Extra environment variables. Format: DEBUG=true;NODE_ENV=development or {"DEBUG":"true"}.
  • metadata_json: Labels for filtering in List Sandboxes. Format: userId=user_123;app=dify.
  • ports: Comma-separated port numbers. The tool generates external URLs like https://3000-SANDBOX_ID.e2b.app for each port.
  • env_injection_scope: sandbox_global (default) writes env vars permanently into the sandbox. command_only means env vars are only available when explicitly passed with each command.
  • GitHub and Vercel override parameters: If you set github_token_override, it overrides both the envs_json GITHUB_TOKEN and the provider credential. Same for Vercel parameters.

Story: Creating a sandbox to analyze a private repository

You want Claude Code to review code in a private GitHub repo. You call Create Sandbox with template_alias=claude-code, github_token_override=ghp_xxxxx, github_username_override=lysonober, ports=3000. The sandbox starts with GITHUB_TOKEN and GITHUB_USER injected. You then call Send Sandbox Input with action=shell_command, input_text="git clone https://$GITHUB_TOKEN@github.com/lysonober/my-private-repo.git". The clone succeeds because the token is in the environment.

Create Claude Code Sandbox

Creates a sandbox specifically optimized for Claude Code. This is the tool you should use when your primary goal is to run Claude Code prompts.

What it does that Create Sandbox does not:

  1. Uses the official claude-code template alias, which has Claude Code CLI pre-installed.
  2. Automatically injects ANTHROPIC_API_KEY into the sandbox environment.
  3. Writes E2B_SANDBOX_ID into /home/user/.profile and /home/user/.bashrc using the filesystem API (not shell commands, which avoids the /root/.bashrc permission denied error).
  4. Runs claude update automatically to ensure the CLI is up to date. The update tries three commands in order: yes | claude update, claude update, npm install -g @anthropic-ai/claude-code@latest. The first one that succeeds wins.
  5. Writes .claude/settings.local.json with your chosen permissions preset.
  6. Optionally injects Claude Code memory files (user memory and project memory).

Permissions presets:

  • allow_all (default): Bypasses all permission prompts. Best for non-interactive sandbox environments where Claude Code cannot ask the user for confirmation. This is the recommended default for Dify workflows.
  • dev_standard: Allows common development operations (read, edit, write, git status, npm, pip, pytest) but asks before git push, WebFetch. Denies reading .env files and using curl/wget.
  • ci_build_test: Non-interactive mode for CI pipelines. Auto-denies anything not explicitly allowed.
  • review_readonly: Read-only access. Cannot edit, write, or run commands.
  • plan_mode: Planning only. No tool execution at all.

Story: Setting up a Claude Code sandbox with project context

You are building a Dify bot for a law firm. Each lawyer has domain expertise that should persist across conversations. You call Create Claude Code Sandbox with:

  • permissions_preset=allow_all
  • user_memory_content="I am a corporate lawyer specializing in M&A contracts. Flag indemnification clauses exceeding $10M. Highlight non-compete terms over 2 years."
  • project_memory_content="Tech stack: Next.js, PostgreSQL, Prisma. Follow ESLint rules. Use TypeScript strict mode."
  • sandbox_timeout_seconds=3600

The sandbox starts with Claude Code configured to bypass all permission prompts, the lawyer's expertise written to ~/.claude/CLAUDE.md, and project conventions written to CLAUDE.md in the working directory. Every Claude Code prompt in this sandbox will see both memory files.

Create Next.js Sandbox

Creates a sandbox with a fresh Next.js project scaffolded using the latest create-next-app. This tool does not rely on any pre-built Next.js template. Instead, it always starts from the base template and runs the scaffolding commands at creation time, guaranteeing you get the latest Next.js and shadcn versions.

What happens step by step:

  1. Creates a base sandbox (no template alias).
  2. Runs npx create-next-app@latest . --ts --tailwind --eslint --import-alias "@/*" --use-npm --app --src-dir in /home/user/nextjs-app.
  3. Runs npx shadcn@latest init -d (non-interactive shadcn initialization).
  4. If shadcn_add_all=true, runs yes | npx shadcn@latest add --all (installs all shadcn UI components).
  5. Starts the dev server in background: npm run dev -- --hostname 0.0.0.0 --port 3000.
  6. Waits up to 60 seconds for port 3000 to become reachable. If it does not, returns the dev server log from /tmp/nextjs-dev.log so you can diagnose the issue.

Important: This tool requires allow_internet_access=true (it is the default). Without internet, npx cannot download packages.

Story: Creating a Next.js sandbox and then adding Claude Code

You want users to be able to create a Next.js project and then use Claude Code to modify it. Your Dify workflow does:

  1. Create Next.js Sandbox with shadcn_add_all=true, vercel_token_override=xxx, vercel_org_id_override=team_xxx. Store the sandbox_id.
  2. Install Packages with preset_command=claude_code_latest and the sandbox_id from step 1. Now the sandbox has both Next.js and Claude Code.
  3. Send Sandbox Input with action=claude_code, input_text="Add a dark mode toggle to the navbar using shadcn components", resume_session=false (fresh session since Claude Code was just installed).

The user sees the dev server URL from step 1, and after step 3, the Next.js project has a dark mode toggle.

Create Next.js (Bun) Sandbox

Same as Create Next.js Sandbox, but uses Bun instead of npm. The tool first installs Bun (curl -fsSL https://bun.sh/install | bash), then uses bunx create-next-app@latest and bun run dev. The port readiness timeout is 90 seconds (longer than npm because Bun installation adds time). Dev server log goes to /tmp/nextjs-bun-dev.log.

Send Sandbox Input

The primary interaction tool. Once you have a sandbox_id, this is how you talk to it.

Actions:

  • claude_code (default): Sends input_text as a prompt to Claude Code CLI. Requires ANTHROPIC_API_KEY (from provider credentials or anthropic_api_key_override). If resume_session=true (default), uses claude --continue -p to resume the most recent conversation. If false, starts fresh with claude -p.
  • shell_command: Runs input_text as a shell command. Each call is a fresh shell, so cd and export do not persist across calls. Use Start Shell Session if you need stateful sessions.
  • heartbeat: Runs echo heartbeat. Use this to keep the sandbox alive without doing anything meaningful.
  • extend_lifecycle_1h: Does not run any command. Just connects with a 1-hour timeout to reset the sandbox clock.

What happens when Claude Code CLI is missing: If you select action=claude_code on a sandbox that does not have Claude Code installed (for example, a sandbox created with Create Sandbox or Create Next.js Sandbox), the tool detects "command not found" in the error output and returns a clear message telling you to run Install Packages with the Claude Code Latest preset first. It does not crash.

What happens when Claude Code CLI is outdated: If Claude Code CLI refuses to run because it needs an update (error message contains "needs an update" and "claude update"), the tool automatically runs the update sequence (same as Create Claude Code Sandbox) and retries the original command. This only triggers when the CLI explicitly refuses, not on every call.

Story: Multi-turn conversation with Claude Code

Turn 1: User says "Create a Python web scraper for Hacker News". Your workflow calls Create Claude Code Sandbox, stores sandbox_id, then calls Send Sandbox Input with action=claude_code, input_text="Create a Python web scraper that fetches the top 10 stories from Hacker News and saves them to stories.json", resume_session=false. Claude Code creates the scraper. Workflow returns the output and pauses the sandbox.

Turn 2: User says "Add error handling and retry logic". Your workflow calls Send Sandbox Input with the same sandbox_id, action=claude_code, input_text="Add error handling with exponential backoff retry logic to the scraper", resume_session=true. Claude Code remembers the scraper it created and modifies it. Because resume_session is true, it has full context from turn 1.

Turn 3: User says "Run it and show me the output". Your workflow calls Send Sandbox Input with action=shell_command, input_text="cd /home/user && python scraper.py && cat stories.json". The shell command runs the scraper and returns the JSON output.

Install Packages

Installs tools and packages in an existing sandbox. This is the general-purpose "add stuff to a sandbox" tool.

How to use:

  • Quick single install: Use preset_command dropdown. Pick "Claude Code Latest", "OpenClaw", or "Remotion".
  • Multiple presets at once: Use additional_preset_commands with comma delimiter: claude_code_latest,openclaw.
  • Custom commands: Use custom_commands with your chosen delimiter.

Preset commands and what they actually run:

  • claude_code_latest: npm install -g @anthropic-ai/claude-code@latest
  • openclaw: curl -fsSL https://openclaw.ai/install.sh | bash
  • remotion: npx create-video@latest

Presets execute first, then custom commands, in order. Each command runs sequentially as the user "user" (not root).

Story: Installing multiple tools at once

You created a base sandbox and want to set up a full development environment. You call Install Packages with:

  • preset_command=claude_code_latest
  • custom_commands="npm install -g pnpm\npip install requests beautifulsoup4\napt-get update && apt-get install -y jq"
  • custom_delimiter=newline

This runs four commands in order: (1) npm install Claude Code, (2) npm install pnpm, (3) pip install requests and beautifulsoup4, (4) apt-get install jq. The output tells you which succeeded and which failed.

Start Shell Session / Send Shell Session Input / Kill Shell Session

These three tools work together to provide stateful interactive shell sessions. They solve the problem that sbx.commands.run() (used by Send Sandbox Input with action=shell_command) starts a fresh shell every time, so cd, exported variables, and shell history do not persist.

Start Shell Session:

  • Creates a PTY (pseudo-terminal) session, like opening a new terminal tab.
  • Returns a session_pid (integer) that you use for all subsequent interactions.
  • Optional cwd parameter sets the initial working directory.

Send Shell Session Input:

  • Sends input_text to the PTY and reads back output.
  • By default appends a newline (simulates pressing Enter).
  • read_timeout_seconds (default 2) controls how long to wait for output. For fast commands like ls, 2 seconds is fine. For slow commands like npm install, increase it.
  • max_output_chars (default 4000) caps the output length to avoid flooding.
  • Output may contain ANSI escape sequences (colors, cursor movement) because it is a real terminal.

Kill Shell Session:

  • Terminates the PTY process by PID.

Story: Using a stateful shell to navigate and build a project

Step 1: Start Shell Session with sandbox_id=xxx, cwd=/home/user. Returns session_pid=42.

Step 2: Send Shell Session Input with session_pid=42, input_text="ls". Output shows the directory listing.

Step 3: Send Shell Session Input with session_pid=42, input_text="cd my-project". Output shows the prompt changed to my-project directory.

Step 4: Send Shell Session Input with session_pid=42, input_text="npm install", read_timeout_seconds=30. The shell remembers you are in my-project because the PTY session is stateful.

Step 5: Send Shell Session Input with session_pid=42, input_text="npm run build", read_timeout_seconds=60.

Step 6: Kill Shell Session with session_pid=42.

Notice how steps 3 through 5 all happen in the same shell. If you had used Send Sandbox Input with action=shell_command, each call would start in /home/user and you would have to prepend cd my-project && to every command.

Setup Sandbox Heartbeat

A specialized Claude Code tool for creating periodic background tasks. It prepends a detailed system prompt to your task description that teaches Claude Code how to write a background loop script.

When to use: When you want something to happen repeatedly inside the sandbox over a long period. Examples: health checks, data polling, log rotation, periodic API calls.

Parameters:

  • task_description (required): What should happen. Be specific.
  • suggested_interval: How often. Examples: "5 minutes", "30 seconds", "1 hour".
  • estimated_duration: How long. Examples: "6 hours", "1 day", "until stopped".
  • Default timeout is 3600 seconds (1 hour), longer than other tools.

Story: Monitoring a deployment

You just deployed a web app from a sandbox. You want to monitor it for the next 2 hours. You call Setup Sandbox Heartbeat with:

  • task_description="Check https://my-app.vercel.app every 2 minutes. If the HTTP status is not 200, write an alert to /tmp/alerts.log with the timestamp and status code."
  • suggested_interval="2 minutes"
  • estimated_duration="2 hours"
  • sandbox_timeout_seconds=7200

Claude Code creates a script like:

#!/bin/bash
while true; do
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://my-app.vercel.app)
  if [ "$STATUS" != "200" ]; then
    echo "$(date): ALERT status=$STATUS" >> /tmp/alerts.log
  fi
  sleep 120
done

It runs it with nohup ./monitor.sh & and reports the PID. Two hours later, the sandbox expires. If you need to check the alerts before that, call Read Sandbox File with file_path=/tmp/alerts.log.

Guard Output

A security tool that blocks or redacts known secret values from output text before it reaches end users.

How it works:

  1. Collects secret values from provider credentials (e2b_api_key, e2b_access_token, anthropic_api_key).
  2. Optionally accepts additional secrets via additional_secrets parameter.
  3. For each secret, generates three matching variants: exact string, base64 encoding, URL encoding (only for secrets 12+ characters to avoid false positives).
  4. Scans the input text for any of these variants.
  5. In block mode (default): If any secret is found, replaces the entire output with a warning message.
  6. In redact mode: Replaces each matched secret with [REDACTED] and returns the modified text.

Story: Preventing API key leakage in a chatbot

Your Dify workflow runs Claude Code and returns the output to users. Claude Code might accidentally print environment variables (for example, if the user asks "show me all environment variables" and Claude runs env). Without Guard Output, the ANTHROPIC_API_KEY would be sent to the user.

Your workflow: Send Sandbox Input (claude_code) -> Guard Output (text = output from previous step, mode = redact) -> Reply node. If Claude Code's output contains the API key, it gets replaced with [REDACTED] before reaching the user.

Read Sandbox File

Reads a file or lists a directory from the sandbox filesystem.

For files: Returns the file content directly.

For directories: Lists all entries (files, directories, symlinks) in a tree format, then reads file contents in parallel using up to 50 concurrent threads. You can control how many files to read with max_files_content (0 = tree only, -1 = read all, positive number = limit). Hidden files (starting with .) are excluded by default unless include_hidden=true.

Story: Reviewing what Claude Code created

After running Claude Code to create a project, you call Read Sandbox File with file_path=/home/user/my-project. The tool returns:

/home/user/my-project/
├── src/
├── package.json
├── tsconfig.json
└── README.md

FILE CONTENTS
--- /home/user/my-project/package.json ---
{ "name": "my-project", ... }
--- /home/user/my-project/tsconfig.json ---
{ "compilerOptions": { ... } }
--- /home/user/my-project/README.md ---
# My Project
...

To read the src directory, make another call with file_path=/home/user/my-project/src.

Write Sandbox File

Writes content to a file in the sandbox. Parent directories are created automatically.

Story: Injecting a configuration file before running Claude Code

You want Claude Code to work with a specific .env file. You call Write Sandbox File with file_path=/home/user/my-project/.env, content="DATABASE_URL=postgres://...\nAPI_KEY=test123". Then you call Send Sandbox Input with action=claude_code, input_text="Read the .env file and create a database connection module".

Pause Sandbox

Freezes a sandbox in place. The sandbox stops consuming compute resources, but its entire state (filesystem, memory, running processes) is preserved for up to 30 days.

Technical detail: Pausing takes approximately 4 seconds per 1 GiB of RAM.

When to use: Between user interactions in a multi-turn conversation. Pause after each response, resume (by calling any tool with the sandbox_id) when the user sends the next message.

Story: Cost-efficient multi-turn conversation

Your chatbot creates a sandbox for each user conversation. A user sends a message at 10:00 AM, you create a sandbox and run Claude Code. The response takes 30 seconds. Without pausing, the sandbox runs (and costs money) until the 30-minute timeout. With pausing, you pause immediately after getting the response. The sandbox costs 30 seconds of compute instead of 30 minutes. When the user replies at 10:15 AM, any tool call with that sandbox_id automatically resumes it.

List Sandboxes

Lists all sandboxes (running and paused) in your E2B account with optional filtering.

Filters:

  • state_filter: running, paused, or all (default).
  • sandbox_ids: Comma-separated IDs to look up specific sandboxes.
  • Metadata filters: metadata_user_id, metadata_app, metadata_env, metadata_custom (key=value pairs).

Story: Cleaning up forgotten sandboxes

You notice your E2B bill is higher than expected. You call List Sandboxes with state_filter=running and see 15 running sandboxes. Most of them have metadata_app=dify and metadata_user_id values. You identify 10 sandboxes from yesterday's testing that were never killed. You call Kill Sandbox for each one.

Kill Sandbox

Permanently destroys a sandbox. All files, Claude Code conversation history, and running processes are gone. There is no undo.

When to use: When a conversation ends and you are certain you will not need the sandbox again.

Build Template

Creates a reusable E2B template with pre-installed dependencies and repositories. The build runs on E2B's infrastructure, not on your Dify server.

Base strategies:

  • e2b_base_image (default): Start from E2B's base Linux image.
  • template_alias: Extend an existing template (yours or a public one).
  • docker_image: Start from any Docker image.

What you can pre-install:

  • apt_packages: System packages (comma-separated). Example: jq,curl,git.
  • pip_packages: Python packages (comma-separated). Example: requests,beautifulsoup4,pandas.
  • npm_packages: Node packages (comma-separated). Example: typescript,@anthropic-ai/claude-code.
  • git_repositories: Git URLs to clone (comma-separated). Cloned to /home/user/REPO_NAME.
  • custom_dockerfile_commands: Advanced shell commands.

Story: Building a template for a specific project

Your team works on a Python ML project. Every sandbox needs numpy, pandas, scikit-learn, and the project repo. You call Build Template with:

  • template_name=ml-project-base
  • pip_packages=numpy,pandas,scikit-learn,matplotlib
  • git_repositories=https://github.com/your-org/ml-project.git
  • cpu_count=4
  • memory_mb=4096

The build takes a few minutes. After that, every Create Sandbox with template_alias=ml-project-base starts with everything pre-installed. No waiting for pip install or git clone.

List Templates

Lists all templates in your E2B account with their aliases, build status, CPU, memory, and visibility settings.

Environment Variable Injection

All creation tools support environment variable injection with a clear three-layer priority system:

  1. Tool override parameter (highest priority): github_token_override, vercel_token_override, etc.
  2. envs_json field: Extra environment variables you pass as a JSON object or key=value pairs.
  3. Provider credential (lowest priority): Values configured in the plugin settings.

For example, if your provider credential has VERCEL_TOKEN=aaa, your envs_json has VERCEL_TOKEN=bbb, and your tool parameter has vercel_token_override=ccc, the sandbox gets VERCEL_TOKEN=ccc.

The env_injection_scope parameter controls when variables are injected:

  • sandbox_global (default): Variables are set at sandbox creation time and persist for the entire sandbox lifetime.
  • command_only: Variables are only available when explicitly passed with each command (as a shell prefix).

Vercel variables deserve special mention: when you set Vercel Team ID (via vercel_org_id_override or provider credential), the plugin injects both VERCEL_ORG_ID and VERCEL_TEAM_ID with the same value, because different Vercel tools expect different variable names.

Claude Code Permissions Presets

Create Claude Code Sandbox writes .claude/settings.local.json inside the sandbox. This file controls what Claude Code is allowed to do.

PresetdefaultModeBest For
allow_all (default)bypassPermissionsNon-interactive sandboxes, Dify workflows
dev_standardacceptEditsDay-to-day development with safety rails
dev_webfetch_allowlistacceptEditsDevelopment needing external docs/packages
ci_build_testdontAskCI pipelines, automated testing
review_readonlydontAskCode review, no modifications
plan_modeplanPlanning only, no execution

You can append custom rules via permissions_allow, permissions_ask, and permissions_deny parameters. Format: semicolon-separated rules like Bash(npm run build);Read(./docs/**) or JSON array like ["Bash(npm run build)","Read(./docs/**)"].

Common Mistakes and How to Avoid Them

Mistake: Using shell_command action for multi-step operations

Each action=shell_command call starts a fresh shell. If you call input_text="cd /home/user/project" followed by input_text="npm install", the second call runs in /home/user (the default), not in /home/user/project.

Fix: Either combine commands with && (e.g., input_text="cd /home/user/project && npm install"), or use Start Shell Session for a stateful session.

Mistake: Forgetting that connect resets the timeout

As explained above, every tool call resets the sandbox timeout. If you create a sandbox with a 2-hour timeout but all your Send Sandbox Input calls use the default 30-minute timeout, the sandbox will die 30 minutes after the last interaction, not 2 hours after creation.

Fix: Set consistent timeouts across all tool calls, or use Pause Sandbox between interactions.

Mistake: Using claude_code action on a non-Claude-Code sandbox

If you create a sandbox with Create Sandbox or Create Next.js Sandbox, Claude Code CLI is not installed. Calling Send Sandbox Input with action=claude_code will fail.

Fix: Either use Create Claude Code Sandbox, or call Install Packages with preset_command=claude_code_latest before using the claude_code action.

Mistake: Not using Guard Output before replying to users

Claude Code might accidentally output API keys or tokens. If your workflow sends Claude Code output directly to a Reply node, those secrets reach the end user.

Fix: Always place Guard Output between Send Sandbox Input and the Reply node.

Workflow Design Patterns

Pattern 1: Simple single-turn Claude Code

User Message -> Create Claude Code Sandbox -> Send Sandbox Input (claude_code) -> Guard Output -> Reply -> Kill Sandbox

Pattern 2: Multi-turn conversation with pause/resume

First turn: User Message -> Create Claude Code Sandbox -> Store sandbox_id -> Send Sandbox Input (claude_code) -> Guard Output -> Reply -> Pause Sandbox

Subsequent turns: User Message -> Send Sandbox Input (claude_code, same sandbox_id, resume_session=true) -> Guard Output -> Reply -> Pause Sandbox

Final turn (detected by Dify logic): ... -> Reply -> Kill Sandbox

Pattern 3: Next.js development with Claude Code

Create Next.js Sandbox -> Store sandbox_id -> Install Packages (claude_code_latest) -> Send Sandbox Input (claude_code, "modify the project...") -> Guard Output -> Reply

Pattern 4: Pre-built template for fast startup

One-time setup: Build Template (with git repo, packages) -> Store template alias

Every conversation: Create Sandbox (template_alias=your-template) -> Send Sandbox Input -> ...

Pricing Notes

E2B bills per second for running sandboxes. Paused sandboxes preserve state without running compute costs.

  • CPU: $0.000014/s per vCPU (2 vCPU default = $0.000028/s)
  • Memory: $0.0000045/GiB/s
  • Storage: 10 GiB included (Hobby), 20 GiB included (Pro)

Practical guidance: Use Pause Sandbox between interactions to stop paying for idle compute. A 30-minute running sandbox with 2 vCPU and 512 MiB RAM costs about $0.05 for the compute plus $0.004 for memory. Pausing reduces that to near zero between interactions.

Reference

  • E2B Sandbox Lifecycle
  • E2B Template Building
  • E2B Template Aliases
  • E2B Filesystem
  • E2B Persistence and Pausing
  • E2B Pricing
  • E2B Rate Limits
  • Claude Code Documentation
  • Claude Code Settings
  • Claude Code Permissions

Contact

Email: lysonober@gmail.com