Skip to content
catch-all-favorite
Esc
navigateopen⌘Jpreview
On this page

single-agent-loop 実験レポート

mekuri の Tauri → Deno Desktop 移行を題材にした、自律コーディングループ(catch-all-favorite の single-agent-loop)の振り返り。

  • 対象: feat/deno-desktop-migration ブランチ
  • 期間: 2026-06-25 〜 06-27(約2日。実働はバッチ間の待ち・session limit を含む)
  • ループ構成: claude -p を毎周フレッシュ context で実行し、記憶は loop/MEMORY.md。 5段階(DISCOVER→PLAN→EXECUTE→VERIFY→ITERATE)を loop/run.sh で反復。

1. 結果サマリ

指標
総コミット 58(ループ自動 ≈39 / オペレータ介入 ≈19)
成果物 deno-app/3,548 行(非テスト)+ フロント src/api 等の配線替え
テスト deno 243 + フロント vitest 62
マイルストーン M1〜M8 + polish。アプリは実用レベルで動作
残課題 canary バグ1件を upstream 報告(denoland/deno#35568)。本体は完成

2. ループが「強かった」点

  • 仕様が明確で検証可能な作業に圧倒的に強い。 M2/M5(backend 移植)は 1 周 1 モジュール・ テスト付き・高品質。設計判断も的確(trash の deleter 注入、DirectoryEntry の snake_case を React 互換のため維持、ライブラリ @zip-js/zip-jsnode-unrar-js を理由付きで採用)。
  • MEMORY 規律が白眉。 「何を/なぜ/落とし穴」を毎周詳細に記録。50 周超・複数日・複数 セッションをまたいで文脈を失わず継続できた。フレッシュ context + 外部記憶モデルの実証。
  • 難問の自己診断(最大の驚き)。 白画面の真因 No callback bound for: invoke に対し、 ループ自身が別名バインドを仕込んで計測し「win.bind は採用窓に届かない」と実証 → 全 IPC を HTTP(/__invoke)+SSE(/__events) へ pivot する設計転換まで自律到達。仮説検証型デバッグ。
  • RULES 遵守。 feature ブランチ厳守、src-tauri/ 不可侵、1 周 1 タスク。

3. ループが「失敗した」点(本実験の核心)

最大の教訓: M6 で「完了」を誤宣言した

ループは deno desktopビルド成功LOOP_DONE を出した。しかし実機起動は白画面。 原因は単純で深い:

VERIFY ゲート(deno の fmt/lint/check/test)が「フロント実行時」を一切観測していなかった。

ループは「ゲートを通す」ことに最適化する。ゲートが観測できない失敗モードでは、ループは自信を 持って “green のまま壊れたもの” を出荷する。 これが closed loop の本質的リスク。

派生した盲点

  • GUI/ランタイム全般が盲点。 白画面・ビューワー起動・メニュー位置・close ハング・RAR 遅延 — すべて人間のテストで発覚。ループは「ビルド通る/単体テスト緑」までしか見えない。
  • VISION の誤りをそのまま増幅。 初版 VISION が「src/components 無改変」と書いたため、 ループは正しくそれに従い、コンポーネント側の Tauri API 残存(=白画面の真因)を放置した。 ループは仕様を疑わない。VISION の品質が load-bearing。
  • 運用上の脆さ。 ①session limit で iteration が大量空振り(ある周で 13 回無駄撃ち)、 ②「ハッシュを MEMORY に書く」指示が amend/追記コミットを誘発(1 タスク 3 コミット)、 ③LOOP_DONE を説明文中で言及しただけで誤検出して早期停止 — いずれもオペレータの run.sh 修正/ハードニングが必要だった。
  • 自分の実行時失敗を再現できない。 ヘッドレスで GUI を検証する術がなく、open --stderr 捕捉や smoke ハーネスはオペレータが構築した。

4. 人間(オペレータ)が担い続けた役割

ループ化しても消えなかった仕事:

  • ゲート設計・修復(フロント実行時 smoke、check-no-tauri grep ゲート、サーキットブレーカ、 LOOP_DONE 厳格化)
  • 救出: session limit が iteration を途中で殺した未コミット作業を VERIFY 緑のまま確定 (M4b・event の HTTP 化)
  • 誤完了の検知と是正(false done の撤回 → M7 追加)
  • GUI/ランタイムのデバッグと確定(Not Found・白画面の修正検証・open_viewer・メニュー Y 反転・close ハング切り分け・RAR)
  • 方向付け(canary 導入合図、M7/M8 の VISION、MEMORY のオペレータ注記)

役割は「作業する人」から「ゲートを設計・修復し、ゲートが見えない所を検証する人」へシフトした。

5. 一般化できる学び

  1. ゲートがループそのもの。 ループは DoD ではなくゲートに最適化する。ゲートを実 DoD (ここでは「アプリが描画され操作できる」)に一致させない限り、green でも壊れたものが出る。
  2. ループは盲点を継承する。 ゲートが見えない領域(GUI・統合・体感・並行・ネイティブ挙動) ではループは無力。最初からその領域を観測するゲート(ランタイム smoke)を用意すべき。
  3. VISION 品質が支配的。 ループは仕様を忠実に実行し、誤りも忠実に実装する。
  4. フレッシュ context + MEMORY は実運用に耐える。 長期・複数セッションの継続性は MEMORY 規律が支えた。
  5. 運用ハードニングが効く。 サーキットブレーカ、1 タスク 1 コミット、堅牢な done 検出、 未コミット救出 — 地味な配管が成否を分けた。

6. 次回への推奨

  • ゲートを最初に作り、実 DoD に一致させる。 GUI アプリなら「ビルド+単体」でなく、初日から ランタイム/GUI smoke(描画・主要操作)を入れる。今回の smoke 拡張(ビューワー起動まで検証)は、 入れた後は誤完了を確実に止めた。
  • マイルストーンで人間検証のために “止まる” 設計に。 GUI の「動く/操作できる」はループに 判定させず、節目で human verification を要求する。
  • MEMORY のオペレータ注記は有効。 方向修正の差し込み口として機能した。
  • バッチを短く区切り、ブレーカで空振りを抑える。 session limit 対策。

7. トークン実測とコスト比較

Claude Code のトランスクリプト(~/.claude/projects/.../*.jsonl、6/25 以降の 120 ファイル= メインセッション + ループ各周の claude -p)の usage を集計した実測値。

トークン量(実測・Anthropic)

種別
出力 5.02M
入力(非キャッシュ) 5.03M
入力(cache write) 38.56M
入力(cache read) 706.5M
入力 合計(課金対象) ≈ 750M
アシスタント発話数 4,453

純粋な in/out は「入力 ≈5M / 出力 ≈5M」。ただし実際の入力課金の大半は cache_read 706.5Mで、 これは長い対話+50 周超のループが毎ターン肥大した文脈を読み直すため(cache_read は安価だが量で効く)。

推定コスト比較(実測トークン量に各社単価を適用)

単価(2026-06 時点, per 1M tokens): Claude Opus(標準単価の仮定)入力$15 / cache read$1.5 / cache write$18.75 / 出力$75。GPT-5.4 入力$2.50 / cached$0.25 / 出力$15。GPT-5.5 入力$5 / cached$0.50 / 出力$30。

種別 Claude Opus GPT-5.4 GPT-5.5
入力(非キャッシュ)5.03M $75 $13 $25
cache write 38.56M $723 $96 ※ $193 ※
cache read 706.5M $1,060 $177 $353
出力 5.02M $377 $75 $151
合計 ≈ $2,235 ≈ $361 ≈ $722

※ OpenAI には「キャッシュ作成の割増」が無いため、Anthropic の cache write 38.56M は GPT 側では 通常入力単価で換算。

この表は桁感の目安(正確な比較ではない):

  • トークナイザが違うため、GPT 側の実トークン量は異なる(「Anthropic 実測量 × GPT 単価」の換算)。
  • cache_read 量(最大の費目)はエージェント依存。Codex は文脈管理・キャッシュ挙動が違うので 706.5M にはならない。正確に比べるなら同じ作業を実際に Codex で走らせて usage を測るのが確実。
  • 桁としては Opus ≈ $2.2k / GPT-5.5 ≈ $720 / GPT-5.4 ≈ $360。主因は単価差(Opus が 5〜6 倍)と cache_read の量。

出典: aipricing.guru / Morph / OpenRouter GPT-5.5 / pricepertoken GPT-5.4

8. Max プランのセッションリミットに繰り返し当たった理由

本実験では Max プランの使用上限に複数回到達した。理由は本質的にループの構造による。

  • ループは使用量の「増幅器」。 通常の対話は 1 セッション分の消費だが、ループは 「メインのオーケストレーションセッション + 毎周の claude -p(各々がファイル読み書き・テスト 実行を伴うフル稼働のエージェント)」がすべて同じ 1 契約の枠を消費する。生産性を増幅するのと 同じ理屈で、クォータ消費も増幅される(実質「人間 1 人」ではなく「人間 + N 体のエージェントの 同時並行」相当)。
  • 量が大きく、かつ集中する。 約 2 日で 4,453 発話 / 課金入力 ≈750M / 出力 ≈5M(§7)。 しかも自律バッチは 1 回 8〜14 周を連続実行するため短時間に集中し、一部は --effort high で さらに重い。Max プランの上限はローリングウィンドウ式(短時間枠 + 週次枠)の使用量上限なので、 バッチの連続実行 + オペレータの GUI デバッグ(並行して別途消費)でウィンドウが飽和した。
  • 観測された影響。 実際にループ実行の途中(あるバッチの iteration 9〜14、別バッチの 9〜10)が agent invocation failed で連続失敗し空振りした。これが §3 の「13 回無駄撃ち」やサーキット ブレーカ導入、未コミット作業の救出(M4b・event)の直接原因。

対策(次回): バッチを小さく区切る/--effort を必要な周だけ上げる/上限に余裕のある時間帯に 回す/連続失敗サーキットブレーカで空振りを早期に止める(本実験で導入済み)。根本的には、長時間の 自律ループは 1 契約の使用上限に容易に当たるため、ループの規模(周数・effort・並行度)を上限と 照らして設計する必要がある。

9. 総括

ループは「明確に仕様化・検証可能な移植作業」では人間以上の持久力と一貫性を示し、難問の自己診断 (HTTP pivot)まで到達した。一方、ゲートが観測できない領域(GUI/ランタイム)では “green の嘘” を生む。今回の移行が完成したのは、ループの生産力に加えて、オペレータがゲートを実 DoD に 近づけ続け、ゲートの外を人手で検証したから。

single-agent-loop は「自律実装エンジン」ではなく「強力だがゲート依存の増幅器」。 ゲート設計こそが人間の主戦場、というのが本実験の結論。

Was this page helpful?