> ## Documentation Index
> Fetch the complete documentation index at: https://e2b-sandbox-agent-sdk-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# AutoResume

Many workloads don't need a sandbox running all the time, but when they do need it, it should just work, whether it was paused or not.

`AutoResume` handles this automatically: a paused sandbox wakes up when activity arrives, so your code does not have to check or manage sandbox state.
Configure it through the `lifecycle` object when creating a sandbox.

## Configure lifecycle on create

<CodeGroup>
  ```js JavaScript & TypeScript theme={null}
  import { Sandbox } from 'e2b'

  const sandbox = await Sandbox.create({
    timeoutMs: 10 * 60 * 1000,
    lifecycle: {
      onTimeout: 'pause',
      autoResume: true, // resume when activity arrives
    },
  })
  ```

  ```python Python theme={null}
  from e2b import Sandbox

  sandbox = Sandbox.create(
      timeout=10 * 60,
      lifecycle={
          "on_timeout": "pause",
          "auto_resume": True,  # resume when activity arrives
      },
  )
  ```
</CodeGroup>

## Lifecycle options

* `onTimeout` / `on_timeout`
  * `kill` (default): sandbox is terminated when timeout is reached
  * `pause`: sandbox is paused when timeout is reached
* `autoResume` / `auto_resume`
  * `false` (default): paused sandboxes do not auto-resume
  * `true`: paused sandboxes auto-resume on activity
  * `true` is valid only when `onTimeout`/`on_timeout` is `pause`

## Behavior summary

* Default behavior is equivalent to `onTimeout: "kill"` with `autoResume: false`.
* `onTimeout: "pause"` with `autoResume: false` gives auto-pause without auto-resume.
* `onTimeout: "pause"` with `autoResume: true` gives auto-pause with auto-resume.
* [`Sandbox.connect()`](/docs/sandbox/connect) can still be used to resume a paused sandbox manually.

If you use `autoResume: false`, resume explicitly with [`Sandbox.connect()`](/docs/sandbox/connect).

## Timeout after auto-resume

When a sandbox auto-resumes, it restarts with a **5-minute minimum timeout**. If you originally created the sandbox with a longer timeout, that value carries over.
The countdown begins from the moment the sandbox resumes, not from when it was first created.

For example, if you create a sandbox with a 2-minute timeout:

1. The sandbox runs for 2 minutes, then pauses.
2. Activity arrives and the sandbox auto-resumes.
3. A 5-minute timeout starts (the 5-minute minimum applies because the original timeout was shorter).
4. If no further activity resets the timeout, the sandbox pauses again after 5 minutes.

If you create a sandbox with a 1-hour timeout, the auto-resume timeout will also be 1 hour, since it exceeds the 5-minute minimum.

This cycle repeats every time the sandbox auto-resumes — the lifecycle configuration (`onTimeout: "pause"` + `autoResume: true`) is persistent across pause/resume cycles.

<Note>
  You can change the timeout after the sandbox resumes by calling `setTimeout`/`set_timeout`. See [Change sandbox timeout during runtime](/docs/sandbox#change-sandbox-timeout-during-runtime).
</Note>

## What counts as activity

Auto-resume is triggered by the sandbox activity - that's both HTTP traffic and controlling the sandbox from the SDK.

That includes SDK operations like:

* `sandbox.commands.run(...)`
* `sandbox.files.read(...)`
* `sandbox.files.write(...)`
* opening a tunneled app URL or sending requests to a service running inside the sandbox

If a sandbox is paused and `autoResume` is enabled, the next supported operation resumes it automatically. You do not need to call [`Sandbox.connect()`](/docs/sandbox/connect) first.

### SDK example: pause, then read a file

<CodeGroup>
  ```js JavaScript & TypeScript theme={null}
  import { Sandbox } from 'e2b'

  const sandbox = await Sandbox.create({
    timeoutMs: 10 * 60 * 1000,
    lifecycle: {
      onTimeout: 'pause',
      autoResume: true,
    },
  })

  await sandbox.files.write('/home/user/hello.txt', 'hello from a paused sandbox')
  await sandbox.pause()

  const content = await sandbox.files.read('/home/user/hello.txt')
  console.log(content)
  console.log(`State after read: ${(await sandbox.getInfo()).state}`)
  ```

  ```python Python theme={null}
  from e2b import Sandbox

  sandbox = Sandbox.create(
      timeout=10 * 60,
      lifecycle={
          "on_timeout": "pause",
          "auto_resume": True,
      },
  )

  sandbox.files.write("/home/user/hello.txt", "hello from a paused sandbox")
  sandbox.pause()

  content = sandbox.files.read("/home/user/hello.txt")
  print(content)
  print(f"State after read: {sandbox.get_info().state}")
  ```
</CodeGroup>

## Use cases

### Web and dev/preview servers

Use `onTimeout: "pause"` + `autoResume: true` so inbound traffic can wake a paused sandbox automatically.
This works for both:

* Basic web/API servers
* Dev or preview servers you open occasionally

<CodeGroup>
  ```js JavaScript & TypeScript theme={null}
  import { Sandbox } from 'e2b'

  const sandbox = await Sandbox.create({
    timeoutMs: 10 * 60 * 1000,
    lifecycle: {
      onTimeout: 'pause',
      autoResume: true,
    },
  })

  await sandbox.commands.run(
    `python3 -m pip -q install 'flask>=2.2'`
  )

  await sandbox.files.write(
    '/home/user/app.py',
    [
      'from flask import Flask',
      'app = Flask(__name__)',
      '@app.route("/")',
      'def hello():',
      '    return "Hello, World!"',
      'app.run(host="0.0.0.0", port=3000)',
      '',
    ].join('\n')
  )

  await sandbox.commands.run(
    'python3 -u /home/user/app.py > /home/user/flask.log 2>&1',
    { background: true }
  )

  await new Promise((resolve) => setTimeout(resolve, 1000))

  const previewHost = sandbox.getHost(3000)
  console.log(`Preview URL: https://${previewHost}`)

  console.log(`Status before pause: ${(await sandbox.getInfo()).state}`)
  await sandbox.pause()
  console.log(`Status after pause: ${(await sandbox.getInfo()).state}`)
  ```

  ```python Python theme={null}
  import time

  from e2b import Sandbox

  sandbox = Sandbox.create(
      timeout=10 * 60,
      lifecycle={
          "on_timeout": "pause",
          "auto_resume": True,
      },
  )

  sandbox.commands.run("python3 -m pip -q install 'flask>=2.2'")

  sandbox.files.write(
      "/home/user/app.py",
      'from flask import Flask\n'
      'app = Flask(__name__)\n'
      '@app.route("/")\n'
      'def hello():\n'
      '    return "Hello, World!"\n'
      'app.run(host="0.0.0.0", port=3000)\n'
  )

  sandbox.commands.run(
      "python3 -u /home/user/app.py > /home/user/flask.log 2>&1",
      background=True,
  )

  time.sleep(1)

  preview_host = sandbox.get_host(3000)
  print(f"Preview URL: https://{preview_host}")

  print(f"Status before pause: {sandbox.get_info().state}")
  sandbox.pause()
  print(f"Status after pause: {sandbox.get_info().state}")
  ```
</CodeGroup>

### Agent/tool execution

For queued tasks or tool calls, create once and keep using the same sandbox handle. If it is paused, it will auto-resume when you run the next command.

<CodeGroup>
  ```js JavaScript & TypeScript theme={null}
  import { Sandbox } from 'e2b'

  // One-time setup
  const sandbox = await Sandbox.create({
    timeoutMs: 5 * 60 * 1000,
    lifecycle: {
      onTimeout: 'pause',
      autoResume: true,
    },
  })

  // Later: called for each agent/tool task
  async function runToolTask(command) {
    const result = await sandbox.commands.run(command)
    return result.stdout
  }

  console.log(await runToolTask('python -c "print(2 + 2)"'))
  ```

  ```python Python theme={null}
  from e2b import Sandbox

  # One-time setup
  sandbox = Sandbox.create(
      timeout=5 * 60,
      lifecycle={
          "on_timeout": "pause",
          "auto_resume": True,
      },
  )

  # Later: called for each agent/tool task
  def run_tool_task(command: str) -> str:
      result = sandbox.commands.run(command)
      return result.stdout

  print(run_tool_task('python -c "print(2 + 2)"'))
  ```
</CodeGroup>

### Per-user sandboxes

For multi-tenant apps, keep a map of sandbox IDs by user. On each request, connect to the user's existing sandbox (which auto-resumes if paused) or create a new one.

<CodeGroup>
  ```js JavaScript & TypeScript theme={null}
  import { Sandbox } from 'e2b'

  const userSandboxes = new Map() // userId → Sandbox

  async function getSandbox(userId) {
    let sandbox = userSandboxes.get(userId)

    if (!sandbox) {
      sandbox = await Sandbox.create({
        timeoutMs: 5 * 60 * 1000,
        lifecycle: {
          onTimeout: 'pause',
          autoResume: true,
        },
      })
      userSandboxes.set(userId, sandbox)
    }

    return sandbox
  }

  // On each user request (auto-resumes if paused)
  const sandbox = await getSandbox('user-123')
  const result = await sandbox.commands.run('echo "Hello from your sandbox"')
  console.log(result.stdout)
  ```

  ```python Python theme={null}
  from e2b import Sandbox

  user_sandboxes: dict[str, Sandbox] = {}  # user_id → Sandbox

  def get_sandbox(user_id: str) -> Sandbox:
      if user_id not in user_sandboxes:
          user_sandboxes[user_id] = Sandbox.create(
              timeout=5 * 60,
              lifecycle={
                  "on_timeout": "pause",
                  "auto_resume": True,
              },
          )

      return user_sandboxes[user_id]

  # On each user request (auto-resumes if paused)
  sandbox = get_sandbox("user-123")
  result = sandbox.commands.run('echo "Hello from your sandbox"')
  print(result.stdout)
  ```
</CodeGroup>

## Cleanup

Auto-resume is persistent, meaning if your sandbox resumes and later times out again, it will pause again.
Each time the sandbox resumes, it gets a fresh timeout (at least 5 minutes, or longer if the original creation timeout exceeds that) — so the sandbox keeps cycling between running and paused as long as activity arrives.
If you call `.kill()`, the sandbox is permanently deleted and cannot be resumed.
