Skip to content

bug: Workspace chat turns are hard-capped at 300s, ignoring the agent's configured execution timeout #2214

Description

@vybe

Summary

A Workspace chat turn is hard-capped at 300 seconds and dies there. The cap is a module constant with no setting, no env var and no per-agent override — and it silently overrides the agent's own configured execution timeout, which defaults to 3600s and is operator-settable from 60–7200s.

Context

Reported from live use of /workspace: longer turns die after ~5 minutes and there is no way to regulate it.

src/backend/client_portal/service.py:

PORTAL_TURN_TIMEOUT_SECONDS = 300

That constant is passed verbatim as timeout_seconds= into run_resumable_turn for every Workspace turn. Meanwhile the platform already has a first-class per-agent bound — agent_ownership.execution_timeout_seconds (TIMEOUT-001, default 3600s, GET/PUT /api/agents/{name}/timeout, range 60–7200) — which the Workspace path never consults. So an operator who deliberately raised an agent's timeout to an hour still gets 5 minutes in the surface people actually work in, and nothing tells them why.

Two things to keep intact while changing the number, both load-bearing and both documented in that file:

Raising the default alone is not the whole fix — an operator with a long-running agent needs the bound to follow that agent, and a client watching a 20-minute turn needs the surface to stay honest about it rather than presenting a dead spinner.

Acceptance Criteria

  • The Workspace turn timeout is materially larger than 300s by default, and the value is justified in the code comment rather than picked arbitrarily
  • The bound respects the agent's configured execution_timeout_seconds rather than a constant that silently overrides it (clamped to a sane Workspace ceiling if one is wanted)
  • PORTAL_ATTEMPT_CEILING_SECONDS, PORTAL_MAX_TURN_SECONDS and PORTAL_INFLIGHT_TTL_SECONDS stay derived from the turn bound — no constant left sized against the old 300s
  • The client's wait ceiling stays derived from the server's bound (no independent number to drift)
  • A turn that legitimately runs past the old cap completes and renders instead of dying; the existing tests/unit/test_2133_* pins (or their successors) still hold against the real constants
  • A turn that does hit the new bound fails with an honest, user-readable reason rather than a silent stop
  • If the bound becomes configurable, it is surfaced where operators already set the agent timeout — not .env-only — with a named validation error on out-of-range input

Technical Notes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions