Notes from a 2 AM On-Call: Silent Agent Timeout in pstack-claude's Cursor Harness
Notes from a 2 AM On-Call: Silent Agent Timeout in pstack-claude's Cursor Harness The Failure Symptom [ 2026-01-14T02:17:33Z] Agent workflow started: refactor_auth_middleware [ 2026-01-14T02:18:03Z] [ 2026-01-14T02:18:04Z] Next workflow queued: update_tests No error. No traceback. No stderr. The Cu
[ 2026-01-14T02:17:33Z] Agent workflow started: refactor_auth_middleware [ 2026-01-14T02:18:03Z] <no output> [ 2026-01-14T02:18:04Z] Next workflow queued: update_tests Enter fullscreen mode Exit fullscreen mode No error. No traceback. No stderr. The Cursor agent runner in michael-denyer/pstack-claude just...stopped executing after exactly 30 seconds. The next workflow in the queue picked up immediately, but the refactor job silently dropped. Production requests from our FastAPI gateway started piling up in Redis, and Sentry showed zero exceptions.
This wasn't a crash—it was a silent timeout cliff.
Every Cursor and agent automation tutorial tells you to configure request_timeout in your IDE settings or.cursorrules. We had that set to 120 seconds. The official pstack examples show:
{ "cursor.timeout": 120000, "cursor.maxTokens": 8192 } Enter fullscreen mode Exit fullscreen mode Looks fine, right? When I tested the same refactor workflow manually through Cursor's UI, it completed in 45 seconds without issue. But when triggered programmatically via pstack-claude's PotentoCursorAgent harness under concurrent load (6 parallel workflows), it hard-stopped at 30s.
The problem? Nested timeout inheritance in agent execution contexts.
Digging through michael-denyer/pstack-claude's agent runner implementation, I found this in src/agents/cursor_agent.py:
# Before: Implicit default from httpx client response = await self. client. post ( f " { self. base_url } /v1/chat/completions ", json = payload, # No explicit timeout—inherits httpx default of 30s ) Enter fullscreen mode Exit fullscreen mode The cursor.timeout setting in IDE config controls the UI streaming timeout. It has zero effect on the programmatic HTTP client timeout used by pstack's agent harness when calling the LLM gateway (in our case, routed through https://b-lost.com/v1 for multi-provider fallback).
Under load, our refactor workflow hit a complex dependency graph that triggered 4 sequential sub-agent calls. Each call took ~8 seconds, totaling 32 seconds—just past httpx's 30s default. The client silently closed the connection, and pstack's error handling swallowed the timeout exception without logging.
Three-line patch to src/agents/cursor_agent.py:
import httpx # Explicit timeout for programmatic agent execution self. client = httpx. AsyncClient ( timeout = httpx. Timeout ( 120.0, connect = 10.0 ), limits = httpx. Limits ( max_keepalive_connections = 10 ) ) response = await self. client. post ( f " { self. base_url } /v1/chat/completions ", json = payload, ) Enter fullscreen mode Exit fullscreen mode We also added explicit error surfacing:
try: response = await self. client. post response. raise_for_status () except httpx. TimeoutException as e: logger. error ( f " Agent timeout after { e. request. extensions [ ' timeout ' ] }: { payload [ ' messages ' ][ - 1 ][ ' content ' ][: 100 ] } " ) raise Enter fullscreen mode Exit fullscreen mode After deploying this patch, the refactor workflow completed in 38 seconds, and our Redis queue depth dropped to zero within 5 minutes.
Before the fix (6 concurrent workflows over 10 minutes):
Never rely on implicit timeouts in production agent harnesses.
When integrating pstack-claude (or any LLM workflow orchestrator) with external APIs—especially multi-provider relay gateways like B-Lost—set explicit httpx.Timeout values tied to your SLA budget, not client library defaults. If your P95 workflow execution is 45 seconds, your HTTP timeout should be at least 90 seconds with connection timeout clamped to 10s.
And always, always log timeout exceptions with enough context to reconstruct the failing request payload.
Full production-grade config for pstack-claude's Cursor agent runner:
from httpx import AsyncClient, Timeout, Limits agent_client = AsyncClient ( base_url = " https://b-lost.com/v1 ", # Multi-provider relay timeout = Timeout ( 120.0, connect = 10.0 ), limits = Limits ( max_connections = 20, max_keepalive_connections = 10, keepalive_expiry = 30.0 ), headers = { " X-Workflow-ID ": workflow_id } # For trace correlation ) Enter fullscreen mode Exit fullscreen mode This configuration survived our Black Friday load test: 2,400 concurrent agent workflows over 6 hours with zero silent timeouts.
You're hitting this same failure mode if:
If you see these symptoms in michael-denyer/pstack-claude or similar agent harnesses (Antigravity, Claude Code, Codex variants), audit every HTTP client instantiation for missing explicit timeout configuration.
The 2 AM pages stopped after this fix shipped. Highly recommend the same audit for any production LLM orchestration stack.