How to Handle Sandbox Timeouts and Extend Them in Open Agents
To handle sandbox timeouts in Open Agents, use the extendTimeout method on the VercelSandbox instance before the proactive timeout expires, and register an onTimeout hook to gracefully save state before the SDK enforced hard limit.
Open Agents executes user code inside isolated Vercel Sandboxes—Firecracker micro-VMs managed by the @vercel/sandbox SDK. Understanding how to handle sandbox timeouts and extend them in Open Agents is critical for running long-running workflows without unexpected termination. The system implements a dual-layer timeout strategy: a proactive timeout tracked internally by the VercelSandbox class and a hard SDK timeout enforced by Vercel.
Understanding the Sandbox Timeout Architecture
Proactive vs. Hard SDK Timeouts
Every sandbox maintains two distinct timeout mechanisms. The proactive timeout (_timeout) is calculated when the sandbox is created and stored as an expiration timestamp (_expiresAt). This internal timer fires slightly before the SDK's hard limit, giving your application a window to run cleanup logic. The hard SDK timeout is capped at 5 hours (MAX_SDK_TIMEOUT_MS) and cannot be exceeded.
Key Timeout Constants
In packages/sandbox/vercel/sandbox.ts, the timeout logic is governed by these constants:
| Constant | Value | Purpose |
|---|---|---|
TIMEOUT_BUFFER_MS |
30_000 |
30-second safety buffer before the SDK's beforeStop hook fires. |
MAX_SDK_TIMEOUT_MS |
18_000_000 |
Maximum allowed SDK timeout (5 hours). |
MAX_PROACTIVE_TIMEOUT_MS |
MAX_SDK_TIMEOUT_MS - TIMEOUT_BUFFER_MS |
Highest proactive timeout safely requestable (4 hours 59 minutes 30 seconds). |
DEFAULT_RECONNECT_TIMEOUT_MS |
300_000 |
Fallback reconnection timeout (5 minutes) when session metadata is unavailable. |
When VercelSandbox.create is called, the user-provided timeout is clamped to MAX_PROACTIVE_TIMEOUT_MS, and the SDK timeout is calculated by adding the buffer:
// From packages/sandbox/vercel/sandbox.ts
const effectiveTimeout = Math.min(timeout, MAX_PROACTIVE_TIMEOUT_MS);
const sdkTimeout = effectiveTimeout + TIMEOUT_BUFFER_MS;
How to Extend Sandbox Timeouts
Using the extendTimeout Method
The VercelSandbox class exposes an async extendTimeout method that forwards the request to the underlying SDK session and updates internal state. This is the primary method for handling sandbox timeouts and extending them in Open Agents during long-running operations.
// From packages/sandbox/vercel/sandbox.ts (lines 325-363)
async extendTimeout(additionalMs: number): Promise<{ expiresAt: number }> {
if (this.isStopped) throw new Error("Cannot extend timeout on stopped sandbox");
if (this._expiresAt === undefined) throw new Error("Timeout tracking not enabled");
if (typeof this.session.extendTimeout !== "function") {
throw new Error("extendTimeout is not supported by this version of @vercel/sandbox");
}
await this.session.extendTimeout(additionalMs); // SDK call
this._expiresAt += additionalMs; // update internal state
this.rescheduleProactiveStop(); // restart the timer
// invokes optional onTimeoutExtended hook
return { expiresAt: this._expiresAt };
}
The method performs three critical actions:
- Validates state — Ensures the sandbox is running and timeout tracking is enabled.
- Updates the SDK session — Calls the underlying
@vercel/sandboxSDK to extend the hard limit. - Reschedules proactive cleanup — Recalculates
msUntilTimeoutand restarts the internaltimeoutTimerto fire before the new expiry.
Timeout Extension Limits
While you can call extendTimeout multiple times, the total duration cannot exceed the SDK's hard limit of 5 hours (MAX_SDK_TIMEOUT_MS). Each extension request adds time to the existing expiry, not the original creation time. If you attempt to extend a stopped sandbox, the method throws "Cannot extend timeout on stopped sandbox".
Handling Timeout Events Gracefully
Registering the onTimeout Hook
To handle sandbox timeouts gracefully in Open Agents, register the onTimeout hook in your sandbox configuration. This hook fires when the proactive timer triggers—approximately 30 seconds before the SDK forces termination.
const sandbox = await connectVercelSandbox({
name: "critical-workflow",
timeout: 10 * 60_000, // 10 minutes
hooks: {
onTimeout: async (sb) => {
console.log("Proactive timeout triggered");
await sb.snapshot(); // Persist state before forced stop
},
},
});
The onTimeout hook is your opportunity to snapshot state, flush logs, or notify external systems. It does not prevent the sandbox from stopping; it merely provides a cleanup window.
Reconnecting After Disconnection
If your application disconnects from a sandbox, you can reconnect using VercelSandbox.connect. The library attempts to infer the remaining proactive timeout from session metadata using getRemainingTimeoutFromSession. If metadata is unavailable, it defaults to DEFAULT_RECONNECT_TIMEOUT_MS (5 minutes).
const resumed = await connectVercelSandbox({
sandboxName: "critical-workflow",
resume: true,
});
Once reconnected, you can immediately call extendTimeout to push out the expiry if the remaining time is insufficient.
Practical Implementation Example
Below is a complete pattern for handling sandbox timeouts and extending them in Open Agents during a long-running build process:
import { connectVercelSandbox } from "packages/sandbox/vercel";
// 1. Create with initial 10-minute timeout
const sandbox = await connectVercelSandbox({
name: "build-pipeline",
timeout: 10 * 60_000,
hooks: {
onTimeout: async (sb) => {
console.log("Sandbox expiring – creating snapshot…");
await sb.snapshot();
},
onTimeoutExtended: async (sb, added) => {
console.log(`Extended by ${added}ms, new expiry: ${new Date(sb.expiresAt!).toISOString()}`);
},
},
});
// 2. Execute long-running command
await sandbox.exec("npm run build:heavy", "/", 15 * 60_000);
// 3. Check remaining time and extend if needed
const remaining = sandbox.expiresAt! - Date.now();
if (remaining < 5 * 60_000) {
await sandbox.extendTimeout(5 * 60_000); // Add 5 more minutes
}
// 4. Finalize
const { snapshotId } = await sandbox.snapshot();
console.log("Build complete, snapshot saved:", snapshotId);
Summary
- Open Agents uses Vercel Sandboxes (Firecracker micro-VMs) with a dual-timeout system: a proactive internal timer and a hard 5-hour SDK limit.
extendTimeoutis the primary method for extending sandbox lifetimes; it updates both the SDK session and the internaltimeoutTimerviarescheduleProactiveStop.- Timeout constants defined in
packages/sandbox/vercel/sandbox.tsenforce a 30-second safety buffer (TIMEOUT_BUFFER_MS) and cap proactive timeouts at ~4 hours 59 minutes (MAX_PROACTIVE_TIMEOUT_MS). - Hooks (
onTimeout,onTimeoutExtended) provide graceful handling of expiration events, allowing state snapshots before forced termination. - Reconnection uses
DEFAULT_RECONNECT_TIMEOUT_MS(5 minutes) as a fallback when session metadata is unavailable, ensuring you can still callextendTimeoutafter reconnecting.
Frequently Asked Questions
How long can a sandbox run before it times out?
The maximum runtime is 5 hours (18,000,000ms), enforced by the @vercel/sandbox SDK. While you can extend timeouts repeatedly using extendTimeout, the cumulative duration cannot exceed this hard limit defined in MAX_SDK_TIMEOUT_MS.
What happens if I don't extend the timeout before it expires?
If you do not call extendTimeout, the sandbox enters a timeout phase. First, your onTimeout hook fires (if registered), giving you approximately 30 seconds to snapshot state or clean up. Then the SDK hard-stops the Firecracker micro-VM. Once stopped, you cannot extend the timeout and must reconnect or recreate the sandbox.
Can I extend the timeout after disconnecting and reconnecting?
Yes. When you reconnect using VercelSandbox.connect, the library attempts to restore the remaining timeout from session metadata. If unavailable, it defaults to 5 minutes (DEFAULT_RECONNECT_TIMEOUT_MS). Once the VercelSandbox instance is restored, calling extendTimeout works exactly as it does on a fresh sandbox, provided the session has not already stopped.
What is the TIMEOUT_BUFFER_MS and why is it 30 seconds?
TIMEOUT_BUFFER_MS is a 30,000ms (30-second) safety margin defined in packages/sandbox/vercel/sandbox.ts. It ensures the proactive onTimeout hook fires before the SDK's beforeStop hook, giving your application a guaranteed window to perform graceful shutdown logic. Without this buffer, the SDK might terminate the VM before your cleanup code executes.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →