How to Configure Idle Timeout for Agent Runs Using `idleTimeoutSeconds` in Sandcastle
Set idleTimeoutSeconds in your run options or pass --idle-timeout via CLI to control how long Sandcastle waits before aborting silent agents, with a default value of 600 seconds (10 minutes).
The mattpocock/sandcastle repository provides a sandboxed environment for running AI agents, and the idleTimeoutSeconds configuration prevents runs from hanging indefinitely when an agent stops producing output. This parameter defines the maximum duration of silence (in seconds) before the orchestrator forcibly terminates the process and raises an AgentIdleTimeoutError.
What Is idleTimeoutSeconds and Why Use It?
In src/Orchestrator.ts, Sandcastle monitors the stdout and stderr streams of the agent process using a watchdog timer. If no data arrives within the configured window, the orchestrator assumes the agent has stalled. The idleTimeoutSeconds option converts to milliseconds internally (idleTimeoutMs) and triggers a hard stop, freeing compute resources and preventing zombie processes.
- Prevents infinite hangs: Long-running agents with blocking operations won't run forever.
- Resource management: Automatically cleans up sandboxed environments that become unresponsive.
- Configurable per-run: Tune the timeout based on expected task duration.
Default Behavior and Configuration Options
The timeout behavior is defined across multiple layers of the codebase, from CLI argument parsing to the core orchestration logic.
Default Value (600 Seconds)
In src/run.ts, the constant DEFAULT_IDLE_TIMEOUT_SECONDS is set to 600 (10 minutes). If you omit the idleTimeoutSeconds property from your run configuration, this default is applied automatically when constructing the RunOptions object.
CLI Configuration (--idle-timeout)
For command-line usage, src/cli.ts parses the --idle-timeout flag and maps it to the idleTimeoutSeconds property. Pass an integer value to override the default:
sandcastle run path/to/prompt --idle-timeout 300
This sets a 5-minute idle timeout for that specific execution.
Programmatic API Configuration
When calling Sandcastle from TypeScript or JavaScript, import the run function from src/run.ts and include idleTimeoutSeconds in the options object:
import { run } from "sandcastle";
await run({
prompt: "Analyze this codebase",
idleTimeoutSeconds: 120, // 2 minutes
});
How the Idle Timeout Works Under the Hood
The configuration flows through three architectural layers before enforcement:
-
Entry Point –
src/run.tsvalidates theRunOptionsinterface and applies theDEFAULT_IDLE_TIMEOUT_SECONDSfallback if needed. -
Sandbox Propagation –
src/createSandbox.tsreceives theidleTimeoutSecondsvalue and passes it into the sandbox lifecycle manager, ensuring subprocesses inherit the same constraint. -
Orchestration – In
src/Orchestrator.ts, the constructor converts seconds to milliseconds and initializes a watchdog timer. When the timer fires, it throws anAgentIdleTimeoutErrorwith a message suggesting you increase the timeout using--idle-timeout.
The error message format includes the actual seconds elapsed: "Agent idle for X seconds — no output received. Consider increasing the idle timeout with --idle-timeout."
Practical Configuration Examples
Use these patterns to implement idle timeouts in different contexts:
Command-line execution with 30-second timeout:
sandcastle run ./tasks/build.yml --idle-timeout 30
Programmatic execution with custom timeout:
import { run } from "sandcastle";
await run({
command: "npm run long-process",
idleTimeoutSeconds: 900, // 15 minutes
});
Direct sandbox creation (advanced usage):
import { createSandbox } from "sandcastle";
const sandbox = await createSandbox({
cwd: "/app",
idleTimeoutSeconds: 45, // 45 seconds
});
Summary
idleTimeoutSecondscontrols how long Sandcastle waits for agent output before termination.- The default is 600 seconds (10 minutes), defined as
DEFAULT_IDLE_TIMEOUT_SECONDSinsrc/run.ts. - Configure via CLI using
--idle-timeoutor programmatically via theRunOptionsinterface. - The Orchestrator enforces the limit using a millisecond-based watchdog timer and throws
AgentIdleTimeoutErrorupon violation. - The option propagates through
createSandbox.tsto ensure consistent behavior across sandbox lifecycles.
Frequently Asked Questions
What happens when an agent exceeds the idle timeout?
The orchestrator immediately aborts the process and throws an AgentIdleTimeoutError. The error message includes the duration of inactivity and suggests increasing the timeout via the --idle-timeout flag.
Can I disable the idle timeout entirely?
No, Sandcastle requires an idle timeout to prevent resource exhaustion. However, you can set an arbitrarily high value (e.g., 3600 seconds) in idleTimeoutSeconds to accommodate long-running tasks that legitimately produce no output for extended periods.
Why does the orchestrator convert seconds to milliseconds?
src/Orchestrator.ts converts idleTimeoutSeconds to idleTimeoutMs to align with JavaScript's standard setTimeout API, which requires millisecond increments. This conversion happens during orchestrator initialization before the watchdog timer starts.
How do I troubleshoot idle timeout errors in long-running agents?
Increase idleTimeoutSeconds incrementally based on expected task duration, or enable verbose logging to verify the agent is actually sending heartbeat output. If the agent legitimately runs silently, ensure your configuration passes the timeout value through src/createSandbox.ts when creating custom sandbox instances.
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 →