Codex WebSocket idle retry is hidden until NanoClaw’s 10-minute turn timeout
Summary
A simple Telegram request can remain silent for ten minutes when the Codex Responses WebSocket stalls.
Codex CLI detects its own five-minute WebSocket idle timeout and retries internally, but codex app-server does
not surface that failure to NanoClaw. NanoClaw therefore waits until its fixed ten-minute TURN_TIMEOUT_MS
expires.
Environment
- NanoClaw v2
- Provider:
codex - Codex CLI:
0.138.0 - Model:
gpt-5.4, reasoning efforthigh - Authentication: API key through OneCLI
- Channel: Telegram
- Linux/systemd
- Upstream checked:
mainat53ea1e8b,providersatefc8eff4
Reproduction observed
- Send a simple Telegram request requiring a small workspace edit.
- NanoClaw starts/resumes the Codex thread successfully.
- Codex sends
response.createsuccessfully. - No WebSocket response events arrive for five minutes.
- Codex logs:
stream error: idle timeout waiting for websocket
stream disconnected - retrying sampling request (1/5 ...)- The retry remains inside Codex CLI and is not emitted as an app-server error.
- At ten minutes, NanoClaw emits:
Error: Turn timed out after 600000msNo model output or tool call occurred before the timeout.
Follow-up Telegram messages sent while the turn was stalled were steered into the same active turn, making the bot appear completely stuck.
Relevant implementation
container/agent-runner/src/providers/codex.ts uses:
const TURN_TIMEOUT_MS = 10 * 60 * 1000;
The timeout is fixed wall-clock time. It is not aware of Codex’s internal WebSocket idle timeout or retry state. Timeout errors are also currently emitted with retryable: false.
Expected behavior
NanoClaw should not remain silent for ten minutes after Codex’s transport has already stalled.
Ideally it should:
- Detect prolonged app-server turn inactivity.
- Interrupt the stalled Codex turn.
- Notify the messaging channel promptly.
- Replay automatically only when no assistant output, tool call, or other side effect occurred.
- Queue follow-up messages separately instead of steering them into a stalled turn.
At minimum, the error should explain that the Codex transport stalled and that the original request may need retrying.
Additional context
This appears related to OpenAI Codex issue #19821, where Responses WebSocket failures consume the stream retry budget before HTTP fallback:
https://github.com/openai/codex/issues/19821
A possible short-term mitigation may be disabling WebSocket transport for Codex, but NanoClaw should still have its own activity watchdog and safe recovery behavior.
Source: nanocoai/nanoclaw