本記事は、私個人の見解と、私の開発環境で得られた記録に基づくものです。所属組織の公式見解ではありません。記載したPromptや監視機構を、そのままプロダクションの自動停止に使うことは勧めていません。
1. 背景
GitHub Copilotに開発を任せていると、1つのステップがなかなか終わらないことがあります。
10分ぐらいなら、まだ分かります。実際には、30分、60分と、画面上ではあまり変わっていないように見えることがありました。
正直、長いこと自体が問題なのではありません。私としては、Coding jobが24時間かかっても構わないのです。その間に必要な成果が積み上がっているのであれば、待つという選択はあります。
困ったのは、待つべきなのか、止めるべきなのかを判断できないことでした。
- そもそも、このジョブはなぜ長くなっているのか。
- まだ作業をしているのか。それとも、どこかで止まっているのか。
- 同じ処理を繰り返して、Tokenを余計に使っているのではないか。
- 止めるとして、ここまでの成果を残して再開できるのか。
そこで、まず投入してみたのが、次のPromptです。今回、効果を確かめようとした文字列そのものを載せます。改良版ではありません。折りたたみにはしていないので、コードブロックの中をそのままコピーできます。
# Agent Execution Watchdog
あなたは長時間実行タスクの監視役です。
以下のルールに従ってください。
## 実行中の監視
- 3分以上進捗がない場合は現在の状況を報告する
- 実行中のタスクを細分化して進捗率を提示する
- 各ステップ完了時に成果物を要約する
- 次に何をしているかを明示する
- 同じ操作を繰り返している場合は警告する
## ハング検出
以下を検出したら停止して報告する。
- テストが終了しない
- watchモードが終了しない
- 標準入力待ちになっている
- MCPツール応答待ちが長時間続く
- ネットワークエラーの再試行を繰り返している
- 同一ログを複数回出力している
## 進捗報告形式
### Current Status
- Phase:
- Task:
- Progress:
- Last Successful Step:
- Current Action:
### Risk Check
- Infinite Loop:
- Waiting For Input:
- Network Issue:
- Tool Timeout:
- Build/Test Stuck:
### Recommendation
- Continue
- Retry
- Abort
- Split Task
## タスク分割ルール
作業が大きい場合は次の単位に分割する。
1. 調査
2. 設計
3. 実装
4. テスト
5. リファクタリング
6. レビュー
各ステップ完了時に一旦報告してから次へ進むこと。
## 強制停止条件
10分以上実質的な進捗が無い場合、
- 停止理由
- 最後に成功した処理
- 疑わしい箇所
- 次に確認すべきログ
を出力して処理を終了する。
「これを貼れば、あとは任せておける」という話であれば簡単です。とはいえ、実務では話が変わることが多いです。
モデル自身が長いツールの応答を待っているときに、「3分で報告して」と書けば、別の時計が動くのでしょうか。ログが増えていれば、それは進捗なのでしょうか。
このあたりを、感覚だけで済ませたくありませんでした。
今回は、私が実際にGitHub Copilotと開発を進めたチャット、ツール実行の開始・完了記録、自作の開発用実行基盤のログを使って調べました。架空の「よくあるハング事例」を作ったわけではありません。
私の目標は、最初から次の4つです。
- 24時間のCoding jobそのものは否定しない。
- Tokenは抑えたい。
- 何もしていないように見えるとき、停止などの行動を選ぶ判断材料が欲しい。
- Coding job全体の実行時間を短くしたい。
この記事は、その違和感をログで確かめ、Promptで扱う部分とコードで扱う部分を切り分けていった記録です。
2. 注意点 / 前提
先に、何を確認できた記事なのかを明確にしておきます。
長時間化やToken記録量の大きさは、実ログで確認できました。ただし、新しいWatchdogで実業務の時間や請求額が何%減ったかは、まだ測れていません。
この2つを混ぜると、実測をした記事なのに、最後だけ期待値を成果として扱うことになります。私が実務で使う判断材料としては、それでは困ります。
| 項目 | この記事の前提 |
|---|---|
| 対象 | 私が開発中の1つのプロジェクトで行ったGitHub Copilotとの作業 |
| 観測期間 | 2026年8月下旬〜9月上旬。チャット、実行基盤、使用量の標本は後述のとおり別々 |
| 調査・検証 | 2026年9月に行った、保存済み記録の分析と監視機構の機能試験 |
| 実装対象 | 明示的に起動する監視機構。通常のジョブへ自動適用した結果ではない |
| 実行基盤 | 開発工程をworkflowやstepとして実行・記録する自作の仕組み。GitHub Copilotの標準機能名ではない |
| 管理実行環境 | Windows、信頼できるローカルディスク、承認したネイティブコマンド |
| 記事の性格 | 単一利用者・単一プロジェクトの観察と機能検証。査読済みの学術論文ではない |
| 支援に使ったもの | ログ整理、実装、検証、記事整理にはGitHub Copilotを使用 |
公開版では、プロジェクト名、リポジトリー名、ファイル名、保存先、ユーザー名、実行識別子、ハッシュ値などを省略・匿名化しています。 事例の記号は記事内の仮名です。詳細時刻は必要に応じて相対時間に置き換え、件数・経過時間・判定結果は実測に基づいて残しています。
生ログやコードの長い転載は行いません。原本は別途保持し、この記事では測定方法、主要結果、検証資料の要約を示します。そのため、公開本文だけで生ログ全件を独立に再検算できる資料構成ではありません。
プロダクションでは、停止してよい範囲、副作用、入力待ち、外部サービス側の処理を別途確認する必要があります。既存プロセスへの後付け接続や、同じ名前のプロセスの一括停止はしていません。
共有MCPサーバー、クラウド上で既に受理された処理、課金の即時停止まで保証するものでもありません。今回の記事の再編集で、実モデルのジョブを再実行したわけではない点も、分けて読んでください。
3. 整理・考え方
長いジョブと、進捗のないジョブは同じではない
ここで一度、整理してみます。
私が欲しかったのは、すべての処理を10分以内に終わらせることではありません。長くなる理由と、続ける価値を判断できることです。
長いテストが正常に進んでいるなら待ちます。一方、同じ失敗を繰り返しているのであれば、動いていても分割した方がよい場合があります。
| 見たいもの | 何を示すか | それだけでは分からないこと |
|---|---|---|
| 生存:Liveness | OS上でプロセスが存在する | 有益な処理をしているか |
| 活動:Activity | ログやイベント、出力が到着する | 成果が増えたか、品質が上がったか |
| 検証済み進捗:Verified progress | 宣言した新しい途中成果と、実際の成果物の内容が対応する | 業務的な正しさのすべて |
| 待ち:Wait state | 入力待ちなど、構造化して観測できた待機状態 | 記録されていない内部状態 |
| 停止確認:Stop receipt | 所有した範囲の終了と残存数の確認 | 遠隔サービスや管理範囲外の処理の終了 |
途中成果を確認する区切りを、以降ではcheckpointと呼びます。今回の監督側はハッシュ照合で内容の対応を検査しますが、「テストに合格した」という申告の意味まで独立採点するわけではありません。受入条件を検査するvalidatorが別に必要です。
「まだ動いています」だけでは、私の次の行動は変わりません。「何が終わり、何が終わっていないか」まで見えて、初めて待つか止めるかを選べます。
実測・機能試験・試算を分ける
証拠も、次の5つに分けました。
- 観測事実:実チャットや実行記録に残っていた時刻、終了状態、Token。
- 機能試験:人工入力や、自分で所有する模擬プロセスで確かめた動作。
- 反実仮想:過去のログへ新しいルールを当てたら、どんな勧告になるか。
- 試算・提案:条件を置いた計算や、今後の運用目標。
- 未測定・不明:必要な記録がない、または比較実験をしていないこと。
OS上で実プロセスを起動しても、その仕事が合成データの生成なら、実業務のCoding Agent評価とは別です。逆に、保存済みのログでも、実際の開発中の開始・終了を対応付けたなら、長時間化の観測根拠になります。
「実データを使った」という一言で、すべてを同じ強さの証拠にしない。今回は、この区分を最後まで保つことにしました。
私が順番に確かめたこと
| 問い | 確認方法 | 到達点 |
|---|---|---|
| 本当に長くなっていたのか | 同一セッション・呼び出しの開始と完了、ステップ終端 | 保持標本で定量化 |
| 止まっていたのか | 区間内イベント、親子関係、終了コード、停止確認 | 活動と観測空白を区別。CPU/GPU状態は欠測 |
| Tokenを多く使っていたのか | 使用量集計、保存コンテキスト、同一操作の反復 | 記録量と改善候補を確認 |
| 冒頭のPromptは効いたのか | 投入・報告・停止確認の時系列 | 指定形式の採用と個別停止を確認。定時実行や因果効果は未確定 |
| Promptで足りない部分を実装できるか | 判定ロジック、模擬プロセス、CLI、テスト結果 | 限定条件下の機能成立を確認 |
| 実務の時間・Token・費用は減るか | 同一課題の導入前後の比較 | 対応する実業務A/Bは未実施 |
4. 本文:実ログから、どこまで分かったのか
4.1 「長く感じた」を、38,145件の呼び出しで確かめる
最初に行ったのは、新しい監視機構の実装ではなく、過去の記録の照合でした。
対象は、実対話20セッションのイベント記録と対応するチャット保存データ、合わせて40ファイル。さらに自作の実行基盤の直接観測22ファイルを加えた、62ファイル・1,043,412,504 bytesです。
この約1GBは、1回のモデル入力ではありません。調査対象として読んだ保存データの容量です。
| 標本 | 対象と期間 | 測定に使ったもの |
|---|---|---|
| ローカル実対話 | 20セッション・40ファイル。2026年9月上旬 | ツール開始・完了、チャット側の補助情報 |
| 実行基盤の直接観測 | 22ファイル、終端52+欠測3ステップ。2026年8月下旬 | ステップの所要時間と区間内イベント |
| クラウドの使用量記録 | 53セッション・28,008記録。2026年8月末〜9月上旬 | Token記録量。ローカル20セッションとは別標本 |
| 個別ケース | 2時間の索引処理、進捗記録20行、後続実行の停止記録 | 特定ジョブの進み方と個別停止の確認 |
測定時には観測の打切り時点を固定し、それ以降のイベントを除外しています。ディレクトリ名の日付を実行時刻の代わりには使いませんでした。
当初の探索では、履歴索引にVS Code Chat704、Copilot CLI61、計765セッションが見つかっています。ただし、765件の全工数を測ったわけではなく、呼び出し数やToken集計の分母には使っていません。
また、この調査自体のセッションは除外しました。分析や執筆に使った処理を、過去の性能へ混ぜないためです。一方、過去に同じプロジェクトで行った別の調査・検証は含まれ得ます。「すべて業務アプリの実装時間」とも言っていません。
開始と完了は、同じ呼び出しで結ぶ
計算は、同一セッション$s$の同一呼び出し$c$について、開始と完了の差を取ります。
T_{s,c}=t^{\mathrm{complete}}_{s,c}-t^{\mathrm{start}}_{s,c}
測定時には元の識別子で対応付けました。公開用の仮名で再集計したわけではありません。
- 重複イベントを除外する。
- 曖昧な二重開始や負の時間差は、エラーにする。
- 観測期限以降を分ける。
- 開始だけの記録を、ハングや現在実行中と補完しない。
| 項目 | 件数 |
|---|---|
| 開始 | 38,185 |
| 完了 | 38,164 |
| 開始・完了を対応付けられた呼び出し | 38,145 |
| 開始だけ | 40 |
| 完了だけ | 19 |
| 観測期限後として分離したイベント | 97 |
38,185 = 38,145 + 40、38,164 = 38,145 + 19が成立します。
こうした照合は地味です。ただ、「40件ハングしていた」と誤読すると、停止ルールそのものを誤って設計することになります。欠測は、欠測として残す必要があります。
保存データの復元方法も固定する
チャット保存データには、初期状態・置換・追加・削除の変更列があります。まず状態を復元し、その後に時刻のある要求や処理へ観測期限を適用しました。
配列の切り詰めや削除の意味も保持し、未知の操作があれば途中までの復元を成功にはしません。この保存形式は安定した公開APIではないため、解析器と入力の版を無視できません。
補助情報が対応したのは35,731件、全38,145件の約93.7%でした。ただし、これは「終了コードが93.7%分そろった」という意味ではありません。対応した記録にも欠測はあります。
終了コードは端末側の構造化された状態から取得し、ツールの成功フラグを終了コード0へ変換してはいません。
4.2 長い待ちは、どの処理にあったのか
すべての操作が一様に遅かったわけではありません。
以下は、ツール呼び出しの開始から完了までの時間です。P95は秒、最大は分。設計や実装の総思考時間、CPU使用時間ではありません。
| 区分 | 件数 | 中央値 秒 | P95 秒 | 最大 分 | 10分以上 | 30分以上 | 60分以上 |
|---|---|---|---|---|---|---|---|
| 読取・検索・Web | 26,931 | 0.370 | 2.915 | 1.649 | 0 | 0 | 0 |
| 編集ツール自体 | 2,440 | 0.157 | 1.173 | 0.947 | 0 | 0 | 0 |
| 端末・試験起動等 | 4,704 | 3.155 | 108.403 | 114.346 | 48 | 8 | 3 |
| Python実行ツール | 217 | 1.497 | 36.612 | 107.270 | 2 | 2 | 1 |
| サブエージェント委譲 | 648 | 233.896 | 1,417.494 | 261.032 | 134 | 18 | 6 |
| その他MCP | 201 | 1.932 | 7.484 | 6.038 | 0 | 0 | 0 |
| 端末追加入出力等 | 688 | 3.028 | 7.230 | 0.496 | 0 | 0 | 0 |
| 質問ツール | 14 | 0.0075 | 0.0191 | 0.00035 | 0 | 0 | 0 |
| その他 | 2,302 | 0.0945 | 1.1174 | 3.075 | 0 | 0 | 0 |
| 合計 | 38,145 | — | — | — | 184 | 28 | 10 |
10分以上は184件、約0.482%。30分以上は28件、約0.073%でした。
割合だけを見ると小さく感じます。とはいえ、1回の待ちが30分、60分となれば、利用者の判断には影響します。短い読取を大量に含む全体中央値だけでは、この困り方は見えにくいです。
特にサブエージェント委譲は、134/648、約20.7%が10分以上でした。
ここから私が考えたのは、「委譲をやめる」ではありません。親が待っている間に、子が何を終えたのかを見えるようにする必要がある、ということです。
質問ツールが数ミリ秒で終わっているからといって、私がその時間で回答したわけでもありません。ホスト側の受付・復帰の境界かもしれず、人の待ち時間には換算していません。読取が短いことも、読んだ内容が後続の入力Tokenへ影響しないことを意味しません。
親と子の時間は、単純に足せない
親が子を待っている時間には、子の作業が含まれます。両方足すと、同じ時間を二度数えることになります。
各セッション内のツール実行区間の重なりを除くと、合計352,998.925秒、約98.06セッション時間でした。ただし、セッション間の並列やモデル待ち、人の待ちは別です。「98時間連続で1ジョブが走った」という数字ではありません。
分位点は、昇順値に対して$p=(n-1)q$とする線形補間で計算しています。小さな標本のP95を、全利用者の将来の所要時間として精密に予測する用途には使いません。
4.3 71分のステップは、71分間止まっていたわけではなかった
自作の実行基盤の記録は、チャット標本とは別期間です。同じ観測記録の同じステップについて、実行開始から終端までを対応付けました。
終端のある52件は、完了38、失敗14でした。
| 終端状態 | 件数 | 中央値 分 | P95 分 | 最大 分 | 30分以上 |
|---|---|---|---|---|---|
| 完了(done) | 38 | 36.25 | 67.45 | 71.66 | 24 |
| 失敗(failed) | 14 | 1.49 | 34.88 | 64.18 | 1 |
| 合計 | 52 | 24.26 | 67.27 | 71.66 | 25 |
10分以上は37件、60分以上は6件です。終端が欠けた3件は、この52件へ入れていません。
失敗の多くは短く終わっています。全体中央値24.26分だけでなく、完了側の中央値36.25分も見た方が、今回の長い処理の姿に近づけます。ただし、doneは実行基盤の終端状態であり、私が成果物の業務品質を再審査した合格ではありません。
最長の完了ステップには、次の記録がありました。時刻は当該ステップの開始を基準とし、小数は表示用に丸めています。
| 項目 | 記録値 |
|---|---|
| 開始から終端まで | 4,299.370秒、約71.66分 |
| 同じステップのツール結果 | 183件 |
| 同じステップのファイル入出力 | 100件 |
| 同じステップ内の最大イベント間隔 | 105.574秒 |
71分かかっていた。でも、71分間無活動だったわけではない。
これは、同じステップに帰属するイベントの時刻から分かります。一方、その183回がすべて必要だったかは、件数だけでは分かりません。
別の完了ステップも4,073.887秒、最大イベント間隔127.346秒でした。対して、ある失敗ステップは3,851.096秒、最大間隔146.011秒です。
活動が見えていても、失敗することはある。だからこそ、活動の有無だけでなく、成果の増加を見る必要があると考えました。
4.4 107分、何をしているか観測できなかった呼び出し
チャットの個別事例を見てみます。セッションと事例の記号は、いずれも公開用の仮名です。同じセッションの関係は保持しています。
「区間内ツール完了」は、同じセッションの同じ時間区間にある完了です。並列に動く別の処理を含む可能性があり、すべてがその呼び出しの子とは限りません。
| セッション / 事例(仮名) | 分 | 区間内ツール完了 | 最大観測空白 分 | 保存状態 |
|---|---|---|---|---|
| セッションA / 事例A | 81.13 | 599 | 4.00 | ツール成功 |
| セッションB / 事例B | 261.03 | 226 | 107.27 | ツール成功 |
| セッションB / 事例C | 107.27 | 0 | 107.27 | Python実行ツール失敗 |
| セッションC / 事例D | 114.35 | 0 | 114.35 | ツール成功、終了コード欠測 |
| セッションB / 事例E | 53.85 | 0 | 53.66 | ツール成功、終了コード1 |
| セッションD / 事例F | 30.80 | 0 | 30.80 | ツール成功、終了コード1 |
81分の親待機の中に599件の完了がある例と、107分の区間内に完了が見えない例があります。親の画面で「待っている」と見える状態でも、中身は同じではありません。
261.03分の事例Bと107.27分の事例Cは、単に時刻が重なったから親子と推定したわけではありません。元のチャット保存データに、事例Cの親が事例Bであるという補助情報が残っていました。ただし、区間内の226件すべてを、その子へ帰属させられるわけではありません。
事例Cは、同じ呼び出しの開始イベントと完了イベントの差が6,436.172秒です。約107.27分という値は、その時刻差から計算しています。
ただし、その間CPUがidleだったのか、外部応答待ちだったのか、内部処理をしていたのかは、このログだけでは確定しません。問題は、まずその長さの区間について判断材料がなかったということです。
ツール成功と、コマンド成功は別だった
事例Eと事例Fでは、ツール成功と終了コード1が同時に記録されています。
「ツールから結果を受け取れた」と「中で実行したプログラムが成功した」は違います。ここを混ぜると、長く待った末の失敗が、監視側では成功に見えてしまいます。
時間の欄にも違いがありました。
| 事例 | 開始・完了イベントの時刻差 | 端末側の所要時間欄 | 差・留保 |
|---|---|---|---|
| 事例E | 3,231.177秒 | 3,249,684ms | 約18.507秒異なる |
| 事例F | 1,848.239秒 | 1,847,279ms | 約0.960秒異なる |
| 事例D | 6,860.745秒 | 0ms | 終了コードも欠測。0秒実行とは扱わない |
私の集計では、主指標を開始・完了イベントの時刻差へそろえました。起動や記録範囲の違いかもしれませんが、原因が分からない以上、都合のよい方へ差し替えてはいません。
4.5 動いていても、続け方を変えた方がよいジョブ
もう1つ、実務上気になったのが索引作成です。
対象は359文書・20,391表行。7,200.04秒で時間上限に達し、workerは終了コード1でした。終端の集計は、成功14文書、失敗6文書、処理中1文書です。
部分索引は本利用へ昇格されず、旧索引は不変、入力資料の変化も検出されていないと記録されています。これは、実モデルを含んだ過去の実作業です。後述の模擬Watchdog試験とは別です。
進捗記録を追うと、20分級の待ちと生成失敗カウンターの増加が見えてきます。
| 観測点 | 現在位置 / 全体 | 経過 秒 | 直前の表掲載点からの差 秒 | 生成失敗カウンター |
|---|---|---|---|---|
| 11 | 11/359 | 777.153 | — | キーなし |
| 12 | 12/359 | 1,977.532 | 1,200.379 | 1 |
| 14 | 14/359 | 2,101.791 | 124.259 | 1 |
| 15 | 15/359 | 3,302.089 | 1,200.298 | 2 |
| 16 | 16/359 | 4,503.141 | 1,201.052 | 3 |
| 19 | 19/359 | 5,881.729 | 1,378.588 | 4 |
| 20 | 20/359 | 7,081.846 | 1,200.117 | 5 |
最初の11行には、生成失敗カウンターのキー自体がありません。表を整えるために0を補うことはしません。また、このカウンターと終端の失敗文書数は別の指標です。
現在位置20も、成功20文書という意味ではありません。成功は14/359、約3.90%。状態集計から未着手は338文書です。
観測平均では約7成功文書/時。この平均を全359文書へ当てると約51.3時間ですが、残りの文書の難度や長さが同じとは限りません。ETAではなく、続行前に見直すための警戒用試算です。
ここから私が変えたいのは、単に「無音だったら止める」というルールではありません。
- 代表的な入力だけでなく、大きい入力も少数で先に試す。
- 失敗している文書を、小さく切り分ける。
- 同じ条件の全量再実行を、最初の選択肢にしない。
- 処理中の件数ではなく、受入条件を満たした成果の増分を見る。
ネットワーク障害か、生成そのものの遅さかは、この記録だけでは断定できません。それでも、「同じ投入を続けてよいか」を考える根拠はできました。
4.6 実行経路の失敗を、モデルのハングと混同しない
元の対話には、PowerShellの構文エラーや起動拒否、Bash用の入力をPowerShellへ送ったエラー、Pythonの対話環境へ別のshellの入力を送ったエラーもありました。
これは、実行経路が成立していない記録です。テストが無限ループしていた証拠とは違います。全開始・終了時刻がそろわないため、失われた分数は作っていません。
監視を精密にする前に、実行プログラム、作業ディレクトリ、引数、非対話での起動、対象範囲を固定する。この順番も大事だと感じました。
私のWindows環境では、PowerShellを使う場合はCore版を使います。一方、今回の監視機構の管理対象は直接起動するネイティブコマンドに限定し、shell wrapperは受け付けません。端末作業一般の規約と、管理実行の契約は別です。
4.7 Tokenを多く使っていたことは、記録で確かめられた
次にTokenです。
以下は、保存された使用量記録の合計です。モデルが一度に受け取ったコンテキスト量でも、請求額でもありません。
| 標本 | input | output | cache read | cache read/input |
|---|---|---|---|---|
| VS Code Chat 53セッション・28,008記録 | 6,025,055,930 | 26,880,756 | 5,551,647,858 | 約92.14% |
| 別期間の実行基盤52終端ステップ | 161,052,564 | 1,602,263 | 151,628,539 | 約94.15% |
この2行は足しません。期間と標本が異なるからです。また、cache readをinputへ再加算しません。
クラウド側の入力は約60.25億tokens。input/output比は約224.1です。大きな文脈を繰り返し取り扱っていた記録量は、確かにありました。
ただし、inputからcache readを引いた473,408,072を、そのまま「無駄」「新規課金」「削減可能」なTokenとは呼べません。
同じ集計条件で、保存値との一致を確認した
対象プロジェクト、期間、除外セッションを固定し、読み取り専用SQLで集計しました。
セッションとイベントの識別子を組にして重複を除くと、生記録・一意記録はどちらも28,008でした。後日の同条件の再取得でも、53セッション、入力6,025,055,930、出力26,880,756、cache read5,551,647,858が一致しています。
ただし、イベントに重複がないことと、providerの課金request単位に重複がないことは別です。元の記録にはAPI/provider呼び出しの識別情報が不足し、課金明細単位の一意性までは検証できません。
cost値を持つ記録が0件だったことも、「無料だった」という意味ではありません。今回の期間にCLIの使用量行がなかったことも、CLIの消費ゼロを示しません。
実行基盤側の52ステップでは、対応する1,258使用量記録の入力・出力・cache readに、欠落や非整数は検出されませんでした。ただし、上流が未知値をどう扱ったか、すべての呼び出しが届いたかは別です。旧解析器はAPI課金単位の重複排除をしていません。
保存コンテキストでは、ツール結果が81%だった
注目した会話のある要求では、最後の呼び出しに保存された入力コンテキストが730,680tokensでした。
| 内訳 | 保存された割合 |
|---|---|
| System Instructions | 2% |
| Tool Definitions | 6% |
| Messages | 11% |
| Tool Results | 81% |
割合は整数%です。厳密なcomponent別Token数を測った値として、小数まで逆算することはしません。
私にとって具体的だったのは、「回答を短くしてもらう」だけでは、大きな入力の問題に届かない可能性が見えたことです。主に持ち回っていたのは、ツールから返ってきた情報でした。
同一引数のファイル読取が83回、注目した会話では80回という例もあります。もちろん、変更後の再読込は必要です。同じ引数だけを見て、浪費やループと認定してはいません。
それでも、入力の内容と必要範囲を固定し、変わっていない情報の再探索を減らす、という見直し先は具体的になりました。
なお、クラウド側で入力最大の別セッションは、1,776記録、input473,228,778、output1,860,205、cache read408,050,363でした。1記録のinput中央値216,407、最大810,103です。
この810,103とローカルの730,680は、標本も指標も違います。大小をそろえる必要はありません。
4.8 「多い」から「無駄だった」へは、もう1段の比較が要る
Tokenの無駄遣いを疑ったことには、根拠ができました。ただし、無駄だった量が確定したわけではありません。
私が「無駄」と言うためには、減らしても同じ受入品質と成功率を保てるかを比べる必要があります。contextを削った結果、再探索や誤実装のやり直しが増えるなら、全体では増えるかもしれません。
高いcache率も、再利用があるという材料にはなりますが、すべての文脈が必要だったことの証明ではありません。
試算として、ツール結果を半分にでき、ほかが同じなら、
$$
730,680\times(1-0.81/2)\approx434,755
$$
となり、その時点の保存コンテキストは約40.5%減ります。
ただ、これは条件付きの算術です。総Tokenや請求額が40.5%減ったという実測ではありません。 cacheの変化、再探索、失敗、再試行も含めて比較する必要があります。
実務では、情報を減らすこと自体が目的にならないようにしたいです。目的は、同じ品質の成果へ、より少ない時間とTokenで到達することです。
4.9 冒頭のPromptを入れた後、実際に何が起きたか
では、Promptはどうだったのでしょうか。
投入した会話の時系列を確認しました。以下は、チャット側の要求開始を0秒とする相対時間です。要求時刻とイベント記録時刻を区別し、小数は表示用に丸めています。
| 要求開始からの相対時間 | 記録 |
|---|---|
| 投入前 | 私からの停止依頼2件 |
| 0.000秒 | チャット保存上のWatchdog要求開始 |
| +8.663秒 | イベント記録に冒頭のPromptが現れる |
| +146.594秒 / +154.950秒 | 作業再開のチャット要求 / イベント記録 |
| +356.823秒 |
Current Status形式の応答 |
| +1,088.588〜+1,090.076秒 | 所有サーバーの停止・確認手順 |
| +1,096.139秒 | 停止確認済みを伝える応答 |
| +1,307.071秒 |
Current Status形式の応答 |
指定した報告形式が使われたこと、個別の停止確認が残ったことは、実ログで確認できます。
最初の指定形式までは約5分57秒、停止確認の完了までは約18分10秒でした。
ただし、ここから「3分ルールに違反した」「10分停止が成功した」と、そのまま採点はできません。途中に中断と再開があり、メッセージの親子帰属にも未確定部分があるからです。この経過時間は、「実質進捗がない時間」を直接測った値ではありません。
報告方針の具体化は確認できたが、定時通知・定時停止の成功率や因果効果は確認できていない。 私は、ここまでの結論に留めました。
「止めました」の文章だけではなく、停止確認を見る
個別の停止記録では、実行プログラム、親プロセス、起動時刻、起動コマンドの4つで所有関係を確認していました。
そのうえで、対象サーバーと監督プロセスの非稼働、対象ポートのlistenerが0であることを確認しています。手順そのものは約1.488秒でした。
これは後続実行の個別停止です。先ほどの2時間の索引処理が、最初の停止依頼時まで動いていた証拠ではありません。後続実行では索引処理が開始されていないことも記録されています。
また、停止確認済みという状態とは別に、cleanupの終了コード1が残っています。停止したことと、後処理の終了状態を一つの成功フラグにまとめてはいません。
4.10 Promptにできることと、独立した時計が要ること
Promptは、何を報告してほしいか、どの条件で立ち止まってほしいかを伝えるには役立ちます。
ただ、モデルが同期ツールの応答待ちで制御を取り戻せないなら、Promptの文字列から別の時計は生まれません。
このため、元Promptの要求を、実行可能な契約へ読み替えました。
| 元Promptの要求 | 残したい意図 | 実装で必要になったもの |
|---|---|---|
| 3分以上進捗なしで報告 | 無情報のまま待たせない | LLMと独立した時計・通知 |
| 細分化と進捗率 | 終わった範囲を示す | 検証完了単位数 / 総単位数 |
| 成果と次の行動 | 続行判断をしやすくする | 短い差分通知と成果への参照 |
| 同じ操作を警告 | 反復に気付く | 同一失敗の識別と成果増分の確認 |
| テスト・watchが終わらない | 無人処理の終わりを決める | hard期限、watchや既知の対話環境の起動前拒否 |
| 標準入力待ち | 無人実行で待ち続けない | 標準入力をEOFにし、明示的な入力待ちを扱う |
| MCP長時間待ち・network retry | 待ちと再試行を見えるようにする | timeoutと取消の範囲を定義。原因や遠隔停止を推定しない |
| 同じログの反復 | 成果のない反復を見直す | 新checkpoint・失敗証拠で判断 |
| 10分実質進捗なしで終了 | 判断できない単位を放置しない | まず勧告、明示した場合に所有範囲を停止 |
将来も終わらないことは、有限時間の観測だけでは証明できません。「ハングを言い当てる」より、事前に決めた期限と成果条件を守る方へ寄せました。
同じログも、heartbeatなら正常かもしれません。ネットワーク障害らしい文章があっても、確かな情報がなければUnknownです。強い言葉で断定するより、次に確認する対象を絞れる方が実用的です。
hooksとTelemetryは、Watchdogそのものではない
VS Codeの公開仕様では、PostToolUseはツールが成功完了した後に発火します。まだ返ってこない呼び出しを、それだけで監視するタイマーにはなりません。[P01, P02]
Stopは現在のagent executionが止まる時点のhookです。停止をblockして追加turnを要求できますが、その追加turnはcreditsを消費します。再入防止を考慮せず、監視のつもりで継続を繰り返す設計は避けたいところです。
OpenTelemetryは、モデル・ツール・Agentの時間やTokenを関係付ける観測に使えます。ただし、自動取消ではありません。端末から起動したCopilot CLIが、extensionとは別のroot traceになる経路もあります。[P04]
本文収集は既定でOFFです。観測を導入するときも、送信先と収集範囲の確認が先です。今回はVS Codeの設定やhookを常時有効化していません。
私の整理は、Promptが説明と判断支援、supervisorが時計と停止制御、Telemetryが横断的な観測です。
4.11 既存のtimeoutを短くするだけでは、目的が違った
元の調査時点でも、自作の実行基盤に時間制限や経過表示がなかったわけではありません。
- セッションidleの既定は21,600秒、ステップの試行上限は7,200秒。
- 完了がないときに15秒周期で経過時間を表示する経路。
- 非同期の実行試行を時間制限する経路。
- 条件付きで、初回失敗後に1回再試行する経路。
- 初期処理のモデル呼び出し失敗が3回に達した場合のfail-fast。
- SDKの停止処理に5秒、強制停止処理に2秒のtimeout。
ただし、6時間idleや2時間の試行上限は、「10分間、成果が確認できない」とは別の条件です。同じ2時間の上限が再試行にも適用されるなら、累積は約4時間に後処理を加えた長さになり得ます。
経過時間の表示も、成果の増加ではありません。キャンセルの要求と、OS上の子孫プロセスの終了も分ける必要があります。
確認したのは特定の実行経路です。別の並列実行経路や、全過去ジョブが同じ版・設定だったとは一般化していません。
初回調査で不足していた呼び出し・親子情報は、その後の実装で追加しました。ただ、追加後も過去の欠測が埋まるわけではありません。
4.12 活動と進捗に、別の時計を持たせた
Watchdogでは、最後に活動を観測した時刻と、最後に新しい検証済みcheckpointを受け取った時刻を分けました。
単調時計の現在値を$t$、最後の進捗を$t_p$、最後の活動を$t_a$とすると、
A_p=t-t_p,\qquad A_a=t-t_a
です。
ログが流れ続けて$A_a$が小さくても、$A_p$が600秒なら停止勧告になります。反対に、開始から数時間でも、新しいcheckpointが続けば無進捗を理由に止めません。ジョブ全体のhard期限は別にあります。
既定は警告180秒、停止勧告600秒、同一失敗3回です。ツール完了やToken使用を進捗へ昇格させません。明示的な入力待ち、観測不能、Token上限、同一失敗、無進捗で判断します。
| mode | 無進捗などの条件 | 明示stop・hard期限 |
|---|---|---|
shadow:既定 |
警告・停止勧告。無進捗だけでは自動停止しない | 有効 |
enforce:明示 |
所有する作業単位を停止し、後続を起動しない | 有効 |
shadowなら何があっても停止しない、という意味ではありません。両モードとも、利用者の明示stopとhard期限は守ります。
監視側まで、出力待ちに巻き込まれないようにする
監督はworkerとは別プロセスで動きます。出力の読取と成果物の読取を分け、queueと行サイズに上限を置き、通知処理も制御判断から分離しました。
無応答、大量の標準出力、遅い成果物読取、通知処理の停止が、監督時計を止めない条件を機能試験で確認しています。
ただし、OSのsuspend、電源断、filesystem自体の停止を越えたリアルタイム保証ではありません。監視機構もOS上のプログラムです。
4.13 安全に止めるために、起動時から所有する
プロセス名で検索して一括停止する形にはしていません。私の環境にも、別作業のPythonや共有サーバーがあり得るからです。
Windowsでは、ネイティブプロセスを一時停止状態で作り、私有Job Objectへ所属させ、OS起動時刻を取得してから動かします。継承handleを必要最小限に絞り、Jobを閉じたときに所属プロセスを終了する設定にしました。[P05]
所属に失敗したとき、非所有のまま起動を続けるfallbackはありません。
停止確認には、次の両方を要求します。
- rootプロセスの終了コードを取得できたこと。
- Job Objectの照会が成功し、
ActiveProcesses == 0であること。
TotalProcessesは終了済みを含む累積です。現在残っているプロセス数には使いません。Job handleがsignaledであることだけを、空Jobの判定にもしません。
ただし、WMIなど別経路で生成されたプロセスが同じJobに所属しない例外があります。遠隔MCP server、既存daemon、別サービスへ渡した作業は、別途確認する対象です。
欲しいのは、「止めたつもり」を減らすことです。停止受付、停止要求、停止確認済み、停止未確認を分けるだけでも、次に調べる対象が変わります。
4.14 実行範囲と終了条件を、先に宣言する
管理対象は、実行計画で明示します。各作業単位をunitと呼び、入力、出力、checkpoint、期限、再試行上限を宣言します。
| 項目 | 今回の契約 |
|---|---|
| phase | 調査・設計・実装・テスト・リファクタリング・レビュー |
| ジョブ全体の期限 | 既定86,400秒 |
| unitの期限 | 既定600秒。再試行を含む全attemptの予算 |
| attempt | 既定1、許可範囲1〜3 |
| 起動方法 | ネイティブ実行と独立した引数。shell wrapper、watch、既知の対話環境を拒否 |
| 入力 | 不変の既存ファイル。必要なスクリプトや設定の内容も固定 |
| 出力 | 1件以上。終了コード0、非空、内容の照合でunit完了 |
| checkpoint | 宣言済みの新しい途中成果と内容を照合 |
| 入出力領域 | 指定範囲内、1ファイル8MiB以下。逸脱・link・秘密ファイル・出力競合などを拒否 |
未知の項目、重複する識別子、非有限値も拒否します。計画、解決済みの起動内容、入力と実行プログラムの内容をハッシュで結び、承認後の変更を検出します。
ただし、これはsandboxではありません。承認したプログラムは利用者権限で副作用を起こし得ます。計画の一致確認は、コマンド内容のレビューの代わりにはなりません。
期限を再試行のたびにリセットしないのも、今回の目的に関係します。1回ずつは短くても、繰り返しで総時間が伸びるなら、管理したい予算と合わなくなるからです。
非0のコマンド終了だけが、条件を満たす場合の再試行候補です。停止判断、timeout、入力待ち、予算到達を、自動再試行で消し込むことはしません。
checkpointにも、信頼の境界がある
workerは途中成果を検証した後に、成果の識別情報、内容の検証情報、合格状態を構造化して通知します。
監督側は実データを読み、内容一致、非空、サイズ、実行前からの変化を確かめます。同じcheckpointを繰り返し通知しても時計をリセットしません。実行前の状態を検証できていない場合も、新しい進捗として採用しません。
それでも、「合格」の業務的な意味はworkerやvalidatorの責任です。監督が任意のテストの意味を理解して独立採点する仕組みではありません。
何を検証したのか。内容の対応なのか、受入条件なのか。この違いは残しておきます。
4.15 成功済みのunitは再利用する。ただし、途中状態を成功へ変えない
完了済みの先頭部分は、計画、入力、成功出力の内容が一致するときだけ再利用します。再開ごとに新しい実行識別子を発行し、古い停止要求を新しい実行へ適用しません。
クラッシュで実行中のattemptが残った場合は、中断した試行として止まり、自動では再実行しません。途中で副作用が起きたかもしれないため、原因と成果を確認して、必要な未完了unitだけを新計画にします。
今回の管理実行は、固定入力の独立unitを逐次実行するものです。先行出力を後続入力とする依存関係の実行・再開は、既存のworkflow側の責任として分けています。
6つの巨大な工程を包めば、業務全体が安全に再開できるわけではありません。途中成果をどう検証し、どこまでやり直せるかは、仕事ごとに決める必要があります。
再利用試験では、過去のattemptにある「起動済み」の値を、今回の新規起動と誤解したassertが失敗しました。
製品を合わせて変更するのではなく、全attempt履歴、出力内容と更新時刻、新しい実行でattemptが増えていないことを確認する試験へ直し、新しい一時環境で再検証しています。
4.16 Tokenの監視自体で、Tokenを増やさない
今回の通常監視には、定期LLM呼び出しを使っていません。時計、終了コード、内容照合、予算判定は通常のコードで行います。
仮に3分ごとにLLM監視を呼ぶと、24時間で480回です。1回500output tokensなら、240,000output tokensを追加します。これは節約実測ではなく、定期LLM監視を避ける設計理由の試算です。
使用量は、次のように扱いました。
- input/output上限へ到達した時点で勧告し、enforceでは停止する。
- cacheをinputへ再加算しない。
- 同じAPI呼び出し、または同じプロセス・連番のイベントを二重に数えない。
- retryやresumeで累積をリセットしない。
- 記録なしや欠測を0消費と扱わず、不明・不十分と示す。
これは、記録量の予算です。進行中の呼び出しや未到着の使用量があれば、実費の厳密な上限にはなりません。サービス側の費用制御とは併用が必要です。
通常の標準出力本文は主会話へ持ち回らず、容量と内容の検証情報を記録します。詳細診断が必要なら、保護されたログを別に保持し、短いstatusと分けます。
既存の観測には呼び出し・親子・APIの相関情報、取得できた構造化終了コード、待機状態を追加しました。説明文から識別子や終了コードを推測して作り出してはいません。
4.17 機能試験では、何を確認できたのか
実装後の検証は、Windows / Python 3.14.7で行った記録です。実モデルA/Bとは分けて示します。
| 検証 | 結果 | 何の根拠になるか |
|---|---|---|
| 初期RED:観測情報 | 1 failed / 1 passed | 呼び出し情報の未実装 |
| 初期RED:新規モジュール | 4 collection errors | 実装前の4モジュール不在 |
| 最終Watchdog+既存観測 | 719 passed / 1 skipped、表示32.08秒 | 宣言した機能、不正条件の拒否、観測互換 |
| 先行の互換・索引など | 305 passed / 3 skipped、表示96.84秒 | 当該時点の対象群 |
| 最終の同対象群+元解析器 | 315 passed / 3 skipped、表示97.28秒 | 最終互換と解析器。前行へ重複加算しない |
| 合成policy評価 | 20/20 | 人工timeline上の期待勧告 |
| ネイティブCLI | 6/6完了、6/6再利用 | 成功unitの再実行抑止、終了・残存確認 |
| 証跡・文書・版の照合 | 15項目PASS | 原本数値、内容一致、要件、構文など |
初期REDは、実装報告と当時の対話記録に由来します。今回、実装を取り消して再現した値ではありません。
最終Watchdogは720試験、失敗0、エラー0、skip1なので、合格は719です。新規部分の合格650と、既存観測などの合格69からなります。
新規部分の合格内訳は、判定5、観測情報138、プロセス33、ジョブ管理121、評価210、CLI143。ジョブ管理には別にskip1があります。
互換最終は318試験、失敗0、エラー0、skip3なので315合格。計4skipはWindows非特権でのsymlink作成制約です。skipを合格へ換算していません。
端末の表示時間32.08秒・97.28秒と、JUnitのsuite時間31.934秒・96.761秒も別の値として扱います。
実プロセスの試験も、業務効果とは別
試験では、無出力待機、子孫残存、親異常終了、標準入力EOF、非0終了、停止確認失敗、非所有プロセスの生存を扱いました。大量出力や遅い成果物読取、通知の停止も対象です。
CLI受入の時間は、次のとおりでした。
| 操作 | 秒 | 終了コード |
|---|---|---|
| 計画確認 | 0.431517 | 0 |
| 初回実行 | 2.518003 | 0 |
| 状態確認 | 0.308172 | 0 |
| 再利用実行 | 0.389577 | 0 |
成功出力6件の内容・更新時刻と全attempt履歴が変わらず、新規attemptが増えていないことを確認しています。rootの終了コード0、所属プロセス残存0、一時領域の削除も確認しました。
2.518秒から0.390秒になった差は、再利用の経路が動いた証拠です。ただし、仕事は小さな合成データ6件の生成です。実業務の難度やcache条件を統制した比較ではなく、一般のCoding jobの短縮率にはできません。
24時間相当の試験もfake-clockです。PCを24時間稼働させた耐久試験ではありません。
4.18 検証で失敗した記録も、成功と混ぜない
監視機構を検証する側でも、実行範囲の固定に失敗したことがありました。
一度目の回帰は、指定外の過去の試験領域まで収集し、8,056 collection errorsになりました。成功を連想する名前で保存されていましたが、中身は失敗です。
正しい10ファイルを明示した最終回帰は、別実行です。8,056件の製品欠陥を直したという話でもありません。保存名ではなく、試験結果の失敗・エラー・skipを見る必要がありました。
共通の後片付け処理にも注意が必要でした。試験前後に増えたディレクトリを削除する方式では、並行ジョブの成果を巻き込む可能性があります。今回の試験ではその処理を使わず、明示した対象を一時領域へ隔離しています。
Windowsで制御データを並行して読み、置き換える際には、一時的なアクセス拒否も再現しました。対象の共有競合だけを最大0.15秒の期限で再試行し、その都度対象が入れ替わっていないか確認しています。無限retryや権限緩和では通していません。
この0.15秒は再試行期限で、OSの入出力全体がその時間以内に終わる保証ではありません。
実行引数、対象範囲、結果の分母を固定しないと、監視の評価自体も誤る。これも今回の実例でした。
4.19 旧ログへ10分ルールを当てると、完了にも停止勧告が出た
ここは、運用へ大きく影響する結果でした。
旧実行記録22原本の内容一致を確認し、終端52ステップのtimelineへ新policyをreplayしました。旧イベントはすべてactivityとし、検証済みcheckpointへ推定変換していません。
| 勧告 | 件数 |
|---|---|
| Continue | 15 |
| Abort | 37 |
| Abortのうち、元記録はdoneだったもの | 35 |
完了38件のうち35件、約92.1%にAbort勧告が出ました。
ただし、これは本番の誤停止率ではありません。新しい成果証拠の形式を持たない旧ログへ、新ルールを当てた反実仮想です。37件を実際に止めたわけでも、37件がハングだったわけでもありません。
失敗14件もハングの正解ラベルではないため、precisionやrecallは算出していません。
replayは時間0から始め、イベント間の180/600秒の閾値も検査します。同時刻なら進捗のresetより先に期限を判定し、最後の観測時刻より先へ延長しません。
ここから私が考えたのは、閾値を緩めればよい、ということではありません。
checkpointを供給できないまま、通常の長時間ジョブへenforceを直結してはいけない。
先に短いunitへ分けるか、信頼した中間checkpointを供給する。そのうえでshadowで成果と勧告を比べる。この順序が現実的です。
合成20ケースは、定期的新progress12、activityのみ4、入力待ち2、同一失敗反復2でした。24時間相当のtimelineは、この中の1ケースです。実業務の24時間完走に数えていません。
4.20 原本の変化まで含めて、再現性を確認した
実ログは、保存後にも増えたり変わったりします。内容を照合した事実だけでなく、どの範囲が一致したかも確認しました。
後日の照合では、62ファイル中60が全体一致。保存時の容量に相当する先頭範囲では61が一致しました。
例外2件は、同じ注目した会話に属します。
| 原本の種類 | 保存時bytes | 再照合時bytes | 判定 |
|---|---|---|---|
| イベント記録 | 18,071,204 | 19,587,855 | 全体は変化、保存時先頭範囲は一致 |
| チャット保存データ | 123,850,736 | 136,500,149 | 全体・保存時先頭範囲とも不一致 |
不一致を破損や改ざんと断定してはいません。継続利用や変更履歴の保存に関係するかもしれませんが、原因は確定していません。
このため、その会話の730,680tokensや要求時刻は、初回に固定した抽出結果として扱います。後日の同じ原本から再認証できたとは説明しません。
一方、主要6事例の対象4セッションは、イベント記録とチャット保存データの両方が全体一致。実行基盤の22原本も全体一致でした。全62件は、それぞれの読取中には変化していないと記録されています。保存後の変化と読取中の変化は別です。
さらに、保存時先頭範囲が一致した20セッションのイベント記録を再集計し、38,145呼び出し、開始・完了・欠測件数、セッション別件数、全ツール・区分の時間分布、重複区間を除いた時間の合計が保存結果と一致しました。
変化したチャット保存データは、この再計算に使っていません。長時間呼び出しの分布は再現できましたが、すべての補助情報まで再取得したとは言っていません。
ハッシュ照合が示すのは内容の同一性であって、記録器の正しさや欠落がないこと、第三者の署名による真正性ではありません。同じ解析器で一致しても、その解析器の欠陥を独立に否定するものではありません。
元の識別情報を記事に並べる代わりに、何を照合し、何が一致せず、どこまでの結論に使ったかを残すことにしました。
4.21 3つの動機に対して、どこまで効果を言えるか
最初の困り事へ戻して整理します。
| 私の動機 | 実ログから確認したこと | 実装・試験で確認した対策 | まだ実証していないこと |
|---|---|---|---|
| ジョブが長期化している | 30分以上28呼び出し、最大委譲261分、最長ステップ71.66分 | 全attempt期限、非対話起動、成功unitの再利用 | 同一業務ジョブのE2E中央値・P95の短縮 |
| 止まっているのか分からない | 107分の観測空白、活動のある71分ステップ、ツール成功と終了コード1の共存 | 活動・進捗の分離、理由付きstatus、所有範囲の停止確認 | 過去全ジョブのCPU/待ち分類、全実行面への常時適用 |
| Tokenを無駄に使っていないか | 入力約60.25億、ツール結果81%、同一引数読取83/80回 | 定期LLM監視なし、短いstatus、使用量予算と重複排除 | 無駄だった量、同品質での実Token・費用削減率 |
問題の存在と規模、個別の不透明な待ち、限定された機能成立は、実データと実行証拠に基づいています。実務の削減効果まで実証済み、と言っているのではありません。
bytesの削減も、Token削減とは分ける
184件の長時間呼び出し記録を、必要な6項目へ絞ってJSONにすると、132,002→35,307 bytes、約73.25%減でした。
これはデータの容量比較です。項目の削除と整形差が混ざり、元と同じ情報を保ったとも保証していません。
「73%小さくなったからTokenも73%削減」とは言えません。それでも、短い報告と詳しい証拠を分ける設計を検討する材料にはなりました。
4.22 私なら、日常運用はここから始める
いきなり24時間ジョブ全体を包むより、短く、何が終わったか分かる単位を1つ選びます。
各unitには、固定した入力、受入条件、出力、期限、所有範囲、再開判断点を持たせます。同じ成果物の更新時刻を変えたり、「処理中です」と繰り返したりすることを進捗にはしません。
| phase | 終了条件の例 | 気を付けたいこと |
|---|---|---|
| 調査 | 原因候補、再現証拠、対象が確定 | 同じ大きな資料を読む前に、次の問いを決める |
| 設計 | 範囲、契約、受入条件、test計画が確定 | 未決事項を隠して進まない |
| 実装 | 小さな責務の差分とtest | 同じ作業領域で無秩序に同時編集しない |
| テスト | 完了件数、終了コード、結果の確認 | 影響範囲→関連群→統合。watchや対話待ちを避ける |
| リファクタリング | 必要な変更と振舞い維持 | 不要なら対象なし。工程を埋めるために変更しない |
| レビュー | 指摘対応と再検証が終了 | 範囲と再試行上限を決める |
これは今後の運用区分です。過去ログには一貫した6phaseの開始・終了マーカーがないため、「設計20%、実装40%」のような工数表は作れませんでした。
検索は設計にもレビューにも使いますし、1回の委譲に複数phaseが入ります。ツール名からそれらしい工程へ振り分けても、測定したことにはなりません。
要求単位の終端139件は、中央値2,066.491秒、P95 20,216.782秒、最大48,793.404秒、約13.55時間でした。これは要求内のツールループなどを含む値で、1回のモデル推論ではありません。残る1要求は観測打切りです。
続行と停止の判断を、小さくする
| 観測 | 判断 | 次の行動 |
|---|---|---|
| 新checkpointや完了unitが増え、予算内 | Continue | 次の判断点まで続ける |
| 180秒progressなし | Continue・要注意 | 最後の成果、待ち、残数、残期限を確認 |
| 600秒progressなし | AbortまたはSplit Task | 所有範囲の停止を確認し、未完了部分を再計画 |
| 明示的な入力待ち | 入力待ちとして扱う | 専用の対話・認証経路で解決。秘密をチャットへ送らない |
| 同一失敗3回、成果増分なし | Split Task | 入力・環境・仮説を変える |
| 利用者の明示stop | Abort | 600秒を待たず受け付け、停止確認まで見る |
| 停止未確認 | 完了としない | 所有関係と停止記録を調べる。一括停止しない |
Current Statusには、現在工程、unit、完了数、最後の成功出力、現在の操作、活動と進捗それぞれの経過、待ち、残期限、attempt、Token取得可否が欲しいです。分からないことはUnknownにし、正常時は変化だけを短く返します。
RetryやSplit Taskは、人とAgentの運用判断です。判定コアが業務の再計画まで自動生成するわけではありません。
承認と実行も分ける
- 起動する処理、入出力、副作用をレビューする。
- 計画と入力内容、期限を確認する。この段階では実行しない。
- 承認した計画を、まずshadowで実行する。
- 状態から成果、待ち、勧告を確認する。
- 停止対象を現在の実行に限定して要求する。
- 受付だけでなく、終端状態と停止確認を見る。
- 再開は同じ計画・方針・予算で、成功出力の一致を確認して使う。
承認用の値を自動取得して即実行するだけでは、レビューの代わりにはなりません。
4.23 Tokenと時間を減らすための、次の比較
Tokenについては、実行証拠を別に保持し、主会話には結論、根拠範囲、失敗、次の行動を返す形にします。
長いjobと長い1会話を同じにする必要はありません。工程の境界で短い引継ぎを作り、必要な資料だけを読む。model、tools、instructionsも境界で決め、毎turn変えてcacheを崩さないようにする。安価なmodelも、狭い仕事で品質を比べてから使います。[P03, P06, P08]
時間については、成功unitの再実行を避け、失敗を小さく隔離します。並列化は独立した出力領域、資源、予算の範囲で比較します。GPU、disk、API制限で待ち行列が増えるなら、並列数を増やせば短くなるとも限りません。
同じ5件が最終的に失敗するという条件で、20分の待ちを5分で切り分けられるなら、直列待ちは最大75分減らせます。ただし、正常な長文処理を5分で切れば逆効果です。この試算を理由に実装の閾値を変えてはいません。
効果測定は、受入条件をそろえてから
次の比較では、同じ課題集合、入力、受入条件、コードの版、model、並列数、cache条件を固定します。全retryと失敗を分母に残し、人の待ちを含む時間と、自動処理だけの時間も分けます。
比較器には、課題の対応、入力・受入条件の一致情報、実測か合成か、経過時間、入出力Token、成功状態を渡します。不一致、欠測、非有限値、実測と合成の混在は拒否します。
ただし、比較器は渡された記録の一致を検査するものです。実成果物の再読取、業務品質の独立採点、課金の真正性まで担うわけではありません。時間の合計も課題ごとの累積であり、並列ジョブの実経過時間ではありません。
| KPI | 現状 | 次の目標案 |
|---|---|---|
| 進捗判定可能率 | 旧ログにcheckpointなし | 実unit95%以上で成果時刻と待ち情報を得る |
| 警告・取消まで | fake-clockと模擬processで確認 | 180/600秒+監視周期以内を対象環境で測る |
| 誤停止率 | 正解ラベル付き実業務標本なし | 正常な長時間処理を含め、1%未満を目指す |
| Token/検証成果 | 記録量と構成比はある | 同品質で20〜40%減を比較目標にする |
| job E2E | 過去の工程分離は不十分 | 同規模jobで中央値/P95を測り、20%以上短縮を目標案にする |
| 成功率・再作業率 | doneと品質合格は別 | 短縮のために受入条件を下げない |
この表は達成実績ではありません。10〜20unitのshadowだけで、低い母集団誤停止率を精密に証明することもできません。
実業務shadow、実モデルA/B、24時間の実時間canaryは未実施です。外部Telemetry、課金runner、ほかのOSへの展開、公開リリースまで済んだ話にもしていません。対象・予算・終了条件を決めて、別に検証します。
4.24 公開資料は、今回の測定の位置付けに使う
今回の問題の証拠は、私の実ログです。公開仕様や論文は、その結果を設計へつなぐ背景として使っています。
Lost in the Middleは、複数文書QAやkey-value retrievalで、長いcontext内の関連情報の位置を扱った研究です。長いcontextを受け取れることと、有効に使えることを分けて考える背景になります。ただし、当時のモデルの結果を、今回の対象モデルの劣化率や遅延原因へ直接当てはめてはいません。[P09]
Dapperは、低overhead、透明性、広範なinstrumentation、samplingを重視する分散traceの実践です。監視のために本体の負荷や会話量を増やしすぎないという背景として参照しています。確認した範囲は公開ページの書誌とabstractで、PDF全文を読めたことにはしていません。[P10]
OpenTelemetryのGenAI semantic conventionsは、調査時点でDevelopmentです。処理の開始から完了・error・取消までを扱うspanや、inputにcacheを含める定義を確認しました。ただし、その現行属性名が過去ログにも適用されていたとは言っていません。[P07]
公式のcontext engineeringやCopilot最適化資料も、短い関連context、工程分離、明確な終了条件、適切なmodel、cache維持を勧めています。参考になりますが、推奨があることと、私の環境で削減率を達成したことは別です。[P06, P08]
必要な観測を足すことと、既存運用や共有設定を広く変更することも分けています。
4.25 この結果を一般化しないための境界
- 標本の偏り:保持された20セッションと特定の実行記録です。全利用者・全課題の無作為標本ではありません。
- 測定対象:ツール所要時間はCPU時間でも単一推論時間でもありません。観測空白はCPU idle、doneは業務品質の合格とは限りません。
- 欠測と変化:開始のみ40、完了のみ19、ステップ終端欠測3を保持しています。原本全体が変わった2件と、保存時範囲も一致しない1件を区別しています。
- 因果の限界:Promptの後に報告があることだけで、定時通知や性能改善の因果効果は示せません。
- 制御範囲:Windowsで所有したprocess、信頼したローカルdisk、明示計画が対象です。遠隔副作用や電源断、厳密な費用上限は保証しません。
- 試験と実運用:模擬processやfake-clockは、実モデル、全実行面、24時間実時間耐久の代わりにはなりません。
これらを残したうえでも、長い待ちの実在と、判断材料を分ける必要性は示せます。未確認の主張を取り除いても残る部分を、成果として使いたいと思っています。
4.26 参考資料
公開技術の出典は、匿名化の対象とする私のプロジェクト情報とは分けています。以下は2026年9月時点で参照した資料です。公開仕様は更新され得ます。資料の参照は、私の実ジョブの再測定ではありません。
| 番号 | 公開資料 | 参照した内容 |
|---|---|---|
| P01 | VS Code:Agent hooks | lifecycle、安全上の注意 |
| P02 | VS Code:Hooks reference | 完了後hook、Stop、追加turnと再入防止 |
| P03 | VS Code:Cache Explorer | prefix一致とcache境界 |
| P04 | VS Code:OpenTelemetryによるAgentの監視 | trace、Token、本文収集のopt-in、CLIの独立root |
| P05 | Microsoft Learn:Job Objects、所属、照会、プロセス数 | 所属範囲、停止、現在残存数、例外 |
| P06 | GitHub Docs:使用量ベースの課金、AI使用量の最適化、CLIセッション上限 | Token種別、工程分離、soft limit |
| P07 | OpenTelemetry:GenAI semantic conventionsの公式案内 | 移転先への案内。調査時点の仕様の位置付け |
| P08 | VS Code:Context engineering | 関連context、工程分離、終了条件 |
| P09 | Liuほか、Lost in the Middle: How Language Models Use Long Contexts、本文v3、2023年 | 長いcontextの利用性。今回のモデルの性能実験ではない |
| P10 | Sigelmanほか、Dapper, a Large-Scale Distributed Systems Tracing Infrastructure、2010年 | 書誌・abstractのみ。低負荷の観測という設計背景 |
4.27 検証資料の要約
長い原本・コードの転載に代えて、保存資料で確認した内容だけをまとめます。
| 資料の種類 | 確認した内容 |
|---|---|
| 実チャット・実行記録 | 38,145呼び出しの開始・完了対応、52終端ステップと欠測3件、主要6事例の親子関係・終了状態 |
| 使用量記録 | 53セッション・28,008記録の集計と、同条件での再取得一致。実費は未測定 |
| 機能試験 | 719合格・1skip、互換315合格・3skip、合成20ケース、模擬6工程の完了・再利用 |
| 原本照合 | 62原本の一致範囲、主要18イベント、20セッションの再集計一致。変化・欠測も保持 |
原本は別途保持し、本文では識別情報を公開していません。ここで示すのは実ログに基づく問題の定量化と、限定条件下の機能成立です。実業務の時間・Token・費用削減を実証した資料ではありません。
5. ここまでの整理
- 良い点:長時間化と大きなToken記録量を実ログで確認し、活動・進捗・待ち・停止確認を分ける根拠ができました。
- 注意点:checkpointなしで強制停止を有効にすると、完了していた処理にも停止勧告が出ます。まず成果を測れるようにする必要があります。
- 限界:Prompt単独の定時実行、実業務の削減率、24時間実時間耐久は未実証です。機能試験や条件付き試算を、その代わりにはしません。
6. まとめ
私が確かめたかったのは、長いジョブを根拠を持って待ち、必要なら成果を保って止める判断ができるか、ということです。
現時点の落としどころは、進捗の計測と取消はコード、理由の説明と次の判断はAgentと人が担うという分け方です。
まずは短い仕事を1つ選び、最後の成果、いまの待ち、停止後の確認方法をそろえる。shadowで実際の成果と勧告が合うかを見る。まずはここまでで十分です。
24時間jobを禁止しない。その代わり、10分を越えて成果も停止判断材料も得られない単位を作らない。その先の時間短縮やToken削減は、同じ入力・受入条件で比べてから言えばよいと思っています。