0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

エージェントのコストとレイテンシを抑える基本 — ターン上限・モデル階層・プロンプトキャッシュ

0
Last updated at Posted at 2026-09-07

2026-10-12 訂正:max_turnsは金額のハードキャップではありません。モデル既定とClaudeのcache料金は確認日・モデル条件を示し、呼び出し回数とtool数も区別しました。

AI agent cost and latency basics overview

2026年9月8日時点の公開ドキュメントを根拠に、LLMエージェントのコストとレイテンシを抑える基本を初心者向けに整理します。前日までの「失敗パターン」「HITL」「マルチエージェント」の続きとして、課金と待ち時間が膨らむ場所を先に潰す観点です。

この記事のゴールは、「モデルを安くする」前に、ループ回数・入力トークンの再利用・重いノードの再実行のどれが効くかを切り分けられる状態になることです。

結論:コストはターン数だけでは決まらない

レバー 何が減るか 先に入れる対策
ターン上限 LLMターン数(費用制御の一部) max_turns と終了条件を必須化
モデル階層 1回あたりの単価・推論レイテンシ 既定は軽量、難所だけ高品質モデル
プロンプトキャッシュ 繰り返しプレフィックスの入力課金・TTFT 安定した system/tools を先頭に固定
ツール最小化 ツール説明トークン・誤呼び出し 必要最小のツールだけ渡す
ノードキャッシュ 同じ入力の再計算 LangGraph の CachePolicy 等

迷ったら次の一文で十分です。

エージェントの費用は「賢いモデルを選ぶ」より先に、「何回LLMを呼ぶか」と「毎回同じ長いプレフィックスを再計算していないか」で決まる。

1. なぜエージェントはチャットより高いのか

確認できる事実

OpenAI Agents SDK の agent loop は、最終出力が出るまで次を繰り返します。

  1. 現在のエージェントで LLM を呼ぶ
  2. 最終出力なら終了/handoff ならエージェント切替/tool call なら実行して再ループ
  3. max_turns を超えたら MaxTurnsExceeded

出典: Running agents - OpenAI Agents SDK

基本のagent loopはtool結果やhandoff後にモデルを再び呼びます。ただし、一つのターンで複数tool callを要求する場合や、retry・別run・並行処理もあるため、tool数とモデルturn数は一対一ではありません。待ち時間にはtool・network・queueの処理も含まれます。チャットUIでも複数のモデル呼び出しを行う実装はあります。

実務解釈

初心者が最初に見るべきメーターは、モデル単価より 1リクエストあたりの LLM 呼び出し回数です。トレースで「何ターン目に何を呼んだか」が読めないと、値下げもキャッシュも効きません。

2. ターン上限と金額の予算制御を分ける

確認できる事実

Runner.run / run_sync / run_streamed は max_turns を受け取り、超過時は MaxTurnsExceeded を投げます。max_turns=None で上限を無効化できます。上限時に制御された最終出力を返すなら error_handlers={"max_turns": ...} が使えます。

from agents import Agent, Runner, RunErrorHandlerInput, RunErrorHandlerResult

def on_max_turns(_data: RunErrorHandlerInput[None]) -> RunErrorHandlerResult:
    return RunErrorHandlerResult(
        final_output="ターン上限に達しました。依頼を狭めて再実行してください。",
        include_in_history=False,
    )

agent = Agent(name="Assistant", instructions="Be concise.")
result = Runner.run_sync(
    agent,
    "Analyze this long transcript",
    max_turns=3,
    error_handlers={"max_turns": on_max_turns},
)

出典: Running agents

実務解釈

max_turnsはrunのLLMターン数を制限し、金額のハードキャップではありません。一回の入力・出力・推論token、tool料金、retry、handoff先のモデル、並行run数によって費用が変わります。予算を強制するなら、呼び出し前の保守的な費用予約と上限判定、実usageの照合、同時実行の排他、結果不明時の精算を別に設計します。事後のusage記録だけでは超過を防げません。以下の例は金額制御を実装していません。

  • 本番では 上限なし(None)を既定にしない。デモで無限に回る挙動は、請求とレイテンシの両方を壊します。
  • 上限に当たったとき「黙って例外」だけだとユーザー体験が悪いので、短いフォールバック文を返す設計を先に決める。
  • 「もう少し回せば解けそう」は、プロンプトとツール境界を直す合図であって、上限を外す合図ではありません。

3. モデル階層:全部を最強モデルにしない

確認できる事実

Agents SDK では、Agent にモデルを指定しない場合の既定は、低レイテンシ向けの軽量設定です(2026-10-12に確認した現行資料では gpt-5.6-luna + reasoning.effort="none" + verbosity="low")。品質が必要なエージェントには、明示的に高品質モデルと model_settings を設定する、と案内されています。エージェントごとに model を変えたり、MultiProvider でプレフィックス付きルーティングもできます。

出典: Models - OpenAI Agents SDK

実務解釈

役割の例 モデルの置き方 狙い
振り分け・分類・短い抽出 軽量モデル 単価と TTFT を下げる
長文要約・難しい推論・最終回答 高品質モデル 品質が必要な段だけ使う
ツール実行そのもの LLM を呼ばない 正規表現・API・DB で済ませる

「全部を最強モデルにする」は、エージェントのループ回数と掛け算されて一気に高くなります。難所だけ昇格が基本です。

4. プロンプトキャッシュ:同じ長い先頭を再計算しない

確認できる事実

OpenAI の Prompt Caching は、リクエストが同じプロンプトプレフィックスを共有するときに中間状態を再利用します。公式が挙げる利点は次の3つです。

  • 計算の効率化(同じプレフィックスの再計算を避ける)
  • キャッシュ入力トークンの割引(最大約90%)
  • 応答開始までの時間短縮

対応モデルでは既定で有効で、ヒット率は Dashboard で監視できます。長い共通プレフィックスを共有するリクエストには prompt_cache_key を付け、同じキーに寄せるとヒットしやすくなります。

原文: "Prompt caching reuses work when requests share the same prompt prefix."
日本語訳: 「プロンプトキャッシュは、リクエストが同じプロンプトプレフィックスを共有するときに作業を再利用する。」

出典: Prompt caching | OpenAI API

Anthropic 側も同様に、安定したプレフィックスを cache_control でキャッシュでき、標準のキャッシュ読み取りはベース入力単価の0.1倍ですが、現行資料にはモデル別の例外があります。書き込みも TTL により割増となり、読み取り・書き込み・非キャッシュ部分と他の料金条件を分けて計算する必要がある、と公式に説明されています。

出典: Prompt caching - Claude Docs

実務解釈

キャッシュは「魔法の値下げスイッチ」ではなく、プレフィックスを安定させる設計です。

  • system 指示・ツール定義・固定の参考資料を 先頭にまとめる
  • ユーザーごとに変わる情報や毎回変わる日時を 後ろに置く(先頭が揺れるとヒットしない)
  • ツール定義をリクエストごとに並べ替えない
  • ヒット率を見てから、プレフィックスを伸ばす/短くするを決める

エージェントは毎ターンほぼ同じ system/tools を送ることが多いので、キャッシュ設計の恩恵が出やすい領域です。逆に、毎ターン巨大な履歴を全部・無秩序に載せると、コストとレイテンシの両方が悪化します。

5. ツールとコンテキストを減らす

確認できる事実

エージェントループでは、ツール呼び出しのたびに結果が入力へ追加され、次の LLM 呼び出しの入力が伸びます(Running agents のループ定義)。ツールが多いほど、ツール説明トークンと誤選択の余地も増えます。

実務解釈

NG OK
「あると便利」なツールを全部載せる そのタスクに必要な最小集合だけ
巨大な検索結果をそのまま次ターンへ 要約・上位N件・必要なフィールドだけ
失敗した試行履歴を全部残す 失敗理由の短い要約に圧縮する

コスト対策の多くは、モデル変更ではなく 次の LLM に渡す文字列を短くすることです。

6. LangGraph:高いノードの再実行をキャッシュする

確認できる事実

LangGraph はノード入力に基づくキャッシュをサポートします。グラフ compile 時に cache を渡し、ノードに CachePolicy(ttl など)を付けると、同じ入力の再実行を避けられます。

from langgraph.graph import StateGraph
from langgraph.cache.memory import InMemoryCache
from langgraph.types import CachePolicy
from typing_extensions import TypedDict

class State(TypedDict):
    x: int
    result: int

def expensive_node(state: State) -> dict[str, int]:
    # ここが重い(外部API・大きな前処理など)
    return {"result": state["x"] * 2}

builder = StateGraph(State)
builder.add_node("expensive_node", expensive_node, cache_policy=CachePolicy(ttl=120))
builder.set_entry_point("expensive_node")
builder.set_finish_point("expensive_node")
graph = builder.compile(cache=InMemoryCache())

出典: Graph API - Node caching

実務解釈

  • 副作用のあるノード(メール送信・課金・書き込み)は安易にキャッシュしない。読み取り・変換・検索の前処理向きです。
  • キャッシュは「LLM の単価」ではなく「同じ仕事を二度やらない」レバーです。RAG の取得ノードや正規化処理と相性が良いです。
  • TTL を決め、古い結果が残り続けないようにする。

実装チェックリスト

ループと上限

  • 本番ランナーに max_turns(または同等の上限)がある
  • token・tool・retry・並行runを含む予算制御を別に定義し、事前の上限判定と事後usage照合を行う
  • 上限到達時のユーザー向けメッセージ/メトリクスがある
  • 1リクエストあたりの LLM 呼び出し回数をトレースで見える

モデルとツール

  • 振り分け/抽出は軽量モデル、難所だけ高品質モデル
  • ツール一覧はタスク単位で最小化している
  • ツール結果を次ターンへ渡す前に要約または切り詰めている

キャッシュ

  • system/tools など安定プレフィックスが先頭に固定されている
  • 変動情報(ユーザー入力・時刻)がプレフィックスを壊していない
  • プロバイダのキャッシュヒット率を監視している
  • 重い読み取りノードに LangGraph 等のノードキャッシュを検討した

観測

  • 入力トークン/出力トークン/キャッシュヒット/ターン数を1リクエスト単位で記録
  • 「高いリクエスト」Top N を週次で見直す

失敗パターン

パターン1:上限なしでデモ成功を本番に持ち込む → 対策: max_turns 必須化。到達時は短いフォールバックを返す。

パターン2:全エージェントを最強モデルにする → 対策: 役割ごとにモデルを分ける。難所だけ昇格。

パターン3:system の後ろに毎回違う文を挿入してキャッシュが死ぬ → 対策: 安定プレフィックスを先頭固定。変動は末尾へ。

パターン4:ツールを増やして「賢くなったつもり」 → 対策: 候補を減らし、説明トークンと誤選択を同時に下げる。

パターン5:副作用ノードまでキャッシュする → 対策: 書き込み系はキャッシュ対象外。読み取り・変換に限定。

パターン6:単価だけ見てループ回数を見ない → 対策: トレースでターン数とツール回数を先に見る。

パターン7:履歴を無制限に積み上げる → 対策: 要約・窓・必要なフィールドだけ残す。毎ターンの入力長を監視する。

今回の検証範囲

SDK・cacheの公開資料を照合し、掲載Pythonの構文を解析しました。SDK/LangGraph実行、外部モデル・tool呼び出し、cache hit・速度・課金額の測定、予算制御の実装・統合testは行っていません。

参考リンク

この記事を書いた人✏️@YushiYamamoto
ITPRODX.com代表 / AIアーキテクト
Next.js / TypeScript / n8nを活用した自律型アーキテクチャ設計を専門としています。
日々の自動化の検証結果や、ビジネス側の視点(ROI等)に関するより深い考察は、以下の公式サイトおよびnoteで発信しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?