付録F コスト管理(トークン・呼び出し回数・上限)

📖 このページのゴール:トークン(料金の単位)の正体をつかみ、エージェント特有の「往復が増えるほど高くつく」落とし穴と、その安くする方法を知る。 ← 目次・はじめにへもどる


CLIエージェントは、電話の向こうの天才シェフ(LLM)に何度も電話をかけ直すしくみでした(第4章のループ)。電話は1回ごとにお金がかかります。このページは「1回いくら?」「なぜエージェントは高くつきやすい?」「どう安くする?」をやさしく整理します。


🟢 ① トークン=文章のかけら。入力と出力は別料金

トークン(token)は、文章を細かく刻んだ“かけら”のことです。AIは文章を「文字数」ではなく、このかけらの数で量を測り、その数でお金を数えます。

🧰 たとえ話:文章をレゴのブロックに割る 文章を、レゴのように小さなブロックに割っていくと想像してください。トークン数とは、そのとき出来たブロックの個数のこと。日本語は1文字でも何ブロックかに割れやすいので、ブロックが増えやすいのです。

ここで一番大事なことが2つあります。

  • 文字数 ≠ トークン数:とくに日本語は1文字で複数トークンになりがち。文字数だけで料金を見積もるとズレます。
  • 入力と出力は別料金:AIに送る分(入力)と、AIが返す分(出力)は、別々の単価で課金されます。ふつう出力のほうが高いです。

そして料金の基本の式はこれだけです。

入力トークン × 入力の単価 + 出力トークン × 出力の単価

ここで言う「入力」には、SYSTEM_PROMPT(しつけ)も、これまでの messages(会話履歴)もぜんぶ含まれます。AIへの前提や過去のやりとりは“タダ”ではなく、毎回まるごと入力トークンとして数えられます。


🟢 ② いくらかかる?(モデル別のざっくり目安)

モデルには賢さと値段のちがいがあります。安い順に claude-haiku-4-5claude-sonnet-4-6claude-opus-4-8(既定)です。

1,000,000(100万)トークンあたりの目安は、次のくらいです(入力 / 出力)。

モデル 入力(100万トークン) 出力(100万トークン) ひとこと
claude-opus-4-8 $5 $25 いちばん賢い(既定)
claude-sonnet-4-6 $3 $15 バランス型
claude-haiku-4-5 $1 $5 いちばん安い・速い

⚠️ 料金は変わります。必ず公式の料金ページ(Pricing)で、使うモデルの最新の値を確認してください。 上の数字は2026年4月ごろの“感覚をつかむための目安”です。

100万トークンと聞くとピンと来ませんが、出力が入力の5倍くらい高いこと、そしてopusはhaikuの5倍くらい高いことだけ覚えておけば十分です。「短い質問に短く答える」会話なら1回あたりはごく少額ですが、エージェントでは話が変わります(次の③)。


🟢 ③ エージェント特有の落とし穴:往復が増えるほど積み上がる

ここがチャット(前作の「おしゃべりAI」)と一番ちがうところです。

第4章のループを思い出してください。エージェントは「考える → 道具を使う → 結果を返してまた考える」を何度もくり返します。そして毎ターン、anthropic.messages.createいつも messages(履歴)をまるごと渡し直しています。AIは前回の電話を覚えていない(毎回まっさら=ステートレス)からです。

🧰 たとえ話:毎回ノートを最初から読み上げる シェフは前回の電話を忘れてしまうので、あなたは毎回これまでの相談メモを頭から全部読み上げてから新しいお願いをします。会話が進むほどメモは長くなり、読み上げ(=入力トークン)も毎回ぶん厚くなります。

つまり、

  • 1往復目:履歴は短い → 入力トークンも少ない
  • 5往復目:道具の結果やAIの返事が積もって履歴が長い → その長い履歴を毎回まるごと再送

道具の結果(ファイルの中身、コマンドの出力など)が大きいと、それがずっと履歴に残って毎ターン再送されます。だから1タスクで5回・10回と往復するエージェントは、1往復だけのチャットよりも入力トークンが積み上がりやすく、高くつきやすいのです。「賢いことを何度もさせる」のは、その分お金もかかる、と覚えておきましょう。


🟢🔧 ④ 安くする4つの対策

積み上がりを抑える手は、大きく4つあります。

1) 🟢 MODEL 定数で安いモデルに替える(賢さとのトレードオフ)

第4章までで使ってきた MODEL は1か所の定数でした。ここを書き替えるだけで、エージェント全体のモデルが変わります。

// const MODEL = "claude-opus-4-8";   // 賢い既定(高い)
const MODEL = "claude-haiku-4-5";     // 安い・速い(その分かしこさは控えめ)

1行ずつ読むと:

  • 1行目(コメント):これまでの既定。賢いぶん、いちばん高いモデルです。
  • 2行目:MODEL を安いモデルに差し替えます。create に渡すモデル名はこの定数1か所だけなので、これでエージェント全体が安いモデルで動きます。

💡 トレードオフ:安いモデルは賢さが控えめです。「ファイル一覧を読むだけ」のような簡単な仕事は haiku、「複雑な計画を立てる」仕事は opus、のように仕事の難しさで選ぶのがコツ。まずは haiku で試し、力不足なら上げる、が無駄がありません。

2) 🟢 ループ回数の上限(第4章)

第4章の for (let step = 0; step < 10; step++)上限10回は、暴走防止であると同時にコストの保険です。万一AIが道具を呼び続けて止まらなくなっても、10回で打ち切るので青天井にはなりません。回数を増やすほど安心は減り、上限の往復ぶんだけ最大コストも増える、という関係です。

3) 🔧 道具結果やコンテキストの刈り込み・要約(第14章)

履歴が長いほど高い、なら履歴を短く保つのが効きます(くわしくは第14章)。

  • 刈り込み(トリミング):大きな道具結果(巨大なファイル全文など)は、必要な部分だけ残して捨てる。
  • 要約(サマリー):古いやりとりは、AIに短くまとめさせて1つの要約に置き換え、長い原文を履歴から外す。

「毎回まるごと再送される」のが高さの原因なので、再送される中身そのものを小さくするという発想です。

4) 🔧 プロンプトキャッシュで前文の再送を安くする

毎回まったく同じ前文(長い SYSTEM_PROMPT や、変わらない最初のほうの履歴)を送るなら、その部分をキャッシュ(一時的に覚えておく)して、2回目以降は安く・速くできます。cache_control という印を付けるだけです。

const res = await anthropic.messages.create({
  model: MODEL,
  max_tokens: 1024,
  system: [
    {
      type: "text",
      text: SYSTEM_PROMPT,
      cache_control: { type: "ephemeral" }, // ここまでをキャッシュ
    },
  ],
  messages,
});

1行ずつ読むと:

  • system: [ { type: "text", text: SYSTEM_PROMPT, ... } ]:これまで文字列で渡していた system を、印を付けられるようにブロックの形で渡します(中身は同じ SYSTEM_PROMPT)。
  • cache_control: { type: "ephemeral" }:「ここまでは毎回同じだから一時的に覚えておいて」という印。次の電話で同じ前文が来たら、覚えておいたぶんは割引になります。
  • ephemeral(エフェメラル=はかない・一時的):キャッシュは短時間で消えます。だから何度も連続でかけるエージェントのループと相性が良いのです。

💡 キャッシュが効くのは「前のほうが毎回まったく同じ」とき。SYSTEM_PROMPT や道具の定義など、変わらない頭の部分に付けると効果的です。


🟢🔧 ⑤ 送る前に見積もる:countTokens

「送ったらいくらだった」では遅いので、送る前に入力トークン数を数えることができます。

const count = await anthropic.messages.countTokens({
  model: MODEL,
  system: SYSTEM_PROMPT,
  messages,
});
console.log(`これから送る入力トークン: ${count.input_tokens}`);

1行ずつ読むと:

  • anthropic.messages.countTokens({ ... }):実際にAIへ送る代わりに、「もしこれを送ったら入力が何トークンになるか」だけを計算してもらいます(返事は作らない=この呼び出し自体は答えを生まない)。
  • 渡す中身(model / system / messages)は create と同じ:本番とそろえることで、本番と同じトークン数が分かります。
  • count.input_tokens:見積もられた入力トークン数。これに②の入力単価をかければ、その電話の入力ぶんの料金がだいたい読めます(出力ぶんは返事ができるまで分かりません)。

💡 ループの各ターンの直前でこれを出すと、「往復のたびに入力トークンが積み上がっていく」のが数字で見えて、③の落とし穴を実感できます。


⚠️ ハマりどころ

  • 文字数とトークン数を同じだと思う:別物です。とくに日本語は1文字で複数トークンになりがち。
  • system や過去履歴を“タダ”だと思うSYSTEM_PROMPT も、これまでの全 messages も、ぜんぶ入力トークンとして毎回課金されます。
  • 出力は無料だと思う:返事(出力)にも、入力とは別の単価で課金されます(しかも高めなことが多い)。max_tokens を大きくしすぎないのも節約です。
  • エージェントをチャットと同じ感覚で見積もる:エージェントは往復のたびに履歴を再送するので、同じモデルでもチャットより高くつきやすい。「1回いくら」ではなく「1タスク(=何往復ぶん)でいくら」で考えます。
  • 数値を断定する:単価もコンテキスト上限(モデルにより数十万〜100万トークン規模)も変わります。最新値は公式で確認を。

📝 ことばメモ

  • トークン:文章を細かく刻んだ“かけら”。AIが量と料金を数える単位。日本語は1文字で複数になりがち。
  • 入力トークン/出力トークン:送る分(SYSTEM_PROMPT+全 messages)が入力、返事の分が出力。別々に課金される(出力が高め)。
  • 単価:トークンあたりの値段。モデルごと、入力/出力ごとに違う。最新値は公式の料金ページで確認。
  • プロンプトキャッシュ:毎回同じ前文を一時的に覚えて、2回目以降を安く・速くするしくみ。cache_control: { type: "ephemeral" } の印で使う。
  • countTokens:実際に送らずに入力トークン数だけを見積もるメソッド。.input_tokens で数が分かる。
  • コンテキスト上限:1回に渡せるトークンの上限。モデルにより数十万〜100万トークン規模(数値は変わるのでぼかして覚える)。

← 目次・はじめにへもどる