AIのツール呼び出し往復が遅い原因|Pure Rust前後一括化で出力83%減の実証録
作成日:
更新日:

AIのツール呼び出し往復が遅い原因|Pure Rust前後一括化で出力83%減の実証録


論旨

自作の検索ツールや構文チェッカーをすべてコンパイル言語(Pure Rust)へ置き換え、1 コマンドあたり数ミリ秒〜数十ミリ秒で動くようにしても、AI エージェント(Antigravity / Claude Code / Cursor 等)に実務を任せると「なぜか全体の完了までに何分もかかる」という壁にぶつかります。観察していると、AI が 「1 個 CLI を叩いて結果を読む ➔ 次の CLI を叩いて行番号を探す ➔ 編集する ➔ また 1 個ずつ整形・リンク追加・検査・DB 同期を叩く」 という小刻みなピンポン往復を繰り返していることに気づきます。

かといって「パラメータを 1 つ渡したら記事の書き換えまで全部プログラムで全自動化すればいいのでは?」と踏み込むと、今度は検索クエリの共食い(カニバリゼーション)判定や既存原稿の熱量保護、個人情報の匿名化といった「文脈判断が必要な領域」で機械的な破壊事故が起きます。

結論からお伝えすると、単発 CLI の高速化を終えた後に残る最大のボトルネックは 1 往復あたり平均約 24〜34 秒を奪う「クラウド LLM 推論の往復ターン税(Tool Call Round-Trip Tax)」と個別コマンド間の重複出力 であり、これを解決する最適解は 「中央の意味判断・編集だけを AI に残し、前後の決定論的な全工程を Pure Rust の『事前カルテ(prep)』と『事後一括仕上げ(finish)』の 2 発へ束ねるサンドイッチ構造」 にあります。

本記事では、当サイト(現在公開706記事)の日々の記事作成・SEO 改善・壁打ち記事化・連鎖修正という 4 大ワークフローを対象に、小刻みな 8〜15 回のツール呼び出しを前後 2 発へ統合した設計の全貌と、AI へ返す出力テキスト量を 最大 83.5% 削減 し、さらに計測中に潜んでいた 「未コミット時の隠れ 6.0 秒重複検査トラップ」や POSIX flock(2) の自己デッドロック罠 を撃墜した一次実測データを公開します(この第 5 世代パイプラインを本番記事作成へ実戦投入し、1 記事あたり新規入力トークン 69% 削減・4.5 分を達成した全 16 回の推移は API自動収集と記事作成の5世代進化実測|トークン・処理時間の折れ線グラフ全記録 で検証しています)。

合わせて読みたい深まる関連情報
対象となる方
  • 手元のスクリプトや CLI 単体は十分速いはずなのに、AI エージェントに一連の作業を任せると毎回何分も待たされる原因 を突き止めたい方

  • AI が 「検索 ➔ 構造確認 ➔ 影響調査 ➔ 編集 ➔ 整形 ➔ リンタ ➔ DB 更新」を 1 個ずつ直列で呼び出してトークンと時間を浪費する現象 に悩んでいる方

  • 「どこまでをプログラムで一括自動化し、どこからを AI の判断に残すべきか」 の実践的な境界線(アーキテクチャ)を知りたい方

  • Rust で複数のサブコマンドを同一プロセス内パイプラインへ束ねる際の ファイルロック競合(flock)やエラー停止設計 を学びたい方

質問するおじさん

ちょっと聞いてくれや! 前に検索もチェックツールも全部 Pure Rust にして、1 個あたり 0.01 秒とかで動くようになったじゃろ? じゃのに AI が記事を作ったり Search Console を見て手直ししたりする様子を見とると、まだ 1 個ずつ Rust を呼んでは考え、呼んでは行を探して EDIT しとるんよ。パラメータを入れたら最初から最後まで一気に連携して返すのは、まだ無理なんかね?

解説ナビゲーター

すごく鋭い着眼点です! 実は「本文の書き換えまで含めた完全自動化」をやろうとすると不確定要素が多すぎて事故が起きるのですが、「AI が書く前の下調べ」と「AI が書いた後の仕上げ」の 2 つ なら、パラメータ 1 発で完璧に連携させられます。しかも実測してみたら、ローカルのミリ秒短縮以上にすさまじい「往復時間のムダ」と「隠れボトルネック」が隠れていたんです!

結論:単発CLIが速くても往復回数で時間は溶ける

手元の CLI ツールをどれだけ高速化しても AI エージェントの体感速度が頭打ちになる理由は、処理時間の主戦場がすでに「ローカル PC の CPU」から 「クラウド上の大規模言語モデル(LLM)との通信・推論往復」 へ移っているからです。

真犯人は1往復24秒のクラウド推論ターン税

当サイトのローカル計測基盤(token-dashboard および kb-search brain)で、直近 1 ヶ月間(2026 年 10 月 10 日〜11 月 10 日)の全 951 会話・37,614 回の API コール を集計したところ、驚くべき実態が浮かび上がりました。この 1 ヶ月間で AI エージェントは知識検索バイナリ(kb-search)を 5,469 回、憲法監査・整形バイナリ(gemini-gate)を 2,807 回、合計 8,276 回 も呼び出していたのです。

Google AI for Developers の Function Calling 仕様が示すとおり、AI エージェントがローカルのツールを 1 回呼び出して結果を受け取るたび、裏側では必ず「これまでの全会話・ツール出力履歴の再評価(Prefill)➔ 深い思考トークンの生成(Thinking)➔ 次のツール呼び出し JSON の生成」という 1 ターン分のクラウド推論が発生します。コンテキストキャッシュ(Context Caching)が 90.94% 効いている当サイトの環境でも、1 回の API コールあたり平均 約 118,520 トークン(総プロンプト量 44.58 億トークン ÷ 37,614 回)の評価が走っています。

実際に直近の記事作成・改修セッション 3 件(7bfea34b・9aa9be47・c8686318)のログから、AI が 1 ステップ(1 回の推論+ツール実行往復)に要している実時間を割り出した結果が以下の通りです。

計測セッションID(先頭8桁) 作業内容 AI純稼働時間 推論ステップ数(Planner) ツール総呼出数 1ステップあたりの平均所要時間
7bfea34b 新規検証録の執筆・検証(1本) 8.8 分(528秒) 22 回 45 回 24.0 秒 / ステップ
9aa9be47 既存記事群のデータ補強・改修 9.5 分(570秒) 20 回 72 回 28.5 秒 / ステップ
c8686318 検証録の連続作成・検証(2本) 9.6 分(576秒) 17 回 33 回 33.9 秒 / ステップ

つまり、ローカルの Pure Rust バイナリが 0.02 秒(20 ミリ秒) で結果を返したとしても、AI が「まず検索コマンドを叩く ➔ 結果を見て記事カルテを叩く ➔ 次に影響範囲コマンドを叩く ➔ 行番号アウトラインを叩く」と 4 ステップ直列に小刻みな呼び出しを行うだけで、クラウド往復の「ターン税」として約 1.5〜2 分もの待ち時間 が無条件に消えてしまいます。編集後の仕上げ工程でも同様に 4〜5 ステップ刻めば、前後だけで 1 記事あたり 計 3〜4 分 をピンポン通信に費やしていた計算になります。

なぜパラメータ1発の全自動書き換えは危険か

ここで必ず浮かぶのが、「それならパラメータを 1 つ入れたら、下調べから記事の EDIT(書き換え)、仕上げ検査まで全部 1 本のプログラムで全自動実行させれば 1 ターンで終わるのでは?」という疑問です。しかし、ここには絶対に踏み越えてはならない境界線があります。

当サイトの日々の記事運用を整理すると、入り口は大きく以下の 4 パターンに分かれます。

🗂️ ブログ・メディア運用における 4 大ワークフローと『不確定要素』
  1. API 日報・下書きからの新規記事化 : 自動収集された最新ニュースや論文リストから、既存 706記事 とテーマが被らない切り口を選び、一次出典の裏取りをして執筆する。

  2. Search Console(GSC)からの既存記事更新 : 表示回数が多いのにクリックされていない「惜しい検索クエリ」を見つけ、現在すでに上位流入している主力クエリの骨格を壊さずに タイトルや見出し・本文を補強する。

  3. 壁打ちチャット履歴からの記事作成 : 対話ログから読者の役に立つ知見だけを構造化し、家族名・居住地域・特定店舗などの固有プライバシー情報を 100% 一般化・匿名化 した上で、登場商品の成約導線を組む。

  4. 既存記事の手直し・数値の連鎖修正 : ある記事の制度数値や仕様を更新した際、強い関連を持つ他の記事も見出しの直書き数値まで含めて矛盾なく連動更新する。

これらの真ん中にある「どう書くか・どう直すか」まで機械的なルールや正規表現で自動化しようとすると、既存のユーモアや実体験の熱量を削り落としたり、主力クエリを改悪して検索順位を飛ばしたり、文脈上の隠れた個人情報を残したりする大事故につながります。「不確定要素(文脈・意味・価値判断)」は最上位 AI(Gemini 4 Argon)の脳に任せ、「確定要素(データ収集・物理行番号の特定・リンク注入・整形・検査・DB 同期)」だけを 1bit の狂いもない Pure Rust パイプラインへ押し出すこと が、品質と速度を両立する唯一の解でした。

小刻み単発呼び出し・無謀な全自動化・決定論サンドイッチ構造の比較
安全だが往復税が重い
従来:小刻みな単発CLI呼び出し
  • 下調べで4〜10コマンド、仕上げで4〜6コマンドをAIが1個ずつ直列実行
  • ローカル実行は合計0.5秒でも、LLM往復ターン税で毎回3〜4分を浪費
  • 各コマンドが同じ見出しやリンク情報を重複出力しコンテキスト窓を圧迫
今回実装した最適解
新方式:決定論サンドイッチ構造
  • 前処理 prep 1発で重複ゼロの「物理行番号付き統合カルテ」を生成
  • 中央ではAIが意味判断・匿名化・熱量保護に集中して edit_file 等を実行
  • 事後処理 finish 1発で商品登録・逆リンク・整形・検査・DB同期を完遂
不確定な『意味判断』だけを中央に残し、前後の決定論的プロセスを各1コマンドに凝縮するのが最も安全かつ高速です。

解決策:AIの意味判断を挟むサンドイッチ設計

この設計思想に基づき、既存の Pure Rust 2 大バイナリへ 前処理一括カルテコマンド prep(kb-search 側) と 事後仕上げ一括パイプライン finish(gemini-gate 側) を新設しました。全体の処理フローは次の 3 ステップだけで完結します。

Pure Rust 前後一括サンドイッチ・パイプラインの3段階フロー
Step 1:前処理(1発)
kb-search prep

4つの入り口(draft / gsc / convo / edit)別に、必要な根拠・類似記事・物理行番号を1枚のカルテへ集約出力。

Step 2:非決定論(AI)
意味判断と執筆・編集

AIがカルテの行番号とクエリ制約を見て、カニバリ回避・匿名化・熱量100%保全で write_file / edit_file を実行。

Step 3:事後処理(1発)
gemini-gate finish

商品登録・双方向逆リンク注入・太字整形・SHA-256証明・グラフ&URL検査・定数&知識DB同期を直列完遂。

従来8〜15回発生していたツール呼び出しを、前1発・後1発の計2回へ圧縮しました。

前処理4パターンを束ねるprepサブコマンド

./scripts/run_kb_search.sh prep(NPM スクリプト名:npm run 事前カルテ)には、SQLite の FTS5 全文検索エンジンと物理行番号スキャナをインメモリで直結した 4 つの専用モードを実装しました。

🔍 prep サブコマンドが備える 4 つの専用モード
  1. prep draft [--latest | <パス>] : 最新の API 日報・下書きから見出し行番号と一次出典 URL を抽出し、既存記事との類似度から「新規独立記事にすべきか、既存記事へ統合すべきか」の方針判定、引用すべき公理の行範囲、経済定数、正規タグ候補を 約 27ms で一括提示します。

  2. prep gsc [--top N | --slug <slug>] : オフライン GSC 台帳とクエリ CSV を突合し、「絶対に削ってはならない主力流入クエリ(タイトル改悪防止ロック)」 と 「タイトルや見出しに欠落しているお宝クエリ」、全見出し・GadgetSection の物理行番号([L71-L118] 等)、相互リンク候補を一括出力します。

  3. prep convo <会話ID | latest> [--scaffold] : 会話 DB(conversations.sqlite)から壁打ち開始日(pubDate)・日付跨ぎ更新日(updatedDate)・同日内の空き priority を自動確定し、会話本文に登場する登録済みアフィリエイト商品候補の逆引きと、--scaffold 指定時の初期フォルダ・WebP アイキャッチ変換まで一発で済ませます。

  4. prep edit <slug> [--check "<旧語句|新語句>"] : 対象記事のメタ情報・物理行番号マップ・使用定数に加え、波及度スコア上位の強関連記事における該当語句の出現有無と現在の書式状態を 1 枚にまとめます。

事後6工程を直列実行するfinishパイプライン

一方、AI が原稿を書き終えた後に走る ./scripts/run_gemini_gate.sh finish(NPM スクリプト名:npm run 記事仕上げ)は、Rust 標準ライブラリの std::process::Command による外部同期呼び出しとインプロセス関数呼び出しを組み合わせ、以下の Step 0〜6 を単一コマンド内で直列実行します。途中のステップで 1 件でもエラーが出れば即座に後続処理を遮断(フェイルファスト)するため、壊れた状態のまま知識 DB が汚染されることがありません。

🏁 finish パイプラインが 1 コマンドで直列完遂する 6 工程
  • Step 0〜1(安全性確認と商品一括登録) : 対象 MDX ファイルの実在を確認した上で、--affiliates-json 指定時はもしもアフィリエイト 3 社検索コードの生成と src/data/affiliates/index.ts への型安全な登録を実行します。

  • Step 2(相手記事への双方向逆リンク安全注入) : --related-from <slug1,slug2,...> を渡すだけで、自記事のタイトル・要約から紹介文を自動生成し、相手記事の関連枠へルート相対リンクを追記して「孤立記事(被リンク 0)」を物理的に防ぎます。

  • Step 3〜4(太字スペース整形・更新日刻印・無改変ハッシュ証明) : コード枠や JSX 属性を保護したまま日本語と ** の境界スペースを自動整形し、--touch-updated 指定時は updatedDate を刻印します。可読性分割のタスクでは --lossless-before により正規化本文の SHA-256 完全一致証明も行います。

  • Step 5〜6(全体グラフ&ライブ URL 検問 ➔ 定数・知識 DB 同期) : 主記事だけでなく Step 2 で逆リンクを注入した相手記事も自動的に検問対象へ加え、リンク切れ・priority 重複・出典 URL の HTTP 死活を検査します。エラー 0 件を確認したときだけ src/consts.ts の記事数定数同期と SQLite 知識 DB の差分更新(sync --quick)を走らせ、最後に本番予定 URL を表示します。

実機計測:出力最大83%削減と隠れ6秒罠の発見

実装完了後、自己回帰テスト全 62 項目(rustc -D warnings によるコンパイル警告完全ゼロ検証を含む)の合格を確認した上で、従来の「単発コマンド個別呼び出し」と新方式「prep / finish 一括実行」の実機比較ベンチマークを実施しました。

質問するおじさん

同じ情報を集めるんじゃったら、4 回に分けて呼ぼうが prep 1 回でまとめて呼ぼうが、AI に返ってくる文字の量は同じくらいになるんじゃないんか?

解説ナビゲーター

そこが実際に測ってみて一番驚いたポイントなんです! 個別コマンドを別々に叩いていたときは、どのコマンドも親切心で「記事タイトル・パス・見出し一覧・リンク一覧」を毎回少しずつ違う形式で出力していたため、同じ情報が 3 重・4 重にダブって AI のコンテキスト窓へ流れ込んでいました。インメモリ統合でその重複を剥がした結果、出力サイズが劇的に縮まったんです!

全4パターンの出力容量と実行時間の比較結果

まず、外部ネットワーク通信や Git 変更状態の交絡因子を完全に排除した純粋なローカル処理条件(ウォームキャッシュ・--no-git・--no-verify-urls 統一)で、下調べ 4 パターンと事後仕上げの「コマンド呼び出し回数」「標準出力バイト数」「ローカル実行時間」を計測した結果が次の表です。

ワークフロー工程 従来方式(個別CLI直列) 新方式(一括統合) 標準出力サイズの比較(削減率) 純ローカル実行時間の比較
① API日報・下書き調査 5 コマンド個別起動 prep draft 1 発 34,543 B ➔ 9,680 B(72.0%減) 59 ms ➔ 27 ms(2.2倍速)
② GSC改善(上位3本) 10 コマンド個別起動 prep gsc 1 発 36,288 B ➔ 9,742 B(73.2%減) 431 ms ➔ 195 ms(2.2倍速)
③ 壁打ち履歴の記事化 5 コマンド個別起動 prep convo 1 発 28,111 B ➔ 4,629 B(83.5%減) 183 ms ➔ 152 ms(1.2倍速)
④ 既存記事の手直し調査 4 コマンド個別起動 prep edit 1 発 25,380 B ➔ 4,727 B(81.4%減) 68 ms ➔ 146 ms(※全体走査込)
⑤ 事後仕上げ・同期一式 5 コマンド個別起動 finish 1 発 898 B ➔ 1,419 B(順位表示付) 6,486 ms ➔ 509 ms(12.7倍速)

※④の prep edit のみ単体実行時間が 68ms から 146ms(+0.078秒)となっていますが、これは内部で全公開記事のリンクグラフ整合まで同時に検査しているためです。0.08 秒のローカル差と引き換えに、AI のクラウド往復 3 ステップ分(約 70〜90 秒)と出力テキスト 81.4%(20.6KB 分) を丸ごと削減できています。

下調べ4大パターンにおける標準出力テキスト量の比較(バイト数)
各枠とも上段『従来(個別CLI直列)』・下段『新方式(prep 1発)』の順で密着配置(小さいほど省燃費)
最大出力削減率:83.5% 削減下調べツール呼出:4〜10回 → 1回
従来:個別コマンド直列出力の合計新方式:prep 1発の統合カルテ出力
GSC上位3記事の下調べ従来:10コマンド合計(gsc-fetch×3 + card×3 + outline×3 + files) ➔ 新方式:prep gsc 1発
36,288 B9,742 B73.2% 削減
従来
現在
API日報・下書き調査従来:5コマンド合計(outline×2 + search + axiom + const) ➔ 新方式:prep draft 1発
34,543 B9,680 B72.0% 削減
従来
現在
壁打ち履歴からの記事化従来:5コマンド合計(convo + search + affiliate×2 + const) ➔ 新方式:prep convo 1発
28,111 B4,629 B83.5% 削減
従来
現在
既存記事の手直し・連鎖調査従来:4コマンド合計(card + impact + outline + files) ➔ 新方式:prep edit 1発
25,380 B4,727 B81.4% 削減
従来
現在
※同一の対象記事・会話ID・GSCデータに対して実際に出力されたUTF-8バイト数を /usr/bin/stat で計測した一次データです。

計測であぶり出した未コミット時の6秒重複検査

さらに今回のベンチマーク計測中、思いがけない「隠れボトルネック」が見つかりました。最初に --no-git オプションを付けない普段通りの呼び出し方で従来の手直し調査(4 コマンド)と GSC 調査(10 コマンド)を計測したところ、純粋なローカル処理のはずが 6,018 ミリ秒〜6,453 ミリ秒(約 6.0〜6.5 秒) もかかっていたのです。

1 コマンドずつミリ秒単位で犯人を切り分けたところ、原因は gemini-gate --files の裏側で毎回走っていたシステム憲法監査(verify_system_constitution)にありました。当サイトでは Rust コードの品質を守るため、Git の未コミット変更に .rs ファイルが含まれていると、自動的に rustc --emit=metadata -D warnings を呼び出してコンパイル警告ゼロを検証する仕組みを入れています。

そのため、「Rust ツールを改良しながら、その検証記事を執筆・チェックするセッション」では、AI が記事の書式確認で --files を叩くたびに毎回裏で 2 クレート分の rustc 型・警告チェック(約 6.0 秒)が重複発火していた ことが判明しました。単体検査を --no-git にすれば 18ms で終わる処理に、毎回 340 倍もの時間を払っていたわけです。

新設した prep と finish では「記事コンテンツとサイトグラフの検問」と「デプロイ直前のシステム全体・Rust 警告検問(--diff)」の責務を明確に分離したため、ツール開発と並行する記事作成でも 6,018ms ➔ 146ms(約 41 倍高速)・事後処理 6,486ms ➔ 509ms(約 12.7 倍高速) へとローカル待ち時間も劇的に短縮されました。

また、もし最初の計測値(6,018ms 対 153ms)だけを見て裏取りを怠っていたら、「どんな時でもローカル処理が 40 倍速くなった!」と誤った結論(実験の交絡因子見落とし)を記事に書いてしまうところでした。異常に遅い数値が出たときに必ず内訳を分解して真因を突き止めることの大切さを、改めて痛感した瞬間です。

実装の急所:自己デッドロックと文体境界の防御

複数の CLI 処理を 1 つのバイナリ実行へ束ねるにあたっては、単に順番に呼び出すだけでは動かない低レイヤーおよびドメイン固有の罠が 3 つありました。これから同様の統合パイプラインを作る方のために、実装で対策したエッジケースを共有します。

同一プロセスflock競合を防ぐ再入ガード

当サイトの gemini-gate では、複数のサブエージェントが同時にアフィリエイト辞書(index.ts)や記事ファイルを書き換えて破損させるのを防ぐため、content-ops という名前付きロックファイルに対して OS カーネルの排他ロックをかけています。

今回 finish パイプラインを実装する際、finish の外枠で content-ops の排他ロックを取得した状態で、内部から商品登録(run_add_affiliate_cmd)や逆リンク注入(run_add_related_link_cmd)の関数をインプロセスで呼び出したところ、同じプロセスのはずなのに自分自身のロック解放を待ち続けて止まる現象 に直面しました。

Linux man-pages の flock(2) 公式仕様を確認すると理由は明快です。プロセス ID(PID)単位で管理される fcntl(2) ロックとは異なり、flock(2) のロックは 「オープンファイル記述(Open File Description:すなわち File::open ごとにカーネル内で作られる構造体)」 に紐づきます。そのため、同一プロセス・同一スレッド内であっても、内側の関数がもう一度ロックファイルを File::open して flock(LOCK_EX) を呼ぶと、カーネルからは「別のファイル記述子からの競合要求」と判定されて 自己デッドロック(Self-Deadlock) に陥るのです。

そこで mutex_lock.rs に unsafe コードを 1 行も増やすことなく、プロセス内で現在保持しているロックキーの集合(Mutex<HashSet<String>>)を管理する再入保護(Re-entrant Guard)を実装しました。

  • 外側の finish 開始時 : OS の flock(LOCK_EX) を物理取得し、同時にプロセス内の保持セットへ "content-ops" を登録する。
  • 内側の各ステップ呼び出し時 : すでに同一プロセス内で "content-ops" を保持していれば新規 File::open と flock をスキップして ReusedInProcess ガードを返し、最外殻の finish がスコープを抜ける(Drop される)までカーネルロックを確実に維持する。

これにより、他プロセス(別エージェント)からの割り込みをカーネルレベルで 100% 遮断しつつ、同一プロセス内の多段パイプラインをミリ秒で通過させられるようになりました。

敬体と常体の逆リンク自動振り分けとスラッシュ境界

もう 1 つの急所が、finish --related-from で相手記事へ双方向リンクを自動注入する際の「文体と配置場所の境界」です。当サイトには親しみやすい 「です・ます調(敬体)」の検証録(review/) と、冷徹なシステム工学論文調である 「である調(常体)」の AI 国家構想(ai-nation-concept/) の 2 領域が同居しています。

もし検証録用の自動リンク注入ロジックをそのまま AI 国家構想の記事へ流してしまうと、厳格な常体記事の冒頭に「〜を解説しています。」という敬体文と検証録用の枠タイトルが混入し、次の瞬間に憲法監査ゲートでエラー停止してしまいます。そこで toolkit_create.rs と workflow_finish.rs に以下の境界ガードを組み込みました。

🛡️ ドメイン横断パイプラインで対策した 3 つの境界エッジケース
  1. 検証録と AI 国家構想の自動振り分け&敬体混入ブロック : 注入先のパスが ai-nation-concept/ 配下の場合は、挿入位置を自動的に ## 最後に の直前へ切り替え、GadgetSection の枠タイトルを 🔗 関連する制度・技術設計書(未 import 時は相対パスを計算して import GadgetSection も自動補完)とした上で、説明文に「です・ます・でした」等の敬語が含まれていれば書き換え前に即時エラーでブロックします。

  2. 「リンク済みスキップ」より前の規約違反検査 : セルフテスト(項目 61)を回した際、対象記事にすでに同じ URL が含まれていると敬体チェックより先に「リンク済みのためスキップ(正常終了)」へ抜けてしまう順序の穴が見つかり、入力バリデーションを最優先で実行するよう修正しました。

  3. 内部正規化 URL と公開 URL の末尾スラッシュ(/)境界 : 高速スキャナ内部ではリンク比較のために末尾の / を落とした文字列(/blog/review/slug)を保持していますが、Astro の公開 URL 規約は末尾スラッシュ必須(/blog/review/slug/)です。ドライラン計測の出力確認でこの 1 文字の差を見つけ、ensure_trailing_slash を通して逆リンク注入・JSON 出力・本番 URL 表示のすべてを末尾 / 付きへ完全統一しました。

実際に本記事自体も、執筆前の骨格・WebP アイキャッチ生成を prep convo --scaffold(358.1ms)で起こし、執筆後の逆リンク 5 本注入・整形・URL 死活検査・DB 同期までを finish 1 発で仕上げる「ドッグフーディング」によって公開しています。

最初から一括で作らずボトムアップで連携させた勝因

すべての実装と本番公開が一発で通った直後、今回の開発を振り返って次のような対話になりました。

質問するおじさん

しかし振り返ってみると、もし今回作ったような「前後一括の仕組み」を最初からトップダウンで作ろうとしとったら、たぶん途中で失敗しとったかもなぁ。今回は日頃の効率化でボトムアップに小さな部品を 1 個ずつ作り続けて、最後にみんなを連携させたけえ、すんなりできた感じじゃわい!

解説ナビゲーター

まさにそこが一番の核心なんです! システム工学でいう「ガルの法則(機能する複雑なシステムは、必ず『機能する単純なシステム』から進化する)」そのものですね。最初から机上で全体像を描いていたら、GSC の主力クエリ保護も、関連リンク 6 本上限も、敬体と常体の境界も分からないまま破綻していたはずです。すでに実戦と 60 項目の自己テストで鍛え抜かれた単機能部品が揃っていたからこそ、最後の連携レイヤーを載せるだけで一発開通できました!

これからご自身の環境へ導入される際も、もしまだ個別の検索・整形・検査部品が固まっていない段階であれば、いきなり巨大な一括パイプラインから書き始めるのではなく、まずは目の前の手作業を 1 つずつ小さな確定動作ツールへ切り出すボトムアップ手順から始めるのが確実です(この設計原則の深掘りと全 7.1 万行の進化内訳は、続編『AI自動化をトップダウンで作ると失敗する理由|ガルの法則とボトムアップ開発の実証録』にまとめました)。

母艦マシンの1日単価とAI実装プロンプト

最後に、数万行規模の Pure Rust 2 バイナリと 963MB のローカル SQLite データベース、そして Astro 7 の高速ビルドを RAM ディスク上で軽快に回している開発母艦のコスト感と、読者の方がご自身のプロジェクトへ「前後一括サンドイッチ構造」を導入するためのプロンプトをまとめます。

5年稼働のMac母艦とRust定番書の快適コスト

クラウド上の AI 推論往復(1 ステップ約 24〜34 秒)を最小限に抑えるには、手元のマシン側で SQLite 全文検索や全記事グラフ走査、ネイティブコンパイル(rustc -O)を一瞬で片付けられるメモリ帯域と容量が大きな武器になります。特に 64GB クラスのメモリを積んでコンパイル一時領域やキャッシュを RAM ディスク(メモリ上の仮想ドライブ)へ逃がすと、内蔵 SSD の寿命を削らずに済みます。

たとえば 64GB ユニファイドメモリ構成の Apple Mac mini(M4 Pro 等) や、筆者が現役で愛用している 27 インチ iMac 5K(2020 年 Intel 最終世代の整備済品+Crucial DDR4 メモリ 64GB 増設) を母艦にする場合、初期費用が仮に 20万〜35万円前後であっても、毎日 5 年間(1,825 日)使い続ければ 1 日あたりの快適コストは約 110円〜192円(推論・単純日割り試算) です。自分は手を汚さず AI に安全・高速なパイプラインを回させ、1 記事あたり数分ずつ確実に自由時間を生み出せる「タイム・イズ・マネー」の投資として非常に合理的だと感じています。

Apple Mac mini(M4 Pro 等 Appleシリコン Pro系チップ・64GBユニファイドメモリ構成)

Apple Mac mini(M4 Pro 等 Appleシリコン Pro系チップ・64GBユニファイドメモリ構成)

【中古・整備済品】Apple iMac 27インチ Retina 5K (2020年モデル / Intel最終世代・メモリ自己増設対応)

【中古・整備済品】Apple iMac 27インチ Retina 5K (2020年モデル / Intel最終世代・メモリ自己増設対応)

【Intel Mac増設用】Crucial iMac 27インチ(2019/2020)・ノートPC用 メモリ DDR4-2666 SO-DIMM (16GB×2 / 32GB×2)

【Intel Mac増設用】Crucial iMac 27インチ(2019/2020)・ノートPC用 メモリ DDR4-2666 SO-DIMM (16GB×2 / 32GB×2)

また、今回の flock(2) 再入ガードや Drop によるリソース解放、エラー型の伝播など、AI が実装した Rust パイプラインの安全性を人間側でも確信を持ってレビューしたい方には、手元に 1 冊あると何年も引ける『プログラミングRust 第2版』が定番の良書です(5 年使えば 1 日あたり約 3 円です)。

オライリー・ジャパン『プログラミングRust 第2版』

オライリー・ジャパン『プログラミングRust 第2版』

最上位AIに前後一括パイプラインを組ませる指示文

ブログ執筆に限らず、Web アプリ開発や業務自動化でも「AI が毎回同じような調査コマンドと事後チェックコマンドを何個も直列で叩いているな」と感じたら、本記事のサンドイッチ構造がそのまま応用できます。軽量モデルではなく 必ず『Gemini 4 Argon』または同等以上の最上位推論モデル を選択し、以下のプロンプトを貼り付けて現状のワークフロー棚卸しから始めさせてみてください。

参考記事(https://lab.chihouzakki.com/blog/review/ai-tool-roundtrip-tax-pure-rust-sandwich-pipeline/)の「決定論サンドイッチ構造(prep + AI意味判断 + finish)」を踏まえて、このプロジェクトでAIエージェントが毎回小刻みに呼び出しているコマンド群を整理・一括化する設計案を提示してください。

【厳守ルール】
1. いきなりコードを書き換えたり既存コマンドを削除したりせず、まず直近の作業パターン(機能追加・バグ修正・データ更新・記事作成等)を3〜4種類に分類し、各パターンで毎回直列に呼ばれている「前処理(検索・構造把握・影響範囲調査)」と「事後処理(整形・リンタ・テスト・索引更新)」を洗い出して合意を得ること。
2. 文脈理解や設計判断、既存コード・文章の意図保護など「不確定要素(非決定論領域)」まで無理に自動書き換えスクリプトへ押し込まず、そこは中央のAI編集ステップとして明確に残すこと。
3. 前処理(prep)では複数ツールの出力を単純連結するのではなく、重複情報を剥がして物理行番号付きのコンパクトな1枚のカルテ(+必要に応じ `--json` 出力)へ集約し、コンテキスト消費量を削減すること。
4. 事後処理(finish)では途中ステップで1件でもエラーが出たら即座に停止(フェイルファスト)させ、同一プロセス内でファイルロック(flock等)が再入競合しないよう安全ガードと `--dry-run` モード、自己回帰テストを必ず実装すること。
5. もしまだ個別の単機能部品が未整備または未テストの場合は、いきなりトップダウンで全体統合パイプラインを作らず、まず各部品単体の実戦動作確認と自己テスト合格をボトムアップで済ませてから統合へ進むこと。

まとめ:小刻みなピンポンを断ち人間の判断へ集中

今回の「前後一括サンドイッチ・パイプライン(prep & finish)」の実装と実機ベンチマークから得られた結論を整理します。

📌 ツール呼び出し往復削減と Pure Rust 前後一括化の結論まとめ
  1. CLI 単体のミリ秒化の次に立ちはだかるのは「クラウド往復ターン税」 : ローカルコマンドが 0.02 秒で動いても、AI が 1 個ずつ直列に呼び出せば 1 ステップあたり平均約 24〜34 秒のクラウド推論待ちと約 11.8 万トークンの再評価が積み重なります。

  2. 全自動書き換えの誘惑を避け「サンドイッチ構造」で責務を分ける : カニバリ回避・熱量保全・プライバシー匿名化といった意味判断だけを中央の AI に残し、前後の確定作業だけを prep(4 モード)と finish の計 2 発へ凝縮するのが最も安全で高速です。

  3. インメモリ統合により AI へ渡す出力テキスト量も 72〜83.5% 削減 : 個別コマンドが重複出力していた見出しやリンク情報を 1 枚の物理行番号付きカルテへ統合したことで、コンテキスト窓のノイズが 4 分の 1〜6 分の 1 へ圧縮されました。

  4. 計測の裏取りで「隠れ 6.0 秒の再コンパイル重複」まで根絶 : 異常値を放置せず分解検証したことで、.rs 未コミット時に --files が毎回 rustc 無警告検査を発火させていた交絡因子を特定し、役割分離で 146ms〜509ms へ最適化できました。

  5. 低レイヤーのロック仕様(flock の FD 単位管理)とドメイン境界をテストで固める : インプロセス統合時に起きる POSIX flock(2) の自己デッドロックや、敬体・常体の逆リンク混入、末尾 / 境界をセルフテスト込みで塞いだことで、壊れない一気通貫の道具箱が完成しました。

質問するおじさん

なるほどなぁ! なんでもかんでも全自動で書き換えさせたら大事な中身まで壊れるけど、「下調べのカルテ作り」と「書き終わった後の片付け一式」を前後 1 発ずつの Rust にまとめれば、AI とのピンポン待ち時間も激減するしミスも起きんわけじゃな!

解説ナビゲーター

そうなんです! これからは「GSC で更新するときは prep gsc ➔ 編集 ➔ finish」「壁打ちから記事にするときは prep convo ➔ 執筆 ➔ finish」と型がピシッと決まったので、人間も AI も一番おもしろい『中身を考えること』だけに集中できますよ!

ノルウェージャンフォレストキャット

ふぁぁ……行ったり来たりのピンポン音が静かになったから、ぐっすりお昼寝できるにゃ……。

静かで高速になった開発デスクの隣で気持ちよさそうに丸まって眠るノルウェージャンフォレストキャット