## Timeout Configuration
Set execution timeouts to prevent workflows from hanging indefinitely. Prodigy supports two distinct timeout mechanisms: command-level timeouts for standard workflows and MapReduce-specific timeouts with advanced configuration options.
### Command-Level Timeouts
Command-level timeouts apply to individual commands in standard workflows. These accept numeric values only (in seconds).
**Source**: `src/config/command.rs:384` - `pub timeout: Option<u64>`
```yaml
commands:
# Shell command with 10 minute timeout
- shell: "cargo bench"
timeout: 600
# Claude command with 30 minute timeout
- claude: "/analyze-codebase"
timeout: 1800
# No timeout specified = no limit
- shell: "cargo build"
```
**Real-world examples from workflows:**
From `workflows/complex-build-pipeline.yml:12`:
```yaml
- shell: "cargo bench"
timeout: 600 # 10 minutes
capture_output: "benchmark_results"
```
From `workflows/documentation-drift.yml:15`:
```yaml
- shell: "cargo test --doc"
timeout: 300 # 5 minutes
on_failure:
claude: "/prodigy-debug-test-failure --output ${shell.output}"
```
**Important**: Command-level timeouts only accept numeric values. For environment variable support, use MapReduce timeouts (see below).
### MapReduce Timeouts
MapReduce workflows support more sophisticated timeout configuration with environment variable support and advanced policies.
#### Setup Phase Timeout
Control how long the setup phase can run before timing out.
**Source**: `src/config/mapreduce.rs:148` - Uses `deserialize_optional_u64_or_string`
```yaml
mode: mapreduce
setup:
timeout: 300 # 5 minutes for setup
commands:
- shell: "generate-work-items.sh"
```
**With environment variables:**
```yaml
setup:
timeout: $SETUP_TIMEOUT # References environment variable
commands:
- shell: "cargo build"
```
#### Map Phase Agent Timeout
Set a global timeout for all map agents or configure per-agent policies.
**Source**: `src/config/mapreduce.rs:269` - `pub agent_timeout_secs: Option<String>`
**Simple agent timeout:**
```yaml
map:
agent_timeout_secs: 600 # 10 minutes per agent
agent_template:
- claude: "/process '${item}'"
```
**With environment variable:**
```yaml
map:
agent_timeout_secs: $AGENT_TIMEOUT # Configurable via environment
agent_template:
- claude: "/process '${item}'"
```
#### Advanced Timeout Configuration
For fine-grained control, use `timeout_config` to specify policies, per-command overrides, and timeout actions.
**Source**: `src/cook/execution/mapreduce/timeout.rs:38-63` - `TimeoutConfig` struct
```yaml
map:
timeout_config:
agent_timeout_secs: 600 # Global 10 minute timeout
timeout_policy: hybrid # Apply per-agent with overrides
cleanup_grace_period_secs: 30 # 30s to clean up after timeout
timeout_action: dlq # Send timed-out items to DLQ
enable_monitoring: true # Track timeout metrics
# Per-command timeout overrides
command_timeouts:
claude: 300 # Claude commands: 5 minutes
shell: 60 # Shell commands: 1 minute
claude_0: 600 # First Claude command: 10 minutes
agent_template:
- claude: "/analyze '${item}'" # Uses 300s from command_timeouts
- shell: "test ${item.path}" # Uses 60s from command_timeouts
```
**Real example from tests** (`tests/timeout_integration_test.rs:215-233`):
```yaml
agent_timeout_secs: 600
timeout_config:
timeout_policy: hybrid
cleanup_grace_period_secs: 30
timeout_action: dlq
enable_monitoring: true
command_timeouts:
claude: 300
shell: 60
claude_0: 600
```
#### Timeout Policies
**Source**: `src/cook/execution/mapreduce/timeout.rs:79-88` - `TimeoutPolicy` enum
- **`per_agent`** (default): Timeout applies to entire agent execution
- Agent must complete all commands within timeout
- Best for workflows where total time matters
- **`per_command`**: Timeout applies to each command individually
- Each command gets full timeout duration
- Best for workflows with highly variable command durations
- **`hybrid`**: Per-agent timeout with command-specific overrides
- Commands use `command_timeouts` if specified, otherwise agent timeout
- Most flexible option
**Example: Per-command policy**
```yaml
timeout_config:
agent_timeout_secs: 100
timeout_policy: per_command # Each command gets 100 seconds
```
#### Timeout Actions
**Source**: `src/cook/execution/mapreduce/timeout.rs:91-102` - `TimeoutAction` enum
- **`dlq`** (default): Send item to Dead Letter Queue for retry
- **`skip`**: Skip the item and continue with other items
- **`fail`**: Fail the entire MapReduce job
- **`graceful_terminate`**: Attempt graceful shutdown before force kill
```yaml
timeout_config:
timeout_action: skip # Skip timed-out items instead of retrying
```
#### Default Values
**Source**: `src/cook/execution/mapreduce/timeout.rs` - Default implementations
| `agent_timeout_secs` | 600 (10 minutes) | Global agent timeout |
| `cleanup_grace_period_secs` | 30 seconds | Time for cleanup after timeout |
| `enable_monitoring` | true | Track timeout metrics |
| `timeout_policy` | `per_agent` | Apply timeout to entire agent |
| `timeout_action` | `dlq` | Send timed-out items to DLQ |