Skip to content

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

Open
graceqi-g wants to merge 4 commits into
mainfrom
feat/prompt-timeout-seconds
Open

Add support for per-prompt execution timeout (prompt_timeout_seconds)#493
graceqi-g wants to merge 4 commits 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

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.

TAG=agy
CONV=4229555b-deeb-44bb-a481-c751dab59476
@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

@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

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