エージェント型AIのパフォーマンスエンジニアリング(Thoughtworks)整理¶
作成日: 2026-07-15 出典 / きっかけ: Thoughtworks Insights「Performance engineering in agentic AI systems」(Divye Singh・Limansha Safreen Shaik、2026-07-06) https://www.thoughtworks.com/insights/articles/Performance-engineering-in-agentic-AI-systems 関連: ai_agent_9社_本番運用アーキテクチャ agentic_reference_architecture_評価ループ context_engineering_ast活用 dspy_現場プロンプト改善ループ_metricと所有権境界_整理 メルペイ_決済常駐aiエージェント_設計と5層防御_整理 llm学習_並列化戦略5次元_整理
0. 要点(3行)¶
- 本質: 「動くプロトタイプ」→「本番インフラ」の壁は、レイテンシ蓄積・トークンコスト・信頼性劣化・ルーティング幻覚の4つに予測可能な形で現れる。エージェントグラフを「プロンプトのデモ+α」ではなく分散システム(バリア・バックプレッシャ・障害ドメイン・可観測性を持つもの)として扱えば潰せる。
- 効く軸は絶対値でなく相対関係: 全部を最良モデルで回さない(タスク複雑度×モデル階層の相対マッチング)/点数でなく順位・近傍で分類する(KNN)/プロンプトは安定を上・動的を下に固定してキャッシュ前方一致を取りにいく。
- 貫く緊張関係: 柔軟性・決定性・レイテンシ・コストの4方向トレードオフ。1軸だけ最適化した基盤はインシデント負荷で作り直しになる。「自律的な新規性」でなく「可視性と制御」が本番で運用可能にする。
1. 全体像 — なぜ素朴な設計は「予測可能に」壊れるか¶
記事の主張を一言で: エージェント基盤の劣化は事故でなく物理。素朴な実装は次の4つで必ず詰まる。
| 壊れ方 | 原因 | 効く対策(本ノートの節) |
|---|---|---|
| レイテンシ蓄積 | 逐次実行・冗長なLLM往復 | 非同期並列化(§4)・部分決定化(§5) |
| トークンコスト増 | 全部を大モデルで・巨大コンテキスト毎回 | 右サイズ化(§2)・キャッシュ(§3)・コンテキスト選別(§6) |
| 信頼性劣化 | マージ規則・障害境界が無い | fan-in の明示マージ(§4)・構造化出力の検証(§5) |
| ルーティング幻覚 | LLMに分類させて不透明 | セマンティック類似/KNN(§7) |
設計の芯: これらは互いに独立でなく、柔軟性 ↔ 決定性 ↔ レイテンシ ↔ コストの4方向で綱引きする。例えば「全部LLM」は柔軟だが遅く高く不透明、「全部決定的コード」は速く安く再現的だが融通が利かない。どこを決定化しどこをLLMに残すかの線引きが設計の主戦場になる。
まず観測から: 最適化の前に、グラフの各ノードでレイテンシ・トークン消費・失敗率を可観測にする。測らずに最適化しない(記事の第1推奨)。
2. モデルの右サイズ化(Right-sizing)¶
一言: 「最良モデルで全部やる」をやめる。タスク複雑度とモデル能力を明示マッピングし、コード外(設定)に置いて実行時に付け替えられるようにする。
| タスク複雑度 | 例 | 割り当て |
|---|---|---|
| 低 | 意図ルーティング・ラベル分類・キャッシュ穴埋め・言い換え | 小型/高速モデル |
| 中 | RAG接地Q&A・要約・コード生成 | 中位モデル |
| 中(厳格) | 安全/ポリシー分類 | 中位・temperature 0 |
| 高 | 多段プランニング・オーケストレーション・曖昧な対話 | 大型/フロンティア |
勘所: マッピングをコードにハードコードしない。外部設定にすれば、モデル入れ替え・コスト調整がデプロイ無しでできる。これは dspy_現場プロンプト改善ループ_metricと所有権境界_整理 の「所有権境界を切る」思想と同じ — 誰が・どこで変えられるかを分離する。
3. キャッシュは2層ある — 混同しないのが最重要¶
記事は「Prompt/API response caching」を1節で扱うが、実は別レイヤの2種。ここを分けて理解するのが本ノートの一番の付加価値。
| KV/プロンプトキャッシュ(プロバイダ側) | セマンティックキャッシュ(アプリ側) | |
|---|---|---|
| 何をキャッシュ | プロンプト前方一致部分の計算結果(attention の KV テンソル) | 生成された完成レスポンスそのもの |
| キー | プレフィックスのバイト列(完全一致) | クエリの埋め込みベクトル(近傍一致) |
| 効果 | prefill 計算をスキップ(TTFT短縮・入力トークン割引) | LLM呼び出し自体を回避(生成タスク→選択タスクに縮退) |
| 外し方 | 前方1バイトでも変われば以降全滅 | 閾値割れで別クエリ扱い |
3-1. KV/プロンプトキャッシュ(前方一致の物理)¶
一言: キャッシュは前方一致。プレフィックスのどこか1バイトが変わると、その位置以降のキャッシュが全部無効。だから安定を前・動的を後に置く(→§6 で詳述)。
一次裏取り(プロバイダ実挙動):
- Anthropic(Claude): レンダリング順は
tools → system → messages。cache_control: {"type": "ephemeral"}を安定ブロックの末尾に置く。TTL は既定5分、ttl:"1h"で1時間。1リクエストにつきブレークポイント最大4つ。最小キャッシュ可能プレフィックスはモデル依存(下表)。効いたかはusage.cache_read_input_tokens/cache_creation_input_tokensで確認。モデルを切り替えるとキャッシュは無効(キャッシュはモデル単位)。20ブロックの後方探索窓があり、1ターンで20ブロック超を積むと前ターンのキャッシュを見つけ損ねて黙ってミスする。
| モデル | 最小トークン |
|---|---|
| Opus 4.8/4.7/4.6/4.5, Haiku 4.5 | 4096 |
| Fable 5, Sonnet 4.6, Haiku 3.5/3 | 2048 |
| Sonnet 4.5/4.1/4/3.7 | 1024 |
経済性: キャッシュ読み ≈ 通常入力の 0.1倍、書き込みは5分TTLで1.25倍・1時間TTLで2倍。損益分岐は5分なら2リクエスト、1時間なら3リクエスト。
- OpenAI: 1024トークン以上のプロンプトで自動有効。先頭1024が完全一致し、以降は128トークン刻みで一致を拾う。ルーティングは先頭〜256トークンのハッシュで決まり、
prompt_cache_keyでヒット率を上げられる。技術的には attention 層の KV 射影をキャッシュする(Anthropicと同型)。
サイレント無効化の犯人(Anthropic のチェックリスト): system プロンプトに datetime.now()/UUID を差し込む、json.dumps を sort_keys 無しで使う、ツール集合がリクエストごとに変わる。→ いずれも「前方に非決定な値が入る」パターン。
3-2. セマンティックキャッシュ(近傍一致)¶
一言: クエリを埋め込んでベクトル空間で近い過去回答を返す。生成(重い)を選択(軽い)に縮退させる。完全一致キャッシュは言い換えで即ミスするが、こちらは意味が近ければ当たる。
一次裏取り(閾値の実測): 標準実装は GPTCache(zilliztech)。コサイン類似度の閾値がキモで、低いと誤ヒット(false hit)・高いと取りこぼし(false miss)。実測レンジは埋め込みモデル依存で 0.78〜0.95(例: ある検証で 0.8 → ヒット率68.8%・正解率97%超、英語FAQは0.92〜0.95、Albert系は0.78が最適)。→ 記事が §7 で挙げる 0.85 はこのレンジの妥当な中央値。ドメインで再チューニング前提。
4. 非同期並列化(エージェントグラフ)¶
一言: 依存の無いステップは同時に投げる(fan-out)→ 結果を明示ルールで合流(fan-in)。逐次4×3秒=12秒が、並列なら最長ブランチの3秒になる。
逐次: A(3s) → B(3s) → C(3s) → D(3s) = 12s
─────────────────────────────►
fan-out/fan-in:
┌─ A(3s) ─┐
共通 ─┼─ B(3s) ─┼─ merge ─► = 3s(最長ブランチ)
前提 ├─ C(3s) ─┤
└─ D(3s) ─┘
hot path / cold path の分離(レイテンシ設計の芯): - hot path: 主回答に必要な最小ステップ(クエリ生成→データ取得→レンダリング)だけを同期で通す。 - cold path: 付随処理(フォローアップ提案・ロギング・キャッシュ暖機)は応答後に非同期で回す。ユーザー体感を汚さない。
信頼性の条件(並列化は速いが壊れやすい。ここを外すと信頼性劣化に化ける): 1. 人工的な逐次依存を除く(本当は独立なのに並べているだけのもの)。 2. 共有状態のマージ規則を明示(リストは加算、スカラーは last-write-wins など)。 3. ブランチ単位の障害処理(1本コケても全体を巻き込まない部分失敗ポリシー)。
「分散システムとして扱う」の実体がこれ。バリア・バックプレッシャ・障害ドメインは並列グラフの語彙。並列運用の物理的コストは Fable5_3日間で300万円課金_並列エージェント運用の物理的課題 も参照。
5. 部分決定化と構造化出力 — LLM呼び出しを「消す」¶
一言: 決定的にできる変換をLLMに投げない。LLMは推論と言語理解に温存し、機械的処理はコードでやる。スキーマ検証済みの構造化出力があれば、後段の決定的コードが安全に動く。
不要なLLM往復を消す4パターン:
| パターン | Before(LLM往復) | After(コード) |
|---|---|---|
| クエリ修正 | 再プロンプトで条件追加 | 出力をパースしフィルタをコード注入 |
| クエリ再利用 | 別クエリを再生成 | 最初のクエリをコードで改変(COUNT↔SELECT等) |
| ツール応答変換 | 巨大ペイロードを丸ごと文脈に戻す | 必要フィールドだけコード抽出・大物は文脈外へ |
| サンプル生成 | LLMに例を作らせる | 既知スキーマからプログラムで代表データ生成 |
芯: 「LLMに聞くべきか、コードで決めきれるか」を毎ステップ問う。決定化した分だけ速く・安く・再現可能になる(4軸トレードオフの決定性側に倒す)。構造化出力は各ベンダの機能(Claude なら output_config.format、tool の strict:true)で契約を固定できる。
6. コンテキストエンジニアリング+プロンプト構造でKVキャッシュを効かせる¶
6-1. 動的コンテキスト選別(typed slots)¶
一言: クエリに関係するスロットだけ詰める。「データ分析の質問にHRポリシーのツール定義は要らない」。プロンプトテンプレを型付きスロット(関連ツール定義/取得文書/会話ターン/ユーザメタデータ)にして、毎回必要な物だけ選ぶ。効果は3つ: レイテンシ減(処理トークン減)・直接コスト減・回答品質向上(無関係ノイズが減る)。→ context_engineering_ast活用 と同系統。
6-2. プロンプト構造で前方一致キャッシュを取りにいく¶
一言(§3-1の応用): 安定は上・動的は下。静的ブロックの順序を毎回崩すと、そこでプレフィックス一致が切れてキャッシュヒットを丸ごと失う。
推奨順序:
① system 指示 ← 不変(最上部)
② ツール定義 ← 不変(決定的にシリアライズ、名前でソート)
③ 固定 few-shot 例 ← 不変(クエリ毎に並べ替えない)
④ 選別済みコンテキスト ← セッション単位で変わる
⑤ ユーザメッセージ ← リクエスト毎に変わる(最下部)
────────────────────
①〜③ の末尾に cache_control ブレークポイントを置く
やってはいけない: 静的ブロックの並びをリクエストごとに入れ替える/system に日時・UUIDを差し込む/クエリ適応な例を静的プレフィックス内に混ぜる(→ 適応例は静的プレフィックスの後に置く)。プロバイダのキャッシュを明示的に有効化する(Anthropic の cache_control、OpenAI の対応モデルでの自動キャッシュ)。
7. セマンティック類似 vs LLM分類 — 「点数でなく順位で多数決」¶
一言: ラベル空間が安定なら、LLMに分類させるより埋め込みKNNの方が速く・安く・説明可能。LLMルーティングは不透明でルーティング幻覚を生むが、KNNは「近傍を見せろ」で説明できる。
| 観点 | LLM分類 | セマンティック類似(KNN) |
|---|---|---|
| コスト | 全入力トークン | 埋め込み呼び出しのみ |
| レイテンシ | 全推論 | 埋め込み+ベクトル検索(典型 <10ms) |
| 精度 | プロンプト依存 | 例示依存・使うほど改善 |
| デバッグ性 | 不透明 | 近傍を提示でき完全に説明可能 |
| 更新 | プロンプト書換+再デプロイ | ラベル付き例を足すだけ(再デプロイ不要) |
運用: コサイン類似 >0.85 を高信頼として受理、<0.85 で LLM にフォールバック。手キュレーションの種例から始め、低信頼ケースをLLMに回し、確定結果を例ストアに追記 → 使うほど分類品質が上がる(劣化しない)。閾値の妥当性は §3-2 の実測レンジ(0.78〜0.95)が裏付ける。
これは本人メモの「RRF=点数を信じず順位で多数決」と同じ発想の延長。絶対スコアでなく相対的近さで判断し、閾値割れだけ重い手段に委ねる。
8. まとめ — 状況 → 推奨アプローチ 早見表¶
| 症状/状況 | まず効く手 | 節 |
|---|---|---|
| 全部を大モデルで回して高い | タスク複雑度×モデル階層のマッピングを外部設定化 | §2 |
| 同じ/似たクエリが多い | exact多いならKV前方一致、言い換え多いならセマンティックキャッシュ | §3 |
| 逐次で遅い | 独立ステップを fan-out、付随処理は cold path へ | §4 |
| LLM往復が冗長 | 決定的変換をコード化・構造化出力で契約固定 | §5 |
| コンテキストが毎回巨大 | typed slots で関連分だけ選別 | §6-1 |
| キャッシュが効かない(read=0) | 安定を上・動的を下、system の日時/UUID/未ソートJSON/可変ツールを排除 | §3-1,§6-2 |
| ルーティングが不透明・幻覚 | 安定ラベルはKNN、閾値割れだけLLMフォールバック | §7 |
最後の芯(記事の締め): エージェント基盤を運用可能にするのは「自律的な新規性」ではなく「可視性と制御」。まず各ノードを可観測にし、決定化できる所は決定化し、キャッシュと並列化で物理を味方につける。1軸だけ最適化するとインシデント負荷で作り直しになる — 4軸を同時に見る。
参考リンク¶
- Thoughtworks「Performance engineering in agentic AI systems」(原典) — https://www.thoughtworks.com/insights/articles/Performance-engineering-in-agentic-AI-systems
- Anthropic Prompt Caching(cache_control・TTL・最小トークン・前方一致) — https://platform.claude.com/docs/en/build-with-claude/prompt-caching
- OpenAI Prompt Caching(1024トークン自動・128刻み・prompt_cache_key) — https://developers.openai.com/api/docs/guides/prompt-caching
- GPTCache(セマンティックキャッシュ実装) — https://github.com/zilliztech/GPTCache
- GPT Semantic Cache(arXiv 2411.05276、閾値と設計) — https://arxiv.org/html/2411.05276v2
- Portkey「Semantic Caching Thresholds and Why They Matter」 — https://portkey.ai/blog/semantic-caching-thresholds/
作成: 2026-07-15 / 最終更新: 2026-07-15