Skip to content

feat: add global timeout to terminal bench - #2826

Open
elisam0 wants to merge 3 commits into
NVIDIA-NeMo:mainfrom
elisam0:elisam0/add-global-timeout-anyterminal
Open

feat: add global timeout to terminal bench#2826
elisam0 wants to merge 3 commits into
NVIDIA-NeMo:mainfrom
elisam0:elisam0/add-global-timeout-anyterminal

Conversation

@elisam0

@elisam0 elisam0 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds an optional global_agent_timeout config field to AnyTerminalAgentConfig. When set, it overrides the per-task agent_timeout_sec from the dataset for every task, instead of the current default of a per-task timeout falling back to tb_agent_timeout.

This is useful for harness-optimization evals where we want longer traces to observe model behavior — e.g. when running slower models, per-task dataset timeouts can cut off runs before enough signal is collected. Setting global_agent_timeout lets a single config value apply uniformly across all tasks without editing the dataset.

Default behavior (per-task timeout takes precedence) is unchanged when global_agent_timeout is left unset (None).

Checklist

  • I have read the contributing guidelines.
  • The change is focused; unrelated "drive-by" edits are tracked as separate issues/PRs.
  • Tests added or updated and pass locally, or N/A for docs-only / non-code changes (so CI unit/server checks pass when applicable).
  • Pre-commit checks pass locally (pre-commit run --all-files) (so CI lint/format/copyright pass).
  • All commits have DCO sign-off (git commit -s) (so the DCO check passes).

Signed-off-by: Elisa Martinez Abad <elisam@nvidia.com>
@copy-pr-bot

copy-pr-bot Bot commented Aug 27, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

Signed-off-by: Elisa Martinez Abad <elisam@nvidia.com>
@elisam0

elisam0 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

/claude review

@claude

claude Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

SHIP — LGTM, no reliability concerns.

Small, additive change adding an opt-in global_agent_timeout config knob to AnyTerminalAgentConfig.

  • global_agent_timeout: Optional[int] = None lives on a Pydantic config model where siblings (tb_agent_timeout: int = 1800) already carry Python defaults — no TypedDict/YAML-defaults convention violation.
  • Override guard uses is not None, so global_agent_timeout=0 is honored as an explicit override rather than silently falling through to the per-task path. Correct.
  • Default None preserves the prior per-task-timeout behavior exactly; nothing changes for existing configs.
  • No verifier, scoring, async, or public-API surface touched. Eval/verifier timeout path is untouched.
  • Tests cover all three branches (per-task default, global-overrides-per-task, global-without-per-task) and assert real behavior via _setup_params.

Optional NOTE (author's call): the new field isn't documented in any exemplar YAML under configs/; the sibling timeouts aren't either, so this is consistent, not a regression.

@github-actions github-actions Bot added the sla:triage-overdue Review assignment is over the one-business-day SLA label Aug 28, 2026
config_overrides = {}
if problem_info.get("agent_timeout_sec"):
if self.config.global_agent_timeout is not None:
config_overrides["tb_agent_timeout"] = self.config.global_agent_timeout

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This can be set higher than the container's own lifetime, and nothing checks that. The sandbox starts with ttl_s=cfg.tb_sandbox_ttl (default 7200) at L582. In the Docker provider, that makes PID 1 a literal sleep 7200 with --rm (provider.py:337-345), so the container is deleted at t=7200 regardless of the agent timeout.

The tests use global_agent_timeout=7200, exactly equal to the TTL. That leaves no room for startup, staging, or the 300s eval afterward, so the container can disappear before the run finishes. The config comment also points to 12000 as the TB2 max, which is well beyond the TTL.

anyswe_agent derives the TTL instead: swebench_agent_timeout + swebench_tests_timeout + 600 (anyswe_agent/app.py:335). Could we do the same here, or fail at config time if global_agent_timeout + tb_eval_timeout >= tb_sandbox_ttl?

if result.return_code != 0:
detail = result.stderr or result.stdout or ""
print(f"[{cfg.task_name}] agent exit {result.return_code}: {detail[-2000:]}", flush=True)
return time.time() - t0, result.error_type == "timeout"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When the container is killed by its TTL, we score the task as a real zero instead of masking it.

exec on a removed container returns error_type="sandbox" and does not raise. This line and L570 only check for "timeout", while sandbox_failed is only set in the except block, which never runs. As a result, mask_sample at L628 stays False, and a dead container looks like a genuine failed attempt.

anyswe_agent checks result.error_type in ("timeout", "sandbox") (app.py:411, 458). Maybe worth matching that behavior here

agent_runtime_source: str = "auto"
tb_agent_timeout: int = 1800
# When set, overrides the per-task agent_timeout_sec from the dataset for every task.
global_agent_timeout: Optional[int] = None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could this use Field(default=None, gt=0)?

Right now, global_agent_timeout: 0 passes validation, and the check on L777 is is not None, so 0 goes straight through as the agent timeout and every task fails immediately with an empty trace. The old code used a truthiness check, which effectively ignored 0.

@github-actions github-actions Bot removed the sla:triage-overdue Review assignment is over the one-business-day SLA label Aug 31, 2026
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