Antigravity でエージェントを毎日動かしていると、最初の月末に請求書を見て息を呑むことがあります。私も個人開発(インディー開発)で4つのサブエージェントを常時稼働させているのですが、運用初期には月額の API コストが想定の3倍に膨れ上がったことがありました。数字を見た瞬間、指先が少し冷たくなったのを覚えています。
そこから数ヶ月かけて、同じアウトプット品質を保ったまま消費トークンを半分近くまで削減しました。ここではその過程で私が「効いた順」に整理した最適化手順を、失敗例と実測値と一緒に共有します。Antigravity 固有の話に寄せていますが、他のエージェントフレームワークにも応用できる内容です。
まず測る — コスト最適化は観測から始まる
最初に手を出しがちなのは、プロンプトを短くすることです。しかし測定なしの短縮は、往々にして品質低下だけを生み、コスト削減に貢献しません。私の経験では、最初の2週間は一切コードを変えず、観測レイヤーを整えることに時間を使うのが正解 でした。
最低限仕込むべき観測項目は以下です。
エージェント/ツール呼び出しごとの input_tokens と output_tokens
キャッシュヒット率(prompt caching を使っている場合)
ツール実行時間と成功率
同じ user 入力に対する「エージェントが自分で自分を呼ぶ」回数
4つ目が特に重要です。Antigravity のマルチステップ実行では、エージェントが自分の前の出力を読み直しながら進行するため、ループが1回増えるだけで消費が倍増 します。私の環境では、このループ回数が平均4回を超えていた時期があり、そこがコストの温床でした。
観測は Antigravity の標準ログに加えて、私は CloudWatch Logs Insights で以下のようなクエリを仕込んで日次レポートにしています。
fields @timestamp, agent_id, step_count, input_tokens, output_tokens
| stats sum(input_tokens) as total_in, sum(output_tokens) as total_out,
avg(step_count) as avg_steps by agent_id
| sort total_in desc
どのエージェントがコストの大半を食っているかが一目で分かります。ここまで揃えてから、最適化に入ります。
数字で見た最適化前後 — どこがどれだけ減ったか
抽象的な「半減」という言葉より、内訳を見たほうが再現しやすいと思いますので、私の環境の月額内訳(4サブエージェント合計・概算)を並べます。金額はモデル単価によって変わりますので、比率を見ていただければと思います。
費目 最適化前(比率) 最適化後(比率) 効いた施策
固定システムプロンプトの再送 38% 7% prompt caching
過剰なコンテキスト履歴 27% 11% コンテキスト剪定
上位モデルへの一律依存 24% 13% モデル振り分け
自己ループの空回り 11% 4% ステップ上限+要約挿入
総量を100とすると、最適化後は合計35前後まで落ちました。金額換算では月額がおよそ55%減です。注目していただきたいのは、最も大きな費目が「同じ固定文を毎回送り直していた分」だった ことです。つまり最初に効かせるべきは、賢いモデル選定よりも、送っている文字列の重複を消すことでした。
効いた順その1 — プロンプト構造の再設計とキャッシュ活用
最も効果が大きかったのは、プロンプトの「固定部分」と「可変部分」を明確に分離し、固定部分を prompt caching に乗せる 設計への変更でした。
改修前、私のエージェントのシステムプロンプトはこんな構造でした。
[システム指示]
[過去の会話履歴]
[使用可能なツール一覧]
[ユーザー入力]
これを改修して以下の順に変えました。
[システム指示(完全固定)] <- cache_control: ephemeral
[使用可能なツール一覧(ほぼ固定)] <- cache_control: ephemeral
[過去の会話履歴]
[ユーザー入力]
システム指示とツール一覧を前に寄せ、prompt caching に乗せるだけで、同じユーザー入力に対する1回目以降の呼び出しで、キャッシュ部分のコストが10分の1 になります。Antigravity で同じエージェントが連続で呼ばれるワークフローでは、体感として月額が3割減りました。
よくある失敗は、固定部分の中にタイムスタンプや動的な日付を挿入してしまうことです。これだと毎回キャッシュキーがズレてしまい、効果が消えます。私は「このプロンプトブロックはバイト単位で前回と同じか」を CI で検証する小さなスクリプトを仕込みました。
import hashlib, json, sys
# 固定であるべきプロンプトブロックのハッシュを前回値と突き合わせる
def block_hash (text: str ) -> str :
return hashlib.sha256(text.encode( "utf-8" )).hexdigest()
with open ( "prompt_fixed_block.txt" , encoding = "utf-8" ) as f:
current = block_hash(f.read())
with open ( "prompt_fixed_block.lock" , encoding = "utf-8" ) as f:
expected = json.load(f)[ "hash" ]
if current != expected:
print ( "固定ブロックが変化しています。キャッシュが無効化されます。" )
print ( "意図した変更なら prompt_fixed_block.lock を更新してください。" )
sys.exit( 1 )
print ( "固定ブロック一致。キャッシュ継続。" )
このチェックを入れてから、「気づかないうちに固定部へ動的値が混入してキャッシュが効かなくなる」という静かなコスト増を防げるようになりました。効いていたはずの施策が翌月こっそり無効化される、という事故が一番厄介なのです。
効いた順その2 — コンテキストの剪定(pruning)
次に効いたのが、エージェントが参照するコンテキストの剪定です。多くの人が「大は小を兼ねる」でコンテキストを盛り込みすぎています。私自身、最初は全会話履歴を渡していました。
しかし観測データを見ると、エージェントが実際に参照していたのは直近3ターン分と、現在のタスクに直接関係する2〜3件 でした。残りは入力トークンを水増ししているだけです。
私は以下のルールでコンテキストを剪定しています。
直近3ターンは常に含める
それ以前は「このタスクの名詞」に一致するターンだけを含める
含める判定が難しい場合は、要約エージェントに1文で圧縮させる
この要約専用のエージェントは下位クラスの安いモデルで動かします。こう書くと「要約エージェントを挟むとレイテンシが増えるのでは」と思われますが、Antigravity のステップ実行は元々非同期なので、直列に挟んでも体感への影響は小さいです。剪定によって入力トークンが平均で4割ほど軽くなり、しかも余計な履歴に引きずられた誤答が減った、という副次的な効果もありました。コンテキストを削ることは、コストだけでなく精度にも効くことがあります。
効いた順その3 — モデル振り分けと損益分岐
3番目が、タスクごとのモデル振り分けです。私の経験では、全タスクを最高性能モデル1本で回すのは、個人開発では過剰 です。
私の現在の振り分け指針はこうです。
タスク種別 使うモデル階層 判断基準(間違えたときの影響)
設計判断・コードレビュー・障害対応 上位 数週間の手戻り。ここはケチらない
情報抽出・要約・定型変換 中位 目視で気づける軽微な誤り
ログ分類・タグ付け・キーワード抽出 下位 後からバッチで直せる
Antigravity ではサブエージェントごとに使用モデルを指定できるので、この振り分けは比較的簡単です。振り分けの決め手は「間違えたときの影響範囲」で考えるのが分かりやすいです。設計判断を間違えると数週間の手戻りが発生しますが、タグ付けを間違えても後から直せます。
損益分岐の考え方も添えておきます。上位モデルと下位モデルの単価差がおよそ10倍だとすると、下位モデルの誤り訂正に上位モデルの10回分以上の手間がかかるタスクだけ、上位モデルに任せれば元が取れる 計算です。私はこの「10回ルール」を頭に置いて、迷ったタスクを下位から試し、精度が足りなければ一段上げる、という順で決めています。最初から上位で始めると、下げる判断はなかなか働きません。
効かなかったこと、やって後悔したこと
逆に、以下は効果が薄いか、むしろ悪化しました。
プロンプトを日本語から英語に変えた : トークン数は減りますが、私の場合はドメイン用語が日本語だったため、翻訳の揺れで品質が低下しました。バイリンガルな定型処理なら効くかもしれません
max_tokens を小さく設定した : 出力を強制的に短くすると、エージェントが途中で切れて再呼び出しが発生し、結局コストが増えました
複数ツールを1本化した : 「ツール数を減らせばツールスキーマのトークンも減る」と考えて統合しましたが、統合ツールへの呼び出しプロンプトが複雑になり、むしろ入力トークンが増えました
これらはいずれも「直感的には効きそう」なものばかりで、実際に計測するまで効果が逆転していることに気づけませんでした。測定ファーストの重要性を痛感しました。
運用開始後の継続改善とアラート設計
コスト最適化は1度やって終わりではありません。私は週次で以下を確認しています。
先週のトップ3エージェントの消費トークン(前週比)
キャッシュヒット率の変化
「ユーザー1リクエストあたりの平均コスト」の推移
放置運用を成り立たせるには、人が毎週見るだけでなく、閾値を超えたら自動で気づける仕掛けが要ります。私が設定しているアラート閾値の目安を共有します。
監視指標 アラート閾値 疑うべき原因
キャッシュヒット率 前週比 20%以上の低下 固定ブロックへの動的値混入
平均ステップ数 1エージェントで4回超 自己ループの空回り
1リクエスト平均コスト 2週連続の上昇 プロンプト追記の積み重ね
3つ目のメトリクスは、サービスの健全性を見る上で一番重要です。ユーザーが増えてコスト総額が増えるのは健全ですが、1リクエストあたりが増えているのは、設計の劣化か、プロンプト追記の積み重ね です。後者はコードレビューの文化で防ぎます。「プロンプトを1行追加するたびに入力トークンが n 増える」を意識してレビューすると、不要な追記が驚くほど減ります。
最後に残る一番の資産
1ヶ月かけてコスト最適化をやると、節約された費用以上に価値のある資産が手元に残ります。それは「自分のエージェントがどこで何をどれだけ使っているか」の理解です。
この理解があると、新しい機能を追加するときに「ここに機能を足すとコストが n 上がる」と事前に見積もれるようになります。コスト最適化は、見かけ上は経理の作業ですが、実際にはエージェント設計の深い理解を得るためのプロセスでもあります。
Antigravity でエージェントを運用している方で、請求額に違和感があるなら、まず2週間の観測から始めてみてください。コードを書き換えるのはその後で十分間に合います。私自身まだ調整を続けている途中ですが、数字が見えるようになると、運用そのものが少し楽しくなります。お読みいただきありがとうございました。