無限ループに見えるnanobotの実行は有限です。提供されたv0.3.5のソースでは、すべてのエージェントターンにagents.defaults.maxToolIterationsによる上限があり、デフォルトは200です。メンテナーも公に、これは文字どおりの無限ループではないと述べています。本当の問題はトークン使用量です。上限に達する実行ではアシスタントターンが201回記録されるうえ、毎回、増大するプロンプトが再送信されます。あなたの状況を切り分けるには4つの質問があり、証拠のある修正は設定値ではありません。
まず、明らかな手掛かりを除外します。上流の報告はissue #5781で、タイトルはdream.maxIterationsを示しており、PR #5782のタイトルは「fix(dream): enforce configured iteration limit」です。このキーはv0.3.5には存在しません。PRは2026年9月16日に未マージのままクローズされました。これに基づくチュートリアルは何も設定していません。
1点、切り分けが必要です。検索結果は誤ったトラッカーを表示します。このページの対象はHKUDS/nanobot(MIT)で、PyPIパッケージnanobot-aiとしてインストールされます。バージョンは0.3.5、Python 3.11以降、アップロード日は2026年9月15日です。obot-platform/nanobotは別のGoプロジェクトで、READMEにはメンテナンスモードでissueは無効と記載されています。そのissue番号はここでの証拠にはなりません。また、接尾辞のないpip install nanobotは、無関係なロボットナビゲーションパッケージをインストールします。
報告された内容と対象バージョン
Dreamはnanobotのスケジュール実行されるメモリ統合ジョブで、dreamという名前のcronジョブとしてゲートウェイが実行します。これは埋め込みジョブでもベクトルインデックスジョブでもありません。Kunavoは埋め込みモデルを提供しておらず、Dreamにも必要ありません。nanobotの永続メモリはワークスペース内の通常のファイルであり、Dreamの実行は通常のチャットトラフィックだからです。
issue #5781は2026年9月15日、BrianMwangi21によってnanobot v0.3.0に対して登録されました。Python 3.12上で、OpenRouter経由で到達した推論モデルを使用していました。症状は、Dreamジョブがmemory/history.jsonlに対するread_fileと、1つのSKILL.mdに対するread_fileを何十回も交互に実行するというものです。その間、推論トレースは1つの小さな事実をどこに記録するかを再検討していました。約26時間にわたる7回の実行は、およそ25分からおよそ111分でした。ツール呼び出しが200回近くに達した実行はグローバル上限に達しており、セッションチェックポイントには同じread_file呼び出し上でruntime_checkpoint.iteration: 164、フェーズtools_completedと記録されていました。
これらの数字には、3つのスコープ上の制限があります。これは、1人のユーザーが自己申告したゲートウェイログであり、1つのモデル、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日に2つのリリースタグを確認した結果は次のとおりです。
| 設定キー | v0.3.0の場合 | v0.3.5の場合 | 現在すべきこと |
|---|---|---|---|
dream.maxIterations | デフォルト15、# Deprecated: no longer usedと記載 | スキーマから削除 | 書き込まない。何も設定しない |
dream.maxBatchSize | デフォルト20、同じ非推奨コメント | 削除済み | 書き込まない |
dream.annotateLineAges | デフォルトtrue、同じ非推奨コメント | 削除済み | 書き込まない |
dream.enabled | デフォルトtrue | デフォルトtrue | WebUIランタイム設定で編集可能 |
dream.intervalH | デフォルト2 | デフォルト2 | config.jsonを編集。WebUIの末端項目ではない |
dream.cron | null。レガシー上書き | null。レガシー上書き | 設定されている場合はintervalHより優先 |
dream.modelOverride | 宣言済み、実装保留とコメント | 実装済み | プリセット名のみ。生のモデルIDは不可 |
agents.defaults.maxToolIterations | 200 | 200 | 唯一の上限であり、プロセス全体に適用 |
この表は2つの理由で間違えやすいものです。200は二重の意味で正しい値です。報告者の設定にある値であり、v0.3.5タグおよびmainにおけるnanobot/config/schema.py行129の提供時デフォルトでもあります。そのため、自分で設定していない読者にも200が適用されます。また、ドキュメント化されていません。2026年9月21日にnanobot自身の0.3.5設定リファレンスを取得したところ、HTMLは488,608バイトで、maxToolIterationsの出現回数は0でした。そのタグにおけるリポジトリのdocs/configuration.mdにもありません。この数値はソースとメンテナーのコメントから証明できますが、ドキュメントページからは証明できません。そのため、異なる数値を引用するチュートリアルには注意してください。
modelOverrideはバージョンによる制限がある唯一の対処法です。v0.3.0ではこのフィールドが実装待ちというコメント付きで存在していましたが、プリセット名を解決するコードはまったくありませんでした。2026年7月27日にマージされたPR #5107が、v0.3.5向けにこれを実装しました。公式の0.3.5メモリページには、Dream用にmodel_presetsから名前付きエントリを選択し、プリセット名のみを受け付け、生のモデル識別子はサポートしないと記載されています。このページにはDreamのキーが3つ記載されており、反復上限についてはどこにも触れていません。ここに現在の完全なインターフェースを示します。依存するprovidersブロックについては、nanobotセットアップページで説明されています。
{
"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を使って1回だけ構築され、Dreamのcronパスと手動の/dreamパスはいずれも、サブエージェントと同様に反復引数なしでprocess_direct(...)を呼び出します。上限を下げると、チャット、Dream、ハートビート、サブエージェントのすべてで上限が下がります。
この順序で診断してください
変更する前に、次の4点を確認してください。3つは無料で確認でき、4つ目は最初の3つが重要かどうかを判断できます。ログ文字列はv0.3.5のリテラルテキストで、波括弧は実行時の値です。
| 質問 | 確認箇所 | 回答が意味すること |
|---|---|---|
| 1. 実行は自動的に停止しましたか、それとも上限に達しましたか? | ゲートウェイログ:Max iterations (200) reached、agent/loop.pyから | 存在する場合は上限に達した実行で、アシスタントのターン数はおよそ201回です。存在しない場合は、上限に達する前に実行が終了しました。モデルが収束したか、実行が完全に失敗してDream cron job failedを記録したかのどちらかです |
| 2. Dreamカーソルは進みましたか? | cli/gateway_runtime.py内の、異なる3行:Dream cron job completed, cursor advanced to …、… completed with no memory changes; cursor advanced to …、Dream cron job did not complete (…); cursor remains at … | 3行目はv0.3.5のフェイルセーフ処理です。不完全な実行ではバッチが再試行されます。また、同じバッチが次のティックで再び実行されることも意味します |
| 3. 同じツールが同じ引数で繰り返されていますか? | この2つのマーカーの間にあるTool call:行 | 同じツールと引数が何度も繰り返されるのは、モデルが収束していないことを示します。これは上流側の結論です。v0.3.5で唯一の繰り返しガードが照合するのはweb_fetchとweb_searchであり、繰り返されるread_fileは検出されません |
| 4. 費用はいくらでしたか? | 設定ディレクトリ内のllm_usage.sqlite3を日付とソース別に集計します。ゲートウェイ側では、usage内でキー別・日別に確認できます | Dreamにはdreamというタグが付きます。ハートビートにはcronというタグが付くため、"heartbeat"で絞り込んでも何も見つかりません |
再現のためにcronのティックを2時間待つ必要はありません。/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の変更がもう1つあります。セッションJSONLファイルは設定ディレクトリのsessions/<workspace-id>/ツリー配下に移動しました。そのため、課題スレッドに記載されたv0.3.0のパスは、チェックポイントの場所ではありません。
5つの調整項目と、それぞれを実際に裏付ける根拠
| 手段 | 根拠 | 有利な場面 | 発生するコスト |
|---|---|---|---|
| v0.3.0からv0.3.5へアップグレードする | v0.3.5にあり、v0.3.0にはないコミット4e2640fにより、停止理由がcompletedの場合にのみカーソルが進みます | 症状は支出ではなく、メモリのスキップです | 収束しないループは短縮されず、#5781は0.3.5で再テストされていません |
| Dreamのモデルを変更する | 変更前後を比較できる唯一の対策です。報告者の監査では、あるモデルで91分間費やしても完了しなかったバッチが、同じプロンプト、同じ履歴、同じツールを使い、別のモデルによる次の実行では、約1分、ツール呼び出し6回で完了しました | チャットの品質は高価なモデルで維持する必要があります | v0.3.5と定義済みのプリセットが必要です。v0.3.0ではこのフィールドは何も解決しません |
maxToolIterationsを下げる | WebUIのランタイム設定で編集できます。最小値は1で、webui/settings_runtime.pyごとに適用されます | 診断中に最悪ケースの上限が必要です | チャット、Dream、ハートビート、サブエージェントに共通する1つの設定です。上限に達した実行ではカーソルが進まないため、同じバッチが次のティックで再試行されます |
| Dreamを遅くするか無効にする | WebUIでintervalHまたはdream.enabledを設定します。マージ済みのPR #5407により、無効化すると永続ジョブが終了します | あなたのワークロードでは統合のコストに見合わない | 機能であるメモリ統合が失われます |
| 再送を安くするようルーティングする | v0.3.5では、supports_prompt_cachingを設定するプロバイダ仕様は正確に2つです。anthropicとopenrouterです。このフィールドのデフォルト値はfalseです | 長時間の実行を受け入れ、コストを下げたい | 設定したプロトコルパスと、返された使用量を自分で確認するかどうかに依存します |
報告者がOpenRouter経由で記述した2つのモデルIDはdeepseek/deepseek-v4-flash-0731とopenai/gpt-5.6-lunaでした。これらのIDと価格はここでは確認していないため、比較はモデルが収束を決めるという根拠として読んでください。どちらか一方の推奨ではありません。上流側も同じ結論に達しました。issue #5781でPR #5782の終了を発表した際、chengyongruは、固定されたDream反復上限ではモデル依存の根本的な収束問題に対処できず、本来実行可能な実行が繰り返し再試行される可能性があると記述しました。
上限に達した実行のコスト:説明用の計算
これは測定済みのタスクコストでも請求上限でもなく、説明用のトークン計算です。nanobotはDreamの実行ごとのトークン数を公開していないため、ここで使う値はすべて仮定であり、自分の測定値に置き換える必要があります。報告者の監査で数えられた、上限に達する1回の実行を想定します。これは201回のアシスタントターンで、各ターンが25,000トークンで一定のプロンプトを再送するとします。これは公開値ではなく、報告者自身のワークスペースについての説明です。入力トークンは5.03Mです。出力トークンは含めていません。また、実際のプロンプトは各ツール結果によって大きくなるため、この計算は実際の実行を2つの方向で同時に過小評価します。料金は現在のKunavoカタログ価格です。
| モデル | 1Mあたりの入力 | 1Mあたりのキャッシュ読み取り | 上限に達する実行1回(キャッシュなし) | 同じ実行で、再送分をキャッシュから読み取る場合 |
|---|---|---|---|---|
| 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回の再送はすべてキャッシュ読み取りとして処理されるケースです。キャッシュ書き込みには独自の料金がかかり、一部のモデルでは通常の入力料金より高く設定されています。キャッシュエントリには有効期限があり、増大するプロンプトは再読み取りではなく再書き込みになります。そのため、最後の2列の差は見込める節約幅として扱い、見積書として扱わないでください。要点は、長く反復的な実行では、費用の大部分をモデルではなく再送が占めるということだけです。
キャッシュマーカーが実際に送信されるかどうかは、nanobotの設定で決まり、同梱ソースで確認できます。providers配下の、作成したプロバイダキーは通常のOpenAI互換プロバイダとして扱われ、supports_prompt_cachingはデフォルトのfalseのままになります。そのため、Claude形式のモデルIDであっても、そのパスではnanobotのクライアントはcache_controlマーカーを送信しません。組み込みのanthropicプロバイダ上でプリセットを維持し、providers.anthropic.apiBaseを上書きすれば、マーカーは維持されます。これはnanobotのクライアントが送信する内容についての説明であり、各エンドポイントが自身の側で行う処理についてではありません。また、Kunavoはnanobotを実行時テストしていません。定期ジョブをキャッシュ済みとして予算化する前に、実際の1回の呼び出しで返された使用量を確認してください。キャッシュに関するドキュメントには機能するキャッシュの状態が、ベースURLリファレンスには2つのエンドポイント方式が示されています。
Kunavoのカタログ金額は上限ではなく請求下限です。上流側が料金を報告すると、請求額はカタログ料金と、該当するマークアップを乗じた上流料金のうち高い方になります。最低トップアップ額は$10の前払いクレジットです。これは資金補充の最低額であり、タスク料金でもサブスクリプション料金でもありません。請求の詳細と、上記の仮定を置き換える測定方法についてはコスト最適化を参照してください。
1回の実行で修正を検証する
1つだけ変更してから、スケジュールを待たずに/dreamを1回実行し、3つのマーカーを順番に確認します。Max iterations (200) reached警告がないこと、cursor remains at …ではなくcursor advanced to …行が出ること、その間のツール呼び出し数が妥当であることです。次に、その時間帯について自分のアカウントに記録された請求額を、使用状況でキー別・日別に確認します。nanobotのストアが数えるのはトークンであり、金額ではありません。エンドポイントを初めて設定する場合は、クイックスタートとnanobotセットアップページで両方のプロトコル方式を説明しています。キーへの入金前に行う手順はKunavoアカウントの作成です。実行環境を比較する場合は、nanobotとOpenClawの比較で2つのバックグラウンド周期を並べて確認でき、エージェントAPIディレクトリではクライアントを通信プロトコル別に検索できます。
よくある質問
nanobotは本当に無限ループに陥るのですか?
いいえ。メンテナーも公にそう説明しています。2026年8月10日にissue #5324へコメントしたchengyongruは、nanobotのエージェントランナーはagents.defaults.maxToolIterationsによって上限が設定され、デフォルトは200であるため、これは文字どおりの無限ループではないと述べました。ただし、長い有限ループでも累積トークン使用量が非常に大きくなり得るため、実際の影響はあるとも付け加えています。提供されたv0.3.5のソースも一致しています。nanobot/config/schema.pyではmax_tool_iterationsのデフォルトが200で、agent/loop.pyは実行が上限に達したときに「Max iterations (200) reached」という警告を記録します。人々が無限ループと呼んでいるものは、この上限に達する実行です。ある報告者のログでは、同じ2つのファイルを再読込するアシスタントターンが201回発生していました。
dream.maxIterationsを設定しても何も起きないのはなぜですか?
そのフィールドはもう存在しないからです。nanobot v0.3.0ではDream設定にmax_iterations、max_batch_size、annotate_line_agesがあり、ソース内でそれぞれ「Deprecated: no longer used」というコメントが付いていました。v0.3.5タグでは3つとも削除され、クラスには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だけに適用できるものは2つあります。モデルと、そのプリセット固有の呼び出しごとの上限です。ModelPresetConfigにはmaxTokensとcontextWindowTokensがあり、dream_runtime()は名前付きプリセットをDream実行が使用するランタイムに解決します。これらは個々の呼び出しを制限するだけで、実行全体を制限しません。そのため、maxTokensを低くしても200回の呼び出しは200回のままです。スケジュールもintervalHを通じてDreamだけに設定できます。累積予算は、現時点で上流が追加を見送っているものです。2026年9月16日、PR #5782を閉じた日に、chengyongruはissue #5781で、バックグラウンドタスクのトークンまたはリソース予算には、予算単位とスコープ、終了の意味、再試行とカーソルの挙動、可観測性、異なるモデルとの相互作用を含む、より詳細な設計が必要であり、現時点ではこれを前進させる予定はないと述べました。
すでに実行中のnanobot Dreamを停止するにはどうすればよいですか?
v0.3.5のソースを読む限り、/stopでは停止できません。/stopはこのチャットのアクティブなエージェントターンをキャンセルするものとして文書化され、そのチャットのセッションキーに登録されたタスクをキャンセルします。一方、Dreamの実行はdream:YYYYMMDD-HHMMSS形式の独自の一時キーで作成されます。これはコードパスを読んだ結果であり、テスト済みの結果ではありません。ここでは実行中のDreamに対して/stopを実行していません。文書化されている手段は/restart、agents.defaults.dream.enabledを無効にすること、またはゲートウェイプロセスを停止することです。v0.3.5にマージされたPR #5407によって、無効化時に永続化されたシステムジョブが実際に廃止され、スケジュールに残らないようになっています。
nanobotのバックグラウンドジョブが使用したトークン数を確認するにはどうすればよいですか?
スラッシュコマンドではなく、ローカルの使用量ストアを読み取ってください。nanobot v0.3.5は、各モデル呼び出しをuser、api、cron、dream、systemのいずれかとしてsourceフィールドに記録し、設定ディレクトリ(デフォルトでは~/.nanobot)のllm_usage.sqlite3に、入力、出力、キャッシュ読み取り、キャッシュ書き込みのトークン列とともに保存し、日付とsourceでグループ化して集計します。注意点が2つあります。/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としてタグ付けされますが、ハートビートの使用量はcronとしてタグ付けされます。ハートビートのセッションキーが文字どおり「heartbeat」だからです。これらは金額ではなくトークン数なので、プロバイダー自身の台帳と照合してください。
nanobot v0.3.5へのアップグレードでループは直りますか?
直るとは誰も言っておらず、このページもそうは言いません。issue #5781はv0.3.0に対して登録され、現在もオープンで、enhancementおよびpriority p2のラベルが付いています。報告者はアップグレード後に再テストしておらず、メンテナーも再現していません。v0.3.5が修正するのはより限定的な点ですが、それでも有用です。コミット4e2640fは未完了の実行によってDreamカーソルが進み、履歴が静かにスキップされるのを止め、マージ済みPR #5442は未完了の実行が完了しなかった理由を報告するようにし、マージ済みPR #5325は編集内容がないedit_fileについて成功と報告する代わりに「Error: new_text must be different from old_text.」を返すようにしました。最後の修正はissue #5324の読み取り後編集ループに対応するものであり、#5781の読み取り専用ループには対応しません。v0.3.5には、同一のツール呼び出しを一般的に繰り返さないためのガードもありません。提供されたソースにある唯一の反復ガードであるnanobot/utils/runtime.pyのrepeated_external_lookup_errorは、web_fetchまたはweb_searchが同一内容で2回試行された後にブロックしますが、他のツール名には適用されません。そのため、read_fileの繰り返しは反復上限まで続きます。一般的なガードを提案した5つのプルリクエスト(#3077、#4522、#5344、#3701、#4154)はすべて未マージです。
2026年9月21日確認:HKUDS/nanobotのGitHub API、issue #5781、#5324、#3073、pull request #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タグの同梱ソースにある、上記で引用したすべてのデフォルト値、ログ文字列、コードパスを確認し、2つが異なる箇所についてはv0.3.0と比較しました。Kunavoはnanobotをインストールも実行もしておらず、ここで述べる挙動はKunavoによるテスト済みではありません。また、issue #5781のループは、誰によってもv0.3.5で再テストされていません。トークン料金は現在のカタログから取得し、すべてのドル金額は記載した仮定に基づく説明用の計算です。