Skip to content

Add support for per-prompt execution timeout (prompt_timeout_seconds) - #493

Open
graceqi-g wants to merge 1 commit into
mainfrom
feat/prompt-timeout-seconds
Open

Add support for per-prompt execution timeout (prompt_timeout_seconds)#493
graceqi-g wants to merge 1 commit into
mainfrom
feat/prompt-timeout-seconds

Conversation

@graceqi-g

@graceqi-g graceqi-g commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Supports setting prompt_timeout_seconds across Agent CLI generators (gemini_cli, claude_code, codex_cli, agy_cli) to terminate prompt turns that spin indefinitely. Configurable per scenario JSON, per model YAML, or per run_config YAML.

Order of precedence from highest priority to lowest is scenario, model, then run config.

@graceqi-g
graceqi-g force-pushed the feat/prompt-timeout-seconds branch from 2e3a7e9 to 0c78054 Compare July 14, 2026 19:27
@graceqi-g

Copy link
Copy Markdown
Collaborator Author

/gcbrun

@graceqi-g
graceqi-g marked this pull request as ready for review July 14, 2026 23:26
@prernakakkar-google

Copy link
Copy Markdown
Collaborator

/gcbrun

timed_out = True
proc.kill()
break
line = proc.stdout.readline()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

proc.stdout.readline() is a blocking call. If the subprocess stalls mid-line (never emits a newline) rather than between lines, the timeout check on the while True loop never gets revisited until the next line arrives the timeout is only enforced between lines, not truly wall-clock bounded. Consider using non-blocking reads (e.g., select, a reader thread with a queue, or proc.stdout.readline wrapped with signal.alarm/asyncio) to guarantee the kill happens within timeout regardless of the subprocess's I/O behavior.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added threading.Timer to ensure the timeout is enforced

@graceqi-g
graceqi-g force-pushed the feat/prompt-timeout-seconds branch from 5e97d01 to 3d141aa Compare July 20, 2026 19:18
Comment thread evalbench/test/codex_cli_test.py Fixed
Comment thread evalbench/generators/models/codex_cli.py Fixed
@graceqi-g
graceqi-g force-pushed the feat/prompt-timeout-seconds branch 4 times, most recently from fb3eed0 to bbfa5d2 Compare July 20, 2026 20:11
@graceqi-g

Copy link
Copy Markdown
Collaborator Author

/gcbrun

@graceqi-g
graceqi-g force-pushed the feat/prompt-timeout-seconds branch from bbfa5d2 to aba996d Compare July 20, 2026 20:15
@graceqi-g

Copy link
Copy Markdown
Collaborator Author

/gcbrun

2 similar comments
@graceqi-g

Copy link
Copy Markdown
Collaborator Author

/gcbrun

@prernakakkar-google

Copy link
Copy Markdown
Collaborator

/gcbrun

@prernakakkar-google

Copy link
Copy Markdown
Collaborator

Neither subprocess.run(..., timeout=...) (gemini/claude/agy) nor proc.kill() (codex) kills the process group — only the direct child. These agent CLIs are node-based and routinely fork subprocess trees (MCP servers, tool subprocesses). On timeout, grandchildren can be orphaned and keep running, holding ports/CPU/memory. Across a long eval run with repeated timeouts, this can accumulate

@prernakakkar-google

Copy link
Copy Markdown
Collaborator

subprocess.TimeoutExpired carries the output captured so far on e.stdout / e.stderr, but the handlers hardcode "":

except subprocess.TimeoutExpired:
    return subprocess.CompletedProcess(command, 124, "", f"Error: ...")

This is inconsistent with the Codex path, which preserves stdout_lines. More importantly, it contradicts the existing design intent in agy_cli._run_agy_cli, whose own comment says "a timed-out/errored run still ends in a result event carrying real data" — but with a hard subprocess.run timeout, that stream is thrown away, so the partial trajectory/tool calls before the hang are lost.
This is happening for agy/claude/gemini cli

@graceqi-g
graceqi-g force-pushed the feat/prompt-timeout-seconds branch from e4b4c70 to d05c5a2 Compare July 29, 2026 23:24
Comment thread evalbench/generators/models/agy_cli.py Fixed
Comment thread evalbench/generators/models/codex_cli.py Fixed
Comment thread evalbench/generators/models/claude_code.py Fixed
Comment thread evalbench/generators/models/gemini_cli.py Fixed
@graceqi-g
graceqi-g force-pushed the feat/prompt-timeout-seconds branch from d05c5a2 to 22e4c23 Compare July 29, 2026 23:53
Comment thread evalbench/generators/models/agy_cli.py Fixed
Comment thread evalbench/generators/models/agy_cli.py Fixed
Comment thread evalbench/generators/models/agy_cli.py Fixed
Comment thread evalbench/generators/models/claude_code.py Fixed
Comment thread evalbench/generators/models/claude_code.py Fixed
Comment thread evalbench/generators/models/claude_code.py Fixed
Comment thread evalbench/generators/models/codex_cli.py Fixed
Comment thread evalbench/generators/models/codex_cli.py Fixed
Comment thread evalbench/generators/models/gemini_cli.py Fixed
Comment thread evalbench/generators/models/gemini_cli.py Fixed
@graceqi-g
graceqi-g force-pushed the feat/prompt-timeout-seconds branch from 22e4c23 to 8004d1d Compare July 30, 2026 00:01
@graceqi-g

Copy link
Copy Markdown
Collaborator Author

Neither subprocess.run(..., timeout=...) (gemini/claude/agy) nor proc.kill() (codex) kills the process group — only the direct child. These agent CLIs are node-based and routinely fork subprocess trees (MCP servers, tool subprocesses). On timeout, grandchildren can be orphaned and keep running, holding ports/CPU/memory. Across a long eval run with repeated timeouts, this can accumulate

Added logic to try killing the process group first

subprocess.TimeoutExpired carries the output captured so far on e.stdout / e.stderr, but the handlers hardcode "":

Updated the handlers to output stdout if nonempty and stderr

@graceqi-g
graceqi-g force-pushed the feat/prompt-timeout-seconds branch from 8004d1d to 60f4e3f Compare July 30, 2026 18:48
@graceqi-g

Copy link
Copy Markdown
Collaborator Author

/gcbrun

Supports setting prompt_timeout_seconds across Agent CLI generators (gemini_cli, claude_code, codex_cli, agy_cli) to terminate prompt turns that spin indefinitely. Configurable per scenario JSON, per model YAML, or per run_config YAML.

- Extracts process_timeout context manager and _kill_process_group helper to encapsulate process group termination (start_new_session=True + os.killpg) across all CLI generators.
- Fixes Codex CLI generator to support timeout in CLICommand, create_command, and _run_codex_cli.
- Cleans up unused imports across CLI generators.
- Preserves partial stdout and stream output captured before timeout to retain execution trajectories.

TAG=agy
CONV=4229555b-deeb-44bb-a481-c751dab59476
@graceqi-g
graceqi-g force-pushed the feat/prompt-timeout-seconds branch from 60f4e3f to d6a4e59 Compare August 5, 2026 20:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants