返回指南
疑難排解·2026年10月1日·閱讀約 7 分鐘

NanoClaw Codex 逾時:為何停滯的回合會等待十分鐘,重現結果

Responses WebSocket 停滯、第一次重試被隱藏,以及固定的十分鐘回合計時器:機器人先陷入無聲,接著失敗,而期間傳送的訊息會遺失。已針對替代實作重現,並驗證有效的復原方式。

最後審核於 。

NanoClaw 的 Codex 提供者顯示「Turn timed out after 600000ms」,表示 Codex 的 Responses WebSocket 已停止傳送事件,而 Codex 回報的第一個錯誤,只有在 NanoClaw 固定的十分鐘回合計時器已觸發後才會出現。Codex 會等待閒置串流五分鐘,第一次會靜默重試,只有第二次重試才會回報。我們於 2026 年 10 月 1 日使用 Codex 0.138.0(錯誤報告中的版本)及 0.155.1(NanoClaw 目前固定使用的版本),對接受連線後便保持靜默的本機端點重現了此問題。

這就是 NanoClaw issue #3338 背後的重現案例;檢查時該問題仍開啟,且沒有維護者回覆。關於提供者選項本身,請參閱 NanoClaw API cost and providers;如果機器人因其他原因未在 Telegram 回覆,請參閱 NanoClaw Telegram not responding。

你看到的情況

傳送給機器人的訊息沒有任何回覆——沒有錯誤,也沒有部分回覆——持續十分鐘,然後才出現錯誤。這段期間傳送的訊息似乎會消失。日誌如下:

日誌中的停滯情況
# Codex, inside the agent container (from the issue; our 0.155.1 run printed the same reason)
stream error: idle timeout waiting for websocket
stream disconnected - retrying sampling request (1/5 ...)

# NanoClaw, ten minutes after the message
Error: Turn timed out after 600000ms

重現結果

回合開始後的秒數Codex 0.138.0Codex 0.155.1(NanoClaw 固定使用的版本)
≈1–16透過 WebSocket 傳送第一個請求;沒有回覆預熱請求在 16 秒時由 Codex 關閉;接著才送出實際請求
≈300–316第一個請求逾時;Codex 再次傳送該回合的請求——沒有通知閒置逾時;記錄重試 1——沒有通知
600NanoClaw 的計時器結束回合:「Turn timed out after 600000ms」
≈601–616閒置逾時;記錄「retrying sampling request (1/5)」——仍沒有通知(750 秒內完全沒有通知)第一個 error 通知:「Reconnecting... 2/5」、「idle timeout waiting for websocket」——晚了 15 秒

該端點只是接受 WebSocket 但不傳送任何內容的替身;用戶端則是真正的 Codex 應用程式伺服器二進位檔,使用 NanoClaw 的相同呼叫驅動,並依 NanoClaw 自身的規則判定——任何錯誤通知或已完成的回合都會結束回合,否則由十分鐘計時器結束。

為什麼時間安排如此糟糕

  • Codex 會等待 300 秒 以取得 Responses 串流上的下一個事件,之後才將串流視為失效,並最多重試五次。這些是兩個版本內建 OpenAI 提供者的預設值。
  • Codex 會隱藏第一次 WebSocket 重試。 其重試程式碼在註解中明確說明:「In release builds, hide the first websocket retry notification to reduce noisy transient reconnect messages」;因此前端在第二次重試前都不會收到任何訊息,約十分鐘後才會收到。
  • NanoClaw 給予 Codex 回合的時間正好是 600,000 ms,並在收到任何錯誤通知時結束回合。兩個閒置視窗加上 Codex 的預熱時間超過這段時間,因此在預設設定下,計時器會先結束。

沉默期間傳送的訊息會遺失

NanoClaw 會將活動回合期間收到的後續訊息傳送至 Codex 的 turn/steer。在這次執行中,Codex 將其接受到停滯的回合中,但沒有再向上游傳送任何內容;逾時後恢復執行緒時,歷史記錄中有原始提示,但沒有被引導的訊息。這就是機器人看起來完全卡住的原因:你輸入的所有內容都進入了一個永遠不會完成的回合。

如何脫離這種狀態

已驗證:逾時後,下一則訊息會在新的應用程式伺服器上恢復同一個執行緒——這是 NanoClaw 的行為;在本次執行中,端點回覆後,它於 0.16 秒內完成。因此,請等待逾時,然後重新傳送你在沉默期間輸入的內容。如果下一則訊息也停滯,上游連線仍是問題所在——請檢查 OpenAI 的狀態;如果容器透過代理伺服器連線到 OpenAI,也請確認該代理伺服器是否傳遞 WebSocket 升級(pull request #2672 描述了不會傳遞的代理伺服器;本次未測試)。

可縮短等待時間的選項,已測量但尚未發布:

變更NanoClaw 首次看到的錯誤結果
改用 HTTP/SSE 而非 WebSockets 連線 Codex——PR #3851,已開啟、尚未合併300 s:「Reconnecting... 1/5」通知表示 Codex 將會重試,且確實重試了,但 NanoClaw 會因此結束回合——由十分鐘失敗縮短為五分鐘失敗
Codex stream_idle_timeout_ms = 60,000(WebSockets)136 sNanoClaw 會自行寫入 Codex 的 config.toml,因此這是程式碼變更,不是可以新增的設定

兩者仍會將回合以失敗結束。測量結果指向 NanoClaw 端——將重試中的錯誤視為進度,而非結束,或將回合預算從最後一個真正事件開始計算——但這是根據這些執行結果做出的推論,不是維護者已確認的修正。

常見問題

為什麼 NanoClaw 的 Codex 代理會沉默十分鐘,然後逾時?

因為 Codex 願意回報的第一個故障跡象,出現時 NanoClaw 已經放棄。當 Responses WebSocket 停止傳送事件時,Codex 會等待 300 秒的閒置逾時,然後重試——而在正式版本中,它會刻意隱藏第一次 WebSocket 重試。第一次錯誤通知要等第二個 300 秒視窗結束後才會出現,已超過 NanoClaw 固定的 600,000 ms 回合計時器。我們於 2026 年 10 月 1 日重現此問題:Codex 0.138.0 在 750 秒內完全沒有傳送通知,而 NanoClaw 目前鎖定的 0.155.1 則在 615.7 秒時才傳送第一個通知;NanoClaw 的規則在 600 秒時結束回合。

我在機器人卡住時傳送的訊息會怎樣?

它們會被導入卡住的回合,而在我們的執行中遺失。NanoClaw 會將活動回合期間到達的後續訊息路由至 Codex 的 turn/steer;Codex 將其接受到同一個停滯回合中,沒有再向上游傳送任何內容,而在逾時和恢復後,被引導的文字並未出現在該執行緒的歷史記錄中。機器人再次回覆後,請重新傳送你在沉默期間輸入的任何內容。

如何從 NanoClaw Codex 回合逾時中恢復?

傳送下一則訊息。NanoClaw 會啟動新的 app-server 並恢復同一個執行緒;在我們的執行中,端點回應後,恢復的回合在 0.16 秒內完成,原始提示仍在歷史記錄中。如果上游仍然停滯,新回合也會以相同方式停滯,因此請先檢查 OpenAI 的狀態或你的網路路徑——並重新傳送任何被吞掉的後續訊息。

將 Codex 從 WebSockets 切換至 HTTP 能解決問題嗎?

它會縮短沉默時間,但尚未合併。Pull request #3851(開放中,由問題回報者提出)加入 NANOCLAW_CODEX_TRANSPORT=http,讓 Codex 透過 HTTP/SSE 傳輸。在我們的類似執行中,第一次錯誤通知在 300 秒時到達,而不是等到計時器結束——但它帶有 willRetry true,此時 Codex 已經在重新傳送;NanoClaw 會在收到任何錯誤通知時結束回合,因此該回合會在 5 分鐘時失敗,而不是恢復。

這是一般的 Codex 逾時嗎?

不是。Codex 本身會持續重試;十分鐘的沉默來自 NanoClaw 的回合計時器與 Codex 隱藏的第一次重試彼此重疊。在 0.155.1 中,應用程式伺服器約於 616 秒時回報「Reconnecting... 2/5」;具有較長回合預算的用戶端會看到它,NanoClaw 則永遠不會。NanoClaw 的預設提供者是 Claude Agent SDK,與此無關。

我們於 2026 年 10 月 1 日使用來自 npm 的原生 codex app-server 二進位檔(@openai/codex 0.138.0 和 0.155.1,darwin-arm64),透過 stdio 傳入 NanoClaw providers 分支(commit 3959d1f055)中的 initialize、thread/start、turn/start 和 turn/steer 參數,透過 WebSocket 和 HTTP/SSE 對本機的 Responses 替身進行重現。Codex 預設值與隱藏的第一次重試取自 codex-rs 的 rust-v0.138.0 和 rust-v0.155.1 標籤。未執行:NanoClaw 的協調器與容器、OneCLI、Telegram 或 OpenAI 的實際端點——替身重現的是靜默串流,而不是導致 OpenAI 串流靜默的原因。問題與提取要求的狀態於同日讀取。