返回指南
設定·2026年9月21日·更新於 2026年9月24日·閱讀約 9 分鐘

Nanobot 無限迴圈與 token 使用量:診斷有迭代上限的 Dream 執行

錯誤標題所指的設定已被刪除,原本會恢復該設定的 pull request 已關閉且未合併,唯一剩下的上限適用於整個程序。

最後審核於 。

看起來像無限迴圈的 nanobot 執行其實是有界的:在已發布的 v0.3.5 原始碼中,每個代理回合都受 agents.defaults.maxToolIterations 限制,其預設值為 200;維護者也明確表示,這並不是字面意義上的無限迴圈。真正的問題是 token 使用量,因為達到該上限的執行會記錄 201 個 assistant 回合,並且每次都重新傳送逐漸增長的提示。要釐清你遇到的是哪一種情況,需要回答四個問題,而有證據支持的修正方式不是某個組態值。

先排除最明顯的線索。上游報告是 issue #5781,標題指向 dream.maxIterations,而 PR #5782 的標題是 "fix(dream): enforce configured iteration limit"。該設定鍵在 v0.3.5 中不存在,而 PR 於 2026 年 9 月 16 日關閉且未合併。以此為基礎的教學實際上不會設定任何東西。

先釐清一點,因為搜尋結果會顯示錯誤的追蹤專案。本頁討論的是 HKUDS/nanobot,採用 MIT 授權,安裝的 PyPI 套件為 nanobot-ai——0.3.5 版、Python 3.11 或更新版本,於 2026 年 9 月 15 日上傳。obot-platform/nanobot 是另一個 Go 專案,其 README 宣告進入維護模式且停用 issues;它的 issue 編號在此不具證據效力。而沒有後綴的 pip install nanobot 會安裝無關的機器人導航套件。

報告內容,以及針對哪個版本

Dream 是 nanobot 排程執行的記憶整合工作,由 gateway 以名為 dream 的 cron 工作執行。它不是 embedding 或向量索引工作:Kunavo 不提供 embedding 模型,而 Dream 也不需要 embedding 模型,因為 nanobot 的持久記憶是工作區下的純文字檔案,Dream 執行則是一般的聊天流量。

Issue #5781 由 BrianMwangi21 於 2026 年 9 月 15 日提出,針對 nanobot v0.3.0,使用 Python 3.12,並透過 OpenRouter 存取推理模型。症狀是:Dream 工作交替對 memory/history.jsonl 執行 read_file、對一個 SKILL.md 執行 read_file,反覆數十次;同時,推理追蹤不斷重新考慮應將一項簡短的事實記錄在哪裡。約 26 小時內記錄的七次執行,耗時約 25 分鐘至約 111 分鐘不等;接近 200 次工具呼叫的執行達到了全域上限,而工作階段檢查點顯示 runtime_checkpoint.iteration: 164,階段為 tools_completed,對應同一個 read_file 呼叫。

這些數字需要搭配三項範圍限制。它們是單一使用者自行回報的 gateway 記錄,使用單一模型,版本為 v0.3.0——沒有維護者重現問題,也沒有人在 v0.3.5 上重新測試。該 issue 標記為 enhancement 和 priority: p2,不是 bug,而且目前仍然開啟。這種模式過去也曾出現:2026 年 4 月 12 日的 issue #3073 回報了一個幾乎相同、對 history.jsonl 執行 read_file 的迴圈,最後以 not planned 關閉。這些都不支持把 nanobot 視為普遍昂貴;它們支持你檢查自己的安裝是否正在發生這種情況。

已棄用的金鑰,以及實際生效的界線

整個困惑源於版本差異,而原始碼已經給出答案。於 2026 年 9 月 21 日讀取兩個版本標籤時:

組態金鑰v0.3.0 中v0.3.5 中現在應怎麼做
dream.maxIterations預設值 15,標記為 # Deprecated: no longer used已從 schema 移除不要寫入;它不會設定任何內容
dream.maxBatchSize預設值 20,相同的棄用註解已移除不要寫入
dream.annotateLineAges預設值 true,相同的棄用註解已移除不要寫入
dream.enabled預設值 true預設值 true可在 WebUI 執行階段設定中編輯
dream.intervalH預設值 2預設值 2編輯 config.json;不是 WebUI 的葉節點
dream.cronNull;舊版覆寫Null;舊版覆寫設定後優先於 intervalH
dream.modelOverride已宣告,並註解為 pending implementation已實作只能使用預設名稱,絕不可使用原始模型 ID
agents.defaults.maxToolIterations200200唯一的上限,而且是整個程序共用

有兩件事容易讓這張表被誤解。200 這個數字有雙重依據——它既是報告者組態中的值,也是 nanobot/config/schema.py 第 129 行隨附的預設值,在 v0.3.5 標籤和 main 上完全相同,因此即使讀者從未設定它,仍然是 200。而且它沒有文件說明:2026 年 9 月 21 日擷取 nanobot 自己的 0.3.5 組態參考時,取得 488,608 位元組的 HTML,其中出現 maxToolIterations 的次數為零,而該標籤下儲存庫的 docs/configuration.md 也完全沒有提到它。這個數字可以從原始碼和維護者留言證明,而不是從文件頁面證明——因此對引用不同數字的任何教學都應保持懷疑。

modelOverride 是唯一具備版本條件的補救措施。在 v0.3.0 中,該欄位存在,但註解為 pending implementation,完全沒有對應的解析程式碼;於 2026 年 7 月 27 日合併的 PR #5107 在 v0.3.5 中實作了它。官方 0.3.5 記憶頁面說明它會從 model_presets 中選取 Dream 使用的具名項目,只接受預設組態名稱,不支援原始模型識別碼。該頁面記錄了三個 Dream 設定鍵,完全沒有提到迭代上限。以下是目前完整的可用介面,其中所依賴的 providers 區塊在 nanobot 設定頁面中有說明:

~/.nanobot/config.json——完整的 v0.3.5 Dream 介面
{
  "modelPresets": {
    "dream-cheap": {
      "provider": "kunavo",
      "model": "claude-haiku-4-5",
      "maxTokens": 8192
    }
  },
  "agents": {
    "defaults": {
      "maxToolIterations": 200,
      "dream": {
        "enabled": true,
        "intervalH": 2,
        "modelOverride": "dream-cheap"
      }
    }
  }
}

請注意該檔案中沒有的內容:任何可以單獨限制 Dream 的方式。AgentLoop 只會使用程序預設值中的 max_iterations 建立一次,而 Dream cron 路徑與手動 /dream 路徑都會在沒有提供迭代參數的情況下呼叫 process_direct(...),子代理也是如此。降低此上限會同時降低聊天、Dream、heartbeat 和子代理的上限。

依此順序診斷

先回答以下四個問題再更改任何設定,因為其中三個不需成本,第四個會告訴你前三個是否重要。記錄字串是 v0.3.5 中的字面文字;大括號代表執行階段值。

問題查看位置答案代表的意義
1. 執行是自行停止,還是達到上限?Gateway 記錄:Max iterations (200) reached,來自 agent/loop.py出現表示執行達到上限,約有 201 個 assistant 回合。未出現表示執行在達到上限前結束——模型可能已收斂,或執行直接失敗並記錄 Dream cron job failed
2. Dream 游標是否前進?cli/gateway_runtime.py 中的三行不同記錄:Dream cron job completed, cursor advanced to …;… completed with no memory changes; cursor advanced to …;Dream cron job did not complete (…); cursor remains at …第三行表示 v0.3.5 的故障安全機制正在運作:未完成的執行會留下該批次以便重試。這也表示同一個批次會在下一次 tick 再次出現
3. 是否以相同參數重複使用相同工具?這兩個標記之間的 Tool call: 行工具與參數一再完全相同,表示模型未收斂,這也是上游的結論。v0.3.5 中唯一的重複防護會比對 web_fetch 和 web_search;重複的 read_file 不會被攔截
4. 成本是多少?組態目錄中的 llm_usage.sqlite3,依日期和來源彙總;在 gateway 端則按金鑰和日期記錄於 usageDream 標記為 dream。heartbeat 標記為 cron,因此篩選 "heartbeat" 會找不到任何內容

你不必等待兩小時讓 cron tick 重現問題。/dream 指令會隨需執行相同工作,並在聊天中回報相同的區分:成功時為 Dream completed in Ns. 或 Dream completed in Ns; no memory changes.,未完成時則針對 Dream did not complete after Ns (reason); memory cursor was not advanced. 回報。你尋找證據時,另一項 v0.3.5 的變更也很重要:工作階段 JSONL 檔案已移至組態目錄的 sessions/<workspace-id>/ 樹狀結構下,因此 issue 討論串中引用的 v0.3.0 路徑並不是你的檢查點所在位置。

五個控制手段,以及每個手段實際有什麼依據

槓桿依據適用時機你需要付出的代價
將 v0.3.0 升級至 v0.3.54e2640f commit 僅在停止原因為 completed 時推進游標;該 commit 存在於 v0.3.5,而不存在於 v0.3.0你的症狀是記憶被跳過,而不是支出過高它不會縮短不收斂的迴圈,而且沒有人在 0.3.5 上重新測試 #5781
更換 Dream 使用的模型唯一有前後對照的補救方式:在報告者的稽核中,某個模型花了 91 分鐘仍未完成的批次,下一次使用另一個模型時,在相同提示、相同歷史記錄和相同工具下,約一分鐘內以 6 次工具呼叫完成聊天品質必須維持使用昂貴模型需要 v0.3.5 和已定義的預設;在 v0.3.0 中該欄位會解析為空值
降低 maxToolIterations可在 WebUI 執行階段設定中編輯,每個 webui/settings_runtime.py 的最小值為 1你希望在診斷期間設定最壞情況上限聊天、Dream、heartbeat 和子代理共用一個控制項;達到上限的執行不會推進游標,因此相同批次會在下一個 tick 重試
減慢或停用 DreamintervalH,或在 WebUI 中使用 dream.enabled;合併的 PR #5407 會在停用時撤除已持久化的工作在你的工作負載中,記憶整合不值得付出相應成本你會失去記憶整合,而這正是該功能本身
設定路由,讓重新傳送的成本更低在 v0.3.5 中,恰好有兩個 provider 規格設定 supports_prompt_caching:anthropic 和 openrouter;該欄位預設為 false你接受長時間執行會發生,並希望降低其成本取決於你設定的協定路徑,也取決於你自行驗證回傳的使用量

報告者透過 OpenRouter 寫出的兩個模型 ID 是 deepseek/deepseek-v4-flash-0731 和 openai/gpt-5.6-luna;此處未核對這些 ID 及其價格,因此應將比較理解為模型決定收斂情況的證據,而不是對任一模型的推薦。上游也得出相同結論:在 issue #5781 中宣布關閉 PR #5782 時,chengyongru 表示,固定的 Dream 迭代上限無法解決模型依賴的根本收斂問題,並可能導致原本可行的執行不斷被重複重試。

達到上限的執行成本:示意計算

這些是示意性的 token 算術計算,並非實測的任務成本,也不是帳單金額上限。nanobot 並未公布 Dream 每次執行的 token 數,因此此處的每個輸入值都是假設,您應以自己的測量結果取代。假設一次執行達到 201 個助理回合的上限——這是報導者稽核時記錄的回合數——每個回合都重新傳送一份固定維持在 25,000 個 token 的提示詞;這是他對自己工作區的描述,並非已公布的數據。這相當於 5.03M 個輸入 token。計算未包含輸出 token,而實際的提示詞會隨著每次工具回傳結果而增長,因此這項計算同時從兩個面向低估了實際執行的用量。費率採用即時的 Kunavo 目錄價格。

模型每 1M 的輸入每 1M 的快取讀取一次達到上限的執行,不使用快取相同執行,重新傳送內容從快取讀取
Claude Haiku 4.5$0.70$0.07$3.52$0.37
GPT-5.6 Terra$0.70$0.07$3.52$0.37
Claude Sonnet 5$1.40$0.14$7.04$0.74

最後一欄假設一個此處未經測試的最佳情況:第一次傳送使用一般輸入費率,所有 200 次重新傳送都以快取讀取提供。快取寫入會按自身費率計費;某些模型的快取寫入費率高於一般輸入費率;快取項目也會過期;而會增長的提示會被重新寫入,而不是重新讀取——因此應將最後兩欄之間的差距視為可能獲得的節省幅度,而不是報價。這裡的重點只是,在長時間的重複執行中,花費主要來自重新傳送,而不是模型本身。

快取標記是否真的送到線上,由你的 nanobot 組態決定,而已發布的原始碼中可以看出這一點。providers 下的自訂 provider 金鑰會被視為純 OpenAI 相容 provider,並讓 supports_prompt_caching 維持預設值 false,因此即使模型 ID 具有 Claude 形式,nanobot 用戶端在該路徑上也不會傳送 cache_control 標記。保留內建 anthropic provider 的預設值並覆寫 providers.anthropic.apiBase,則會保留這些標記。這說明的是 nanobot 用戶端傳送的內容,不是任何端點在自身一側的處理方式,而且 Kunavo 尚未對 nanobot 進行執行階段測試。在將週期性工作預算視為使用快取前,請先讀取一次實際呼叫回傳的使用量;快取文件展示正常快取的樣子,而 基礎 URL 參考提供兩種端點慣例。

Kunavo 的目錄金額是計費下限,而不是上限:當上游回報其費用時,帳單金額取目錄成本與上游成本乘以適用加成兩者中的較高者。預付額度的最低儲值額為 $10 預付額度——這是資金最低額,不是工作費用或訂閱費用。請參閱 計費詳細資訊,以及 成本最佳化中用來取代上述假設的測量方法。

在一次執行中驗證修正

只變更一項內容,然後執行一次 /dream,不要等待排程,並依序檢查三個標記:沒有 Max iterations (200) reached 警告、有 cursor advanced to … 行而不是 cursor remains at …,以及中間的工具呼叫數量合理。接著,在 usage 中讀取你自己的帳戶針對該時段記錄的費用,按金鑰和日期查看;nanobot 的儲存只計算 token,不計算金額。如果你是第一次設定端點,快速入門和 nanobot 設定頁面涵蓋兩種協定路徑,而建立 Kunavo 帳戶是為金鑰儲值前的步驟。若要比較執行環境,nanobot 與 OpenClaw會並列兩種背景執行頻率,而 代理 API 目錄則依線上協定索引用戶端。

常見問題

nanobot 真的卡在無限迴圈中嗎?

不是,而且一名維護者已公開如此表示。chengyongru 於 2026 年 8 月 10 日在 issue #5324 的留言中寫道,nanobot 的代理程式執行器受 agents.defaults.maxToolIterations 限制,預設為 200,因此這不是字面上的無限迴圈——但他也補充,長時間的有限迴圈仍可能造成極高的累積權杖用量,所以實際影響確實存在。隨附的 v0.3.5 原始碼也一致:nanobot/config/schema.py 中的 max_tool_iterations 預設為 200,而 agent/loop.py 會在一次執行達到上限時記錄警告 "Max iterations (200) reached"。人們所稱的無限迴圈,其實是一次達到該上限的執行;在其中一名回報者的記錄中,這代表 201 個助理回合反覆讀取同兩個檔案。

為什麼設定 dream.maxIterations 沒有作用?

因為該欄位已不存在。在 nanobot v0.3.0 中,Dream 設定包含 max_iterations、max_batch_size 和 annotate_line_ages,原始碼中每個欄位都標有註解 "Deprecated: no longer used";在 v0.3.5 標籤中,三者全都已移除,類別只定義 enabled、intervalH、cron 和 modelOverride。維護者 chengyongru 於 2026 年 9 月 15 日表示,Dream 移至一般代理程式迴圈時,dream.maxIterations 就被刻意標記為已棄用且不再使用,之後也已從 main 移除。原本會恢復它的拉取請求 #5782 隔天以未合併狀態關閉。在 v0.3.5 設定中寫入該設定鍵,等於寫入一個設定綱要未定義的設定鍵。

如何只限制 nanobot Dream 工作的權杖數?

在 nanobot v0.3.5 中,不能將其限制為累積預算。隨附程式碼沒有統計一次執行的權杖總數並在達到某個數值時停止的功能,而 agents.defaults.maxToolIterations 是唯一的迭代上限——它是全程序範圍,會同時套用於一般聊天回合、Dream、心跳和子代理程式。透過 agents.defaults.dream.modelOverride,你可以只將兩件事限定於 Dream:模型,以及該預設值自己的每次呼叫限制,因為 ModelPresetConfig 包含 maxTokens 和 contextWindowTokens,而 dream_runtime() 會將具名預設值解析為 Dream 執行所使用的執行時環境。這些限制的是每次個別呼叫,而不是整次執行的總量,因此在低 maxTokens 下進行 200 次呼叫,仍然是 200 次呼叫。排程也可以透過 intervalH 單獨設定。目前,上游拒絕新增累積預算:chengyongru 於 2026 年 9 月 16 日在 issue #5781 上發文——也就是他關閉 PR #5782 的當天——表示背景工作所需的權杖或資源預算,需要更詳細的設計,涵蓋預算單位與範圍、終止語意、重試與游標行為、可觀測性,以及與不同模型的互動;目前他們不打算推進此事。

如何停止已經在執行的 nanobot Dream 執行?

根據對 v0.3.5 原始碼的解讀,不能使用 /stop。文件說明 /stop 會取消此聊天中目前作用中的代理回合;其實作方式是取消註冊在該聊天工作階段金鑰下的工作,而 Dream 執行則使用形如 dream:YYYYMMDD-HHMMSS 的獨立暫時金鑰建立。這是對程式碼路徑的解讀,不是經過測試的結果——此處未對執行中的 Dream 執行實際執行 /stop。文件記載的控制方式是使用 /restart、關閉 agents.defaults.dream.enabled,或停止 gateway 程序。v0.3.5 中合併的 PR #5407 使停用功能確實撤除已持久化的系統工作,而不只是讓它維持排程狀態。

如何查看 nanobot 的背景工作使用了多少 token?

讀取本機使用量儲存,而不是使用斜線指令。nanobot v0.3.5 會記錄每次模型呼叫,並將 source 欄位標記為 user、api、cron、dream 或 system;資料會寫入組態目錄中的 llm_usage.sqlite3——預設為 ~/.nanobot——其中包含 input、output、cache-read 和 cache-write token 欄位,並依日期與來源分組彙總。這裡有兩個陷阱。沒有 /insights 或 /cost 指令:提出這兩項功能的提案 #3735 和 #3921 都已關閉且未合併,而 v0.3.5 的內建指令清單是 /new、/compact、/stop、/restart、/status、/model、/history、/goal、/trigger、/dream、/dream-log、/dream-restore、/dream-prompt、/evaluator-prompt、/skill、/help 和 /pairing。標籤也不對稱:Dream 的支出標記為 dream,但 heartbeat 的支出標記為 cron,因為 heartbeat 工作階段金鑰的字面值就是 "heartbeat"。這些是 token 數量,不是金額,因此請與供應商自己的帳本核對。

升級到 nanobot v0.3.5 能修復這個迴圈嗎?

沒有人表示它能修復,而本頁也不會這樣宣稱。Issue #5781 是針對 v0.3.0 提出的,目前仍然開啟,標記為 enhancement 和 priority p2;報告者升級後從未重新測試,維護者也沒有重現問題。v0.3.5 確實修復的範圍較窄,但仍然值得升級:commit 4e2640f 會阻止未完成的執行推進 Dream 游標並靜默略過歷史記錄,合併的 PR #5442 會說明未完成執行未完成的原因,而合併的 PR #5325 會讓 edit_file 回傳 "Error: new_text must be different from old_text.",不再將無操作編輯回報為成功。最後一項修復的是 issue #5324 的讀取後編輯迴圈,而不是 #5781 的唯讀迴圈。v0.3.5 也沒有提供一般性的重複工具呼叫防護。已發布原始碼中的唯一重複防護 repeated_external_lookup_error 位於 nanobot/utils/runtime.py,會在兩次嘗試後阻擋相同的 web_fetch 或 web_search,且不比對其他工具名稱,因此重複的 read_file 會繼續執行到迭代上限。提出一般性防護的五個 pull request——#3077、#4522、#5344、#3701 和 #4154——目前全部未合併。

截至 2026 年 9 月 21 日已檢查:HKUDS/nanobot 的 GitHub API,以及 issues #5781、#5324 和 #3073,和 pull requests #5782、#5107、#5325、#5442、#5407、#3077、#4522、#5344、#3701、#4154、#3735、#3921 和 #4622;nanobot-ai 0.3.5 的 PyPI 紀錄;nanobot 的 0.3.5 記憶與組態文件;以及 v0.3.5 標籤下已發布的原始碼,以核對上述引用的每個預設值、記錄字串和程式碼路徑,並在兩個版本有差異之處與 v0.3.0 進行比較。Kunavo 未安裝或執行 nanobot,此處沒有任何行為經 Kunavo 測試,而 issue #5781 的迴圈也沒有任何人在 v0.3.5 上重新測試。Token 費率來自即時目錄,所有美元數字都是在所述假設下的示意計算。