# How to Configure Idle Timeout for Agent Runs Using `idleTimeoutSeconds` in Sandcastle

> Learn to configure agent run idle timeout in Sandcastle using idleTimeoutSeconds. Prevent silent agent abortions and control wait times effectively. Get the details now!

- Repository: [Matt Pocock/sandcastle](https://github.com/mattpocock/sandcastle)
- Tags: how-to-guide
- Published: 2026-05-24

---

**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`](https://github.com/mattpocock/sandcastle/blob/main/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`](https://github.com/mattpocock/sandcastle/blob/main/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`](https://github.com/mattpocock/sandcastle/blob/main/src/cli.ts) parses the `--idle-timeout` flag and maps it to the `idleTimeoutSeconds` property. Pass an integer value to override the default:

```bash
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`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) and include `idleTimeoutSeconds` in the options object:

```typescript
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:

1. **Entry Point** – [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) validates the `RunOptions` interface and applies the `DEFAULT_IDLE_TIMEOUT_SECONDS` fallback if needed.

2. **Sandbox Propagation** – [`src/createSandbox.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/createSandbox.ts) receives the `idleTimeoutSeconds` value and passes it into the sandbox lifecycle manager, ensuring subprocesses inherit the same constraint.

3. **Orchestration** – In [`src/Orchestrator.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/Orchestrator.ts), the constructor converts seconds to milliseconds and initializes a watchdog timer. When the timer fires, it throws an `AgentIdleTimeoutError` with 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:**

```bash
sandcastle run ./tasks/build.yml --idle-timeout 30

```

**Programmatic execution with custom timeout:**

```typescript
import { run } from "sandcastle";

await run({
  command: "npm run long-process",
  idleTimeoutSeconds: 900, // 15 minutes
});

```

**Direct sandbox creation (advanced usage):**

```typescript
import { createSandbox } from "sandcastle";

const sandbox = await createSandbox({
  cwd: "/app",
  idleTimeoutSeconds: 45, // 45 seconds
});

```

## Summary

- **`idleTimeoutSeconds`** controls how long Sandcastle waits for agent output before termination.
- The **default is 600 seconds** (10 minutes), defined as `DEFAULT_IDLE_TIMEOUT_SECONDS` in [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts).
- Configure via **CLI** using `--idle-timeout` or programmatically via the **`RunOptions`** interface.
- The **Orchestrator** enforces the limit using a millisecond-based watchdog timer and throws **`AgentIdleTimeoutError`** upon violation.
- The option propagates through **[`createSandbox.ts`](https://github.com/mattpocock/sandcastle/blob/main/createSandbox.ts)** to 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`](https://github.com/mattpocock/sandcastle/blob/main/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`](https://github.com/mattpocock/sandcastle/blob/main/src/createSandbox.ts) when creating custom sandbox instances.