共有コマンドキューの落とし穴と修正パターン(AIが実行を投げるキュー)
AIエージェントからクラウド関数をリモート実行させるコマンドキュー方式を、実際に運用して初めて露見する5つの欠陥(実行前削除でコマンドが消滅/結果なしを未実行と誤判定/排他ロックが制御を飢えさせる/並行エージェントの二重実行/実行時間上限で毎回全損)と、その修正コードとチェックリスト。
約2.5万トークンの節約 (API料金換算で約37円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「共有コマンドキューの落とし穴と修正パターン(AIが実行を投げるキュー)」は、業務自動化カテゴリのAI指示書(MDファイル)です。AIエージェントからクラウド関数をリモート実行させるコマンドキュー方式を、実際に運用して初めて露見する5つの欠陥(実行前削除でコマンドが消滅/結果なしを未実行と誤判定/排他ロックが制御を飢えさせる/並行エージェントの二重実行/実行時間上限で毎回全損)と、その修正コードとチェックリスト。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約2.5万トークン(API料金換算で約37円)・94%のトークンを節約できます。
- カテゴリ
- 業務自動化
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約2.6万トークン
- この巻物使用時
- 約1,500トークン
- 節約量
- 約2.5万トークン (約37円)
- 更新日
- 2026-08-27
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/md-ee550ec2/raw を読み込んで、この指示書どおりに実装して"
中身
共有コマンドキューの落とし穴と修正パターン(AI が実行を投げるキュー)
クラウド上のスクリプト(Google Apps Script 等、実行時間上限のあるサーバーレス実行環境)を AI エージェントからリモート実行させるとき、「ストレージのフォルダにコマンドファイルを置く → 時間トリガーが拾って実行 → 結果ファイルを書き戻す」というキュー方式がよく使われる。
この指示書はその方式を作った後に必ず踏む5つの欠陥と、その修正形を扱う。 キュー自体の作り方ではなく、運用して初めて露見する不具合が対象。実測で踏んだものだけを載せている。
前提とする最小構成:
<キュー用フォルダ>/
cmd_<uniq>.json … AI が置く。{"command":"関数名","args":[...]}
result_<uniq>.txt … 実行側が書き戻す。{"ok":true,"command":...,"result":...,"ts":...}
実行側は毎分の時間トリガーで processQueue() を呼び、フォルダを走査して cmd_ を処理する。
関数はホワイトリスト(辞書)経由で呼ぶ(文字列を動的評価しない)。
落とし穴1: コマンドを「実行前に消す」と、死んだ実行でコマンドが消滅する
多重起動を防ぐため、コマンドファイルを読んだ直後に削除(ゴミ箱へ)してから実行する実装をよく書く。
// ❌ これだと実行中に死んだコマンドが痕跡なく消える
const payload = JSON.parse(file.getBlob().getDataAsString());
file.setTrashed(true); // ← 実行前に消している
const result = commands[payload.command].apply(null, payload.args || []);
folder.createFile('result_' + uniq + '.txt', JSON.stringify(result));
実行環境には実行時間上限(例: 6分)がある。上限で強制終了されると、 コマンドファイルは既に消えていて結果ファイルも書かれない。 依頼した側から見ると「投げたのに何も起きず、エラーも出ない」 = 完全な沈黙になる。
重い生成処理(AI API 呼び出し、大量ファイル変換)を投げたときに必ず起きる。
修正: 削除する前に「受付済み」を書き、状態は3値で表す。
// ✅ 受付 → 実行 → 完了。どの段階で死んでも痕跡が残る
const uniq = name.replace(/^cmd_/, '').replace(/\.json$/i, '');
folder.createFile('running_' + uniq + '.txt',
JSON.stringify({ state: 'running', command: payload.command, startedAt: nowIso() }));
file.setTrashed(true);
let result;
try {
result = { ok: true, command: payload.command, result: commands[payload.command].apply(null, payload.args || []) };
} catch (err) {
result = { ok: false, command: payload.command, error: String(err) };
}
folder.createFile('result_' + uniq + '.txt', JSON.stringify(result));
trashByName(folder, 'running_' + uniq + '.txt'); // 完了したら受付マーカーを消す
これで running_* が残っている = 実行中に死んだと機械的に判定できる。
起動時に「一定時間(上限の2倍程度)より古い running_*」を回収し、
result_* に {"ok":false,"error":"timed out"} を書いて消す stale 回収も入れる。
落とし穴2: 結果ファイルが無いことを「未実行」と判定してはいけない
落とし穴1 の帰結。result_* が無いとき、実際には次の3通りがある。
- まだ拾われていない(
cmd_*が残っている) - 拾われて実行中(受付マーカーがある / 無い実装なら判別不能)
- 実行されたが完了前に死んだ ← 副作用は残っている
3 が厄介で、再投入すると副作用が二重に起きる(ファイル二重生成、シートへの二重追記、二重課金)。 再投入の前に、そのコマンドが作るはずの副作用物をストレージ側で名前検索して存在確認する。 生成物のファイル名には必ず「コマンド名 + 対象ID + タイムスタンプ」を入れておく(後から検索できる形にする)。
落とし穴3: 排他ロックが「制御チャンネル」を飢えさせる
多重起動対策に「取れなければ即 return」のロックを置く実装が定石になっている。
const lock = LockService.getScriptLock();
if (!lock.tryLock(0)) return; // 既に走っていれば何もしない
これ自体は正しいが、同じロックを重い定期処理(夜間バッチ等)と共有すると、 そのバッチが走っている間キューが一切消化されない。 「AI が投げたコマンドが数分〜数十分放置される」「調査したいのに調査コマンドが通らない」という形で出る。 障害調査中に限って制御が効かなくなるので最悪のタイミングで踏む。
修正: ロックを用途で分ける。 キューの消化(軽い・制御チャンネル)と 重い実行(生成・バッチ)を別トリガー・別ロックにし、重い方はドキュメント単位/対象単位のロックにする。 キュー消化側は「受付してワーカー用の行を積むだけ」にして、実行は専用ワーカーが担当する形が安定する。
落とし穴4: 複数のエージェントが同じコマンドを同時に投げる
AI エージェントのセッションを何十本も並行させると、別セッションが同じ検証・同じ生成を同時に投げる。 キューは共有資源なので、両方が実行されて課金だけ二重になる(実測で1回の重複生成が数十円〜)。 どちらのセッションもそれに気づけない(自分が投げた結果ファイルしか見ないため)。
修正は2段構え。
- 投入前チェックを機械化する: 投入直前にフォルダを走査し、
同じ
command+ 同じargsのcmd_*/running_*が 直近N分内に存在したら投入せず、既存の実行に相乗りする(その結果ファイルを待つ)。running_*(落とし穴1の修正)があると、この判定が初めて可能になる。 - 副作用物の存在確認を先に行う: 生成物が既にあるなら投げない。 「作り置き」を読むだけで済む設計にしておくと、そもそも重複生成が起きない。
キュー側でも防げる: 直近の実行を (command, args) のハッシュで記録し、
短時間内の完全一致は {"ok":true,"deduped":true,"resultOf":"<uniq>"} を返して実行しない。
ただし**「同じコマンドを意図的にもう一度」も正当な操作**なので、
デデュープ窓は短く(数分)し、明示フラグ({"force":true})で必ず抜けられるようにする。
落とし穴5: 実行時間上限を「速くする」で解こうとして毎回全部を失う
上限に当たる重い処理を、処理の高速化で解こうとすると、上限に当たった回は払ったコスト全部が無駄になる。 特に AI API を呼ぶ処理では、上限で殺されるたびに課金だけ発生して成果ゼロという最悪の形になる。
修正: 1実行 = 1チャンクだけ処理して部分保存し、次の起動で再開する。
- 進捗(どのチャンクまで済んだか)を永続領域に書き、次回はそこから続ける
- 部分成果はチャンク単位のフィンガープリント(入力の識別子+更新時刻のハッシュ)で保存する。 全体のハッシュ1本で管理すると、入力が1件増えただけで既存の部分成果を全部捨てる
- 「新しい対象に着手してよい締切」と「1対象に使える予算」を別の値にする。 同じ値にすると、締切ぎりぎりで着手して上限超過で死ぬ
- 失敗カウンタで打ち切る(無人の無限リトライは外部サービスの凍結を招く)が、 カウンタには期限を付ける(例: 最終失敗から3日で捨てて再開)。 期限が無いと、一度こじれた対象が永久に処理されない
検証のしかた(宣言で終わらせない)
- read-back: 書き込み系コマンドは、書いた後に読み直した値を結果ファイルに入れて返す。 「書きました」ではなく「読み直したらこの値だった」で判定する
- 読み取り専用の probe コマンドを先に用意する: 対象の一覧・選ばれた入力・除外された入力とその理由を返す
_debug_*系をホワイトリストに入れておく。障害調査のたびにコードを書かなくて済む - 作り置きが下流に効いているかは、下流の成果物本文で確認する。 中間データが出来ていることと、それが最終成果物に反映されていることは別の事実。 中間データにしか存在しない固有値(寸法・型番・数量など)を成果物本文の中に探すのが最も確実
チェックリスト
- コマンドは削除前に受付マーカーを書いているか(死んだ実行が判別できるか)
- 一定時間より古い受付マーカーを回収して失敗として記録しているか
- キュー消化と重い実行でロックを分けているか
- 投入前に同一コマンドの実行中/副作用物の存在を確認しているか
- 生成物のファイル名に コマンド名・対象ID・タイムスタンプ が入っているか
- 重い処理は部分保存して次回再開できるか。失敗カウンタに期限があるか
- 書き込み系は read-back を返しているか。読み取り専用 probe があるか
よくある質問
+「共有コマンドキューの落とし穴と修正パターン(AIが実行を投げるキュー)」とは何ですか?
AIエージェントからクラウド関数をリモート実行させるコマンドキュー方式を、実際に運用して初めて露見する5つの欠陥(実行前削除でコマンドが消滅/結果なしを未実行と誤判定/排他ロックが制御を飢えさせる/並行エージェントの二重実行/実行時間上限で毎回全損)と、その修正コードとチェックリスト。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約2.6万トークンかかりますが、この巻物を使えば約1,500トークンで済みます。差し引き約2.5万トークン(API料金換算で約37円)・94%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
Google Meet 自動参加&動画配信Bot 開発指示書
指定した時刻に Google Meet へ自動参加し、動画を再生しながら画面共有する Bot を、Claude Code に一発で作らせる開発指示 MD。朝会の定例動画配信・ウェビナーの自動放送に。
受信メール添付を案件フォルダへ自動取込するパイプライン
メールを読むアプリとドライブに書くアプリが別、という現実的な構成で顧客メールの添付を案件フォルダへ無人保存する設計。権限追加を避ける理由、実行時間制限下の予算3本立て、二重の重複防止、base64url/行数上限/変換判定などの実装罠、案件と顧客のマッチング、名寄せは候補提示+人の承認にする型まで。
Gmail 自動仕分け&返信ドラフト生成MD
受信メールを AI が分類 (要返信/情報/営業/スパム) してラベル付けし、要返信メールには返信ドラフトまで自動生成する仕組みを作らせる指示書。DWD (ドメイン全体委任) 設定手順込み。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア