VPSでのAI agentの課金高騰を防ぐ方法
VPS上でAI agentを常時稼働させる際、ループによるAPI課金の爆発を防ぐ対策を解説します。実行回数によるコスト倍率の計算や、Tool definitionsによるトークン消費、Prompt cachingの活用、使用量ログの記録方法など、具体的なコスト制御術を紹介します。
AI agentの実行による課金高騰を防ぐ方法
VPS (virtual private server) 上でAI agentのコストを制御するには、実行前に上限を設定する必要があります。実行中に使用量を確認する手段はないためです。max_tokens で各レスポンスに上限を設け、コード内でループ回数を制限してください。変更されないプロンプト部分はキャッシュし、どのジョブがコストを消費しているか確認するために、各レスポンスの使用量数値をログに記録してください。サーバーのレンタル料は月額固定です。一方、モデルのAPIはトークン単位の従量課金であり、放置されたループは静かにトークンを消費し続けます。
これは、所有するサーバーから Messages API を呼び出す既存の agent が存在することを前提としています。仕組みの詳細については VPS上でClaudeを使用してAI agentを構築する を参照してください。
Unattended agent のコスト構造が異なる理由
Interactive session には人間が存在します。モデルが誤った処理を行ったり、40,000行のログを読み込んだりした場合、監視している人間が停止させることができます。Unattended agent にはこのような停止手段がありません。ループが終了するまで実行され、タイマーによって再び実行されます。
多くの人が見落としているのが、実行頻度による倍率です。5分間隔のジョブは、1日に288回、月に約8,640回実行されます。1回の実行コストがいくらであっても、その数値に実行回数を掛けたものが総コストになります。多くの "always-on" agent は、常に稼働している必要はありません。数分以内に回答できればよいため、それはスケジュール管理の問題です。
また、agent はチャットウィンドウでは発生しないコストも発生させます。
- Tool definitions はすべてのリクエストに含まれます。 Tool-use の system prompt のコストは、Claude Opus 4.8 で
tool_choiceofautoまたはnoneが 290 tokens、anyまたはtoolが 410 tokens です。bash tool を使用すると、さらに 325 tokens が追加されます。接続した MCP server が増えるごとに、そのスキーマ分だけコストが加算されます。なお、MCP は model context protocol の略です。 - Tool results は input tokens としてカウントされます。 8,000行を出力するコマンドを実行すると、その 8,000行が次のリクエストに含まれ、そのターンの以降のすべてのリクエストに含まれます。
- 取得したページは input tokens としてカウントされます。 平均的な 10 kB のウェブページは約 2,500 tokens、500 kB のリサーチ用 PDF は約 125,000 tokens です。
max_content_tokensはテキストのみを切り詰めます。これは「PDF のようなバイナリコンテンツではなく、テキストコンテンツに適用される」ためです。PDF の場合はmax_usesとallowed_domainsを使用してください。 - Web search は検索回数ごとに課金されます。 結果の数に関わらず、1,000検索あたり 10ドルです。エラーになった検索には課金されません。
これらは1回あたりのコストは高くありません。しかし、8,640回繰り返されると、非常に高額になります。
Hard ceilings と soft ceilings は異なる問題を解決します
max_tokens が適用されます。 これは、思考プロセスと回答テキストを合わせた、1リクエストあたりの総出力に対するハードキャップ(上限)です。Claude はこの値を超える出力を生成しません。モデル自身はこの数値を知ることはできません。この上限に達すると、stop_reason: "max_tokens" が発生し、回答が途切れます。エージェントにおける注意点として、ツール使用ループ内の各リクエストには個別の max_tokens が適用されます。そのため、この制限はタスク全体ではなく、個々のレスポンスに対して適用されます。例えば、4,000トークンの制限で10回のツール呼び出しを行う場合、そのターンにおける上限は 40,000トークンとなります。
Task budget はアドバイザリ(推奨)です。 task_budget は output_config の内部にあり、思考、ツール呼び出し、ツール結果、および出力を含めた、エージェントのループ全体で使用可能なトークン数をモデルに伝えます。
resp = client.beta.messages.create(
model="claude-opus-4-8",
max_tokens=4096,
betas=["task-budgets-2026-03-13"],
output_config={"task_budget": {"type": "tokens", "total": 64000}},
messages=messages,
)「Task budget はハードキャップではなく、ソフトなヒントです。」 Claude はアクションの途中で上限を超えることがありますが、出力に対する強制的な制限は依然として max_tokens です。「カウントダウンはモデルにのみ表示されます」であり、レスポンスに残り予算のフィールドは含まれません。受け入れられる最小の task_budget.total は 20,000トークンであり、これ未満の場合は 400 error が返されます。タスクに対して予算が小さすぎると、モデルは拒否に近い挙動を示します。具体的には、タスクの範囲を縮小するか、早期に停止します。
コストに関する注意点があります。クライアントがフォローアップリクエストごとに task_budget.remaining を減算する場合、値が変更されるため、その値を含むキャッシュされた prefix は無効になります。値の設定は、最初の1回のみ行ってください。
Task budget は Claude Fable 5、Claude Opus 4.8、および Claude Opus 4.7 でベータ版として提供されています。Claude Sonnet 5 と Claude Haiku 4.5 は Not supported とされており、Claude Code には task budget は適用されません。そのため、tmux でデタッチされた Claude Code セッション は、セッションの管理状態に依存します。
3つ目の制限は Claude Console にあります。エージェントに専用の workspace を割り当て、月間の支出制限と分単位の rate limits を設定してください。「Default Workspace に制限を設定することはできません」また、「workspace の制限の合計が大きくても、Organization 全体の制限が常に適用されます」。「支出通知」を追加しておけば、上限に達する前に閾値で通知を受け取ることができます。
ジョブごとのモデル選択と、実際に変動するコスト要因
モデルの選択はジョブごとに決定します。2026年7月時点の100万トークンあたりの料金(入力/出力)は以下の通りです。Claude Fable 5は$10/$50、Claude Opus 4.8およびOpus 4.7は$5/$25、Claude Sonnet 5は$3/$15、Claude Haiku 4.5は$1/$5です。Sonnet 5は現在、定価より安価です。「2026年8月31日まで、入力/出力100万トークンあたり$2/$10の導入価格が適用されます」という規定があるためです。ログ行の分類のみを行うステップには、Opusは不要です。
次に、コストを左右する要因はeffortです。output_config.effortはlow、medium、high、xhigh、maxを受け付け、デフォルトはhighです。したがって、highを明示的に設定することは、設定を省略することと同じです。effortを下げると、推論の長さだけでなく、他の要素も削減されます。ドキュメントによると、effortを下げるとClaudeのtool callの回数が減り、複数の操作が1つにまとめられます。エージェントにおいては、これが大きな節約につながります。なぜなら、tool callを回避することは、リクエストそのものを回避することだからです。
注意点として、effortの設定はキャッシュと相反します。リクエスト間で値を変更すると、プロンプトキャッシュが無効になります。ドキュメントの例では、リクエスト2はcache_read_input_tokens: 3546を報告しました。effortをhighからmediumに変更したリクエスト3は、cache_creation_input_tokensが3546、cache_read_input_tokensが0でした。したがって、effortの変更はワークロード間で行ってください。キャッシュされた会話の途中で変更してはいけません。キャッシュを維持したまま回答の深さを制御するには、プロンプトを使用してください。最新のユーザーメッセージに「熟考せずに直接回答してください」といった行を追加すれば、それ以前のブレークポイントは維持されます。
Thinking tokensは出力料金で課金され、max_tokensの対象となります。回答が途切れる場合、多くはthinkingが予算を消費したことが原因です。具体的な数値についてはusage.output_tokens_details.thinking_tokensを確認してください。Claudeのトークン料金の内訳で詳細を確認できます。
Stable prefixをキャッシュし、誤って無効化するのを防ぐ
5-minute cacheのキャッシュ書き込みコストは、ベースの入力価格の1.25倍です。1-hour cacheの場合は2倍になります。キャッシュ読み取りコストは0.1倍です。したがって、「5-minute cache(書き込み1.25x)なら1回の読み取りで、1-hour cache(書き込み2x)なら2回の読み取りで、キャッシュの利用が経済的になります」。
常時稼働するagentに適している理由は、次の通りです。「キャッシュされたコンテンツが使用されるたびに、追加コストなしでキャッシュが更新されます」。5-minute cacheに対し、2分ごとにジョブを実行すれば、1回の書き込みだけで、一日中prefixをwarmな状態に保てます。
気づかないうちにキャッシュを失う3つのパターン。
変化するprefix。 「Cache prefixは次の順序で作成されます: tools, system, その次にmessages」。この順序の早い段階で1バイトでも変更があると、それ以降のすべてが無効になります。また、tool definitionsを編集すると、キャッシュ全体が無効になります。よくある失敗は、system promptにtimestampやrun idを含めることです。この場合、リクエストごとにprefixが異なるため、毎回1.25xのコストで新規書き込みが発生し、キャッシュはヒットしません。usage.cache_read_input_tokensが、同じように見える呼び出しに対して0であれば、それが兆候です。変動するテキストは、最新のuser messageに移動させてください。
短すぎるprefix。 各モデルにはキャッシュ可能な最小の長さがあります。その長さに満たない場合、リクエストはキャッシュなしで処理され、「エラーは返されません」。具体的には、Claude Opus 4.8およびClaude Sonnet 5では1,024 tokens、Claude Haiku 4.5では4,096 tokensです。そのため、ジョブをSonnetからHaikuへ移行すると、静かにキャッシュが無効になる可能性があります。
ルックバック範囲を超える会話。 「Lookback windowは20 blocksです」。システムは、各breakpointにつき最大20個のポジションをチェックし、それ以降は停止します。ドキュメントの例では、35 blocksを持ち、35 block目にbreakpointがあるターンは、35から16までのブロックをチェックします。前のターンの15 block目のエントリはウィンドウ外となるため、ヒットしません。毎ターン複数のtool-useおよびtool-resultブロックを追加するagentは、2〜3ターンで20ブロックを超えます。1リクエストにつき4つのbreakpointが使用可能なので、1つは直近のmessagesに割り当ててください。
遅延可能な処理は Batches API へ送信してください
入力と出力の両方において、「すべての利用料金は標準の API 価格の 50%」となります。Batch processing は非同期です。「ほとんどの batch は 1 時間以内に完了」しますが、結果はすべての request が終了したとき、または 24 時間経過したときの、いずれか早いタイミングで返されます。これは一般的な目安であり、保証ではありません。
processing_status が ended になるまでポーリングしてください。errored、canceled、または expired を返す request には課金されません。spend cap を設定している場合の注意点として、「batch が Workspace の設定した spend limit をわずかに上回る可能性があります」
割引は累積されます。また、batch には 5 分以上かかる場合があるため、ドキュメントでは、同じ context を共有する batch に対して 1 時間の cache を使用することを推奨しています。そのため、処理を分割してください。人間や webhook が待機する処理は live path に残し、夜間の digest や前日の log classification は、半額の batch に回してください。
全てのレスポンスのusageフィールドを独自のストアに記録する
記録されていないコストを算出することはできません。全てのレスポンスにはコスト情報が含まれています。
u = resp.usage
row = {
"job": job_name,
"model": resp.model,
"uncached_input": u.input_tokens,
"cache_write": u.cache_creation_input_tokens,
"cache_read": u.cache_read_input_tokens,
"output": u.output_tokens,
"stop_reason": resp.stop_reason,
}API呼び出しごとに、ジョブ名タグを付与したJSON-linesファイルへ1行ずつ追記してください。これにより、1週間後にどのジョブがコストを消費し、どのジョブが単に稼働していただけかを判別できます。cache_readに注意してください。セルフホストのエージェントにおいて、列の値がすべて0になるのは最も一般的なコストに関するバグです。
誤読しやすいフィールドがあります。input_tokensは、最後のキャッシュブレークポイント以降のトークンのみをカウントするため、実際のプロンプトサイズはtotal_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokensとなります。大きなプロンプトに対してinput_tokens: 400を報告するエージェントは、安価ではありません。残りのコストはキャッシュから発生しています。
送信前にカウントしてください。トークンカウントは無料であり、そのレートリミットはメッセージ作成とは別個に管理されています。そのため、count_tokensを使用して、サイズ超過の添付ファイルを支払う前に拒否してください。結果は推定値であるため、モデルごとに再計測してください。他のベンダーのtokenizerのカウントを再利用しないでください。Claude Opus 4.7およびそれ以降のOpusモデル、Claude Fable 5、Claude Sonnet 5は、新しいtokenizerを使用しており、「同じテキストに対して約30%多くのトークンを生成」します。Claude Sonnet 4.6以前、およびClaude Haiku 4.5は、以前のtokenizerを使用しています。
正確なデータが必要な場合は、Admin APIを使用してください。Admin APIはhttps://api.anthropic.com/v1/organizations/usage_report/messagesでusageを、https://api.anthropic.com/v1/organizations/cost_reportでコストを報告します。どちらも、anthropic-version: 2023-06-01においてsk-ant-admin01-...をx-api-key: $ANTHROPIC_ADMIN_KEYとして受け取り、bucket_width=1d、group_by[]=model、およびapi_key_ids[]=を受け付けます。制限事項として、「Admin APIは個人アカウントでは利用できません」というものがあります。
この最後のパラメータは、安価な属性特定の手法です。各ジョブに独自のAPI keyを割り当て、api_key_ids[]でフィルタリングし、group_by[]=api_key_idでキーごとにレポートを分割してください。フィルタは複数形ですが、グループ化の次元は単数形です。VPS上の最初のClaude APIアプリが実装しているように、キーはコード内ではなく環境変数に保持してください。
Bound the loop, because nothing else will
A bounded iteration count is not optional here. The loop is yours, so the counter is yours:
for step in range(MAX_STEPS): # MAX_STEPS = 12, never "while True"
resp = client.messages.create(...)
if resp.stop_reason != "tool_use":
break
else:
log.warning("job %s hit MAX_STEPS=%d, giving up", job_name, MAX_STEPS)Neither ceiling above does it for you: max_tokens caps one response, and the model is only advised of a task budget.
Put a second brake outside the process. Run the job from a systemd timer instead of a permanent process, and set RuntimeMaxSec= on its service unit. With RuntimeMaxSec=600, a hung run is killed after ten minutes instead of spinning until you notice. Running a program as a systemd service and timer covers the unit files themselves. Read what a run did with journalctl -u triage-agent.service --since "1 hour ago".
Cap retries as well, because a handler that retries forever bills every attempt. A 429 or a 500 deserves a few tries with backoff. A 400 deserves none, since the same request fails the same way.
AI agentのコスト管理は、自身の使用量を確認することから始まります
常時稼働するagentのコストを正確に予測できる人は誰もいません。コストは「1実行あたりのtoken数 × 1日あたりの実行回数」で決まり、その両方の数値はユーザー自身が管理しているからです。一度実行してログに記録されたusage行を確認し、自身のスケジュールを掛けて計算してください。2日後にコストレポートを確認し、その計算結果と比較します。数値が一致しない場合、原因のほとんどはキャッシュの不具合か、想定より長く続いたループです。
この計算は、agentがMessages APIを呼び出す自作プログラムであることを前提としています。個人の対話型ワークロードについては、ワークスタイルに合ったClaudeのプランでサブスクリプションについて確認できます。ここに記載されている価格と制限は、2026年7月時点のAnthropicのドキュメントに基づいています。予算を策定する前に、必ず最新のpricing pageを再確認してください。
FAQ
VPSで常時稼働のAIエージェントを運用するコストはいくらですか?
請求書は2種類ありますが、予測可能なのは1種類のみです。サーバー代は月額固定です。モデルAPIはトークンごとの従量課金であるため、コストは「1回の実行での消費量 × 実行頻度」となります。Anthropicはセルフホストの常時稼働エージェントに関する数値を公開していないため、提示される数値はあくまで予測値として扱ってください。実際の実行から usage を取得し、スケジュールに合わせて計算してください。
max_tokens と task budget の違いは何ですか?
max_tokens は強制的に適用され、モデルからは見えません。これは、思考プロセスを含めた1回のリクエストの出力を制限するもので、制限に達すると stop_reason: "max_tokens" が発生します。task budget はその逆です。モデルに数値が渡され、エージェントのループをその範囲内で調整します。ただし、「Task budgets are a soft hint, not a hard cap(タスク予算は厳格な上限ではなく、緩やかなヒントである)」であり、強制的な制限は依然として max_tokens です。
なぜエージェントの cache_read_input_tokens が常に zero になるのですか?
呼び出しごとに prefix が変化しているか、キャッシュするには短すぎるためです。主な原因は、system prompt に挿入された timestamp や run id です。キャッシュは prefix をキーとしているため、1バイトでも変化するとそれ以降のすべてが無効になります。tool definitions や effort の値を変更した場合も同様です。その他の原因はサイズです。短いプロンプトはキャッシュされず、エラーも返されません。
AIエージェントの無限ループを止めるにはどうすればよいですか?
ループ内のコードで反復回数をカウントし、固定の最大値で停止させてください。max_tokens は1回のレスポンスを制限しますが、エージェントは何度もレスポンスを生成するためです。プロセス外で実行時間の制限を設けてください。RuntimeMaxSec= を設定した systemd timer からジョブを開始すれば、停止した実行をスケジュール通りに強制終了できます。また、リトライループは試行のたびに課金されるため、リトライ回数にも上限を設けてください。
Claude API キー単体に支出制限を設定できますか?
ドキュメントに記載されている支出制限は、キー単位ではなく workspace 単位です。そのため、エージェント専用の workspace を作成し、そこで月間の支出を制限してください。「You cannot set limits on the Default Workspace(Default Workspace に制限を設定することはできません)」。また、しきい値に達した際に通知が来るよう、支出通知を設定してください。利用状況を特定するには、ジョブごとに個別のキーを発行し、使用状況レポートを group_by[]=api_key_id でグループ化してください。