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?

Claude Code に「API課金ゲート」を設計する:暴走を防ぐヒューマン・イン・ザ・ループ

0
Posted at

Claude Code に「API課金ゲート」を設計する:暴走を防ぐヒューマン・イン・ザ・ループ

はじめに

Claude Code を含む AI コーディングエージェントを業務で運用していると、必ず一度はぶつかる事故があります。

「気づいたら従量課金 API を何百回も叩いていて、月末に数千円〜数万円の請求が来た」

筆者の環境でも、外部 LLM API(Grok / Gemini)の連続呼び出しを agent に丸投げしていたタイミングで、想定外の課金事故を経験しました。コストもさることながら、本当に怖いのは「ユーザーが知らないうちにエージェントが意思決定して従量課金リソースを消費している」という統制の崩壊です。

この記事では、Claude Code(および同等の CLI エージェント)に API 課金ゲート という仕組みを組み込んで、外部 API を呼ぶ前に必ず人間の確認を挟むためのプロンプト設計とガードレール運用を紹介します。

なぜ「課金ゲート」が必要なのか

LLM エージェントには、典型的に 3 つの暴走パターンがあります。

  1. 無限ループ系:失敗したリクエストを「もう一度試してみます」と自動リトライし続ける
  2. 過剰探索系:問題解決のために「念のため」関連 API を 5〜10 個叩く
  3. 委譲爆発系:sub-agent や Tool が連鎖的に外部 API を呼び出す

これらは個別には合理的な振る舞いですが、従量課金 API に対しては全部アンチパターンです。1 回 0.5 円のリクエストが 200 回走れば 100 円。これが日次タスクで繰り返されれば、月間では 3,000 円が「気づかないうちに」消えます。

「Rate Limit 制」のサブスク(ChatGPT Plus / Claude Pro 等)であればコストは固定ですが、Pay-as-you-go の API は人間の確認を挟まないと安全に運用できない、というのが筆者の結論です。

設計方針:3 つの原則

1. プロバイダごとに「課金タイプ」を分類する

すべての外部 API を一律に扱わず、従量課金 / Rate Limit 制 / 自社内 の 3 階層に分けます。

分類 ゲートの厳しさ
従量課金(Pay-as-you-go) OpenAI API, Anthropic API, Grok API, Gemini API 必ず確認
Rate Limit 制サブスク ChatGPT Plus 連携 CLI など 明示依頼時のみ起動
自社・ローカル ローカル LLM, 自社 RAG 確認不要

このマトリクスを CLAUDE.md(Claude Code のグローバルルール)に書いておくのがポイントです。

2. 確認フォーマットを固定化する

エージェントが毎回違う言い回しで確認すると、ユーザーが流し読みしてしまいます。テンプレート化された短い確認文に揃えます。

⚠️ 課金が発生します
- API: [API名]
- モデル: [モデル名]
- 操作: [何をするか]
- 推定コスト: [概算]
実行してよいですか?(yes/no)

「推定コスト」を入れるのが効きます。gpt-4-turbo で 5,000 トークン消費するなら「約 $0.05」と書く。金額が見えると人間の判断速度が上がります

3. グローバル CLAUDE.md に絶対ルールとして書く

エージェントの「人格」(system prompt 相当)に、以下のような Instruction レベルのルール を埋め込みます。

## [I] API課金ゲート

外部LLM APIを呼ぶ前に **必ず** 確認を挟む。「やって」だけでは実行しない。

- 対象: 従量課金API全般
- 例外: Rate Limit制のサブスクは事前許可で省略可
- フォーマット: 上記テンプレート参照

[I] は Instruction(絶対ルール)の意。[G] Guidance(推奨)と区別することで、AI 側の優先度判定が安定します。

実装:プロンプトと CLI フックの 2 段構え

レイヤー 1:プロンプトでの自己制御

~/.claude/CLAUDE.md に以下を書いておくと、Claude Code 起動時に毎回読み込まれます。

### [I] API課金ゲート

以下のコマンド・ツールを呼ぶ前に必ず確認:
- `mcp__grok__*`
- `gemini` CLI
- 外部 LLM API を内包する任意のスキル

確認フォーマット:
⚠️ 課金が発生します
- API: <名前>
- モデル: <モデル>
- 操作: <内容>
実行してよいですか?(yes/no)

これで、明示的に許可しない限りエージェント側が「念のため Grok を呼んで補強します」のような勝手な意思決定をしなくなります。

レイヤー 2:シェル側のガードレール(保険)

プロンプトだけでは「忘れる」リスクがあるため、CLI 呼び出しに wrapper を噛ませて、実行前に確認を強制 します。

# ~/bin/gemini-gated(PATH の先頭に置く)
#!/usr/bin/env bash
set -euo pipefail

echo "⚠️  Gemini CLI(従量課金)を呼び出します"
echo "    引数: $*"
read -r -p "実行しますか? [y/N]: " ans
case "$ans" in
  y|Y|yes) exec /usr/local/bin/gemini "$@" ;;
  *) echo "キャンセルしました"; exit 1 ;;
esac

alias gemini='~/bin/gemini-gated'.zshrc に書けば、Claude Code が Bash ツールから呼んでも必ず確認が出ます。プロンプト統制とシェル統制の二重化 が実運用では効きます。

レイヤー 3:環境変数でコストキャップ

API クライアント側が対応していれば、環境変数で月次コスト上限を切ります(例:擬似コード)。

import os
from anthropic import Anthropic

MONTHLY_BUDGET = float(os.environ.get("LLM_MONTHLY_BUDGET_USD", "10"))
client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))

# 呼び出し前にコスト累計を確認するラッパーを噛ませる
def safe_create(**kwargs):
    if get_current_month_spend() >= MONTHLY_BUDGET:
        raise RuntimeError(f"月次予算 ${MONTHLY_BUDGET} 到達")
    return client.messages.create(**kwargs)

「気づかないうちに」をなくす最終防衛線です。

運用してわかった落とし穴

筆者の環境で半年運用した結果、いくつかの落とし穴が見えました。

  • Sub-agent からの呼び出しが抜け落ちる:親エージェントが課金ゲートを尊重しても、Task ツールで起動した子エージェントが内部で API を叩くことがある。子側の system prompt にも同じルールを継承する必要がある
  • 「やって」の意味が曖昧:ユーザーが「Grok でリサーチして」と書いた時点で「明示的承認」と解釈してよいかが揺れる。コマンド名を含む依頼のみ事前承認扱い にすると安全
  • 確認疲れ:1 タスクで 10 回確認が出ると人間が「全部 yes」を機械的に押す。バッチ確認(「これから 5 回呼びます」)で集約する設計が必要

まとめ

API 課金ゲートを設計するときの実践ポイント。

  • プロバイダを 3 階層(従量課金 / Rate Limit / ローカル)に分類 し、ゲートの厳しさを変える
  • 確認フォーマットを固定 し、「推定コスト」を必ず含める
  • プロンプトとシェル wrapper の二重化 で、AI が忘れても止まる仕組みにする
  • 環境変数で月次予算上限 を切り、最終防衛線を作る
  • sub-agent への継承バッチ確認の設計 を忘れない

AI コーディングエージェントは生産性を劇的に上げますが、コスト統制を最初に設計しないと「速い・安い・うまい」のうち「安い」が崩壊します。仕組みで止める発想が、長期運用の鍵だと感じています。

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?