Context
The Session-160 security review of #5 flagged that the agent LLM calls have no client-side request timeout. The #5 runner now bounds the pipeline wait (_AGENT_TIMEOUT_SECONDS, pipeline._classify_concurrently) — a hung vendor call degrades to None (the normal agent-failure path), so the CLI no longer hangs.
What remains: a timed-out agent's worker thread is abandoned, not reaped — it runs until the underlying vendor call returns on its own. For a one-shot CLI this dies with the process (harmless). Once this runner is wrapped in a long-lived service (it is explicitly framed as the LangGraph on-ramp), repeated timeouts would leak threads.
Fix
Set a bounded timeout / request_timeout + max_retries on ChatGoogleGenerativeAI and ChatAnthropic in agents.py::_make_client. A timed-out call then raises inside the agent's except Exception → degrades to None → the existing single-agent-failure path handles it.
Must be verified against the pinned client version — the live extras (langchain_anthropic / langchain_google_genai) are optional and not installed in CI, so _make_client is not exercised there. Do not add the kwargs blind; confirm the parameter names against the installed versions first.
Priority
Low — availability / service-hardening, not integrity. No effect on the current CLI (the runner-level bound already prevents the pipeline hang). Belongs with the eventual service-wrapping work.
Related ADRs
- Parent ADR-012 (graceful degradation — agent failure →
None, verdict routes to human)
- Parent ADR-010 (local → hosted deployment; the service context where thread reaping matters)
- Local decision records:
0008 (runnable agent layer, agent-failure contract), 0010 (runner bounds the fan-out; names this as the follow-up)
Context
The Session-160 security review of #5 flagged that the agent LLM calls have no client-side request timeout. The #5 runner now bounds the pipeline wait (
_AGENT_TIMEOUT_SECONDS,pipeline._classify_concurrently) — a hung vendor call degrades toNone(the normal agent-failure path), so the CLI no longer hangs.What remains: a timed-out agent's worker thread is abandoned, not reaped — it runs until the underlying vendor call returns on its own. For a one-shot CLI this dies with the process (harmless). Once this runner is wrapped in a long-lived service (it is explicitly framed as the LangGraph on-ramp), repeated timeouts would leak threads.
Fix
Set a bounded
timeout/request_timeout+max_retriesonChatGoogleGenerativeAIandChatAnthropicinagents.py::_make_client. A timed-out call then raises inside the agent'sexcept Exception→ degrades toNone→ the existing single-agent-failure path handles it.Must be verified against the pinned client version — the live extras (
langchain_anthropic/langchain_google_genai) are optional and not installed in CI, so_make_clientis not exercised there. Do not add the kwargs blind; confirm the parameter names against the installed versions first.Priority
Low — availability / service-hardening, not integrity. No effect on the current CLI (the runner-level bound already prevents the pipeline hang). Belongs with the eventual service-wrapping work.
Related ADRs
None, verdict routes to human)0008(runnable agent layer, agent-failure contract),0010(runner bounds the fan-out; names this as the follow-up)