月のAI費用は$314と出た。中身はほぼClaudeで、Grokの2億4千万トークンは値段不明のままだった

AIにかかった費用は$314.56。hermes insights --days 30 はそう表示しました。cronで記事の下書きや投稿を回し、Slackで指示を出している、30日分の合計です。
分かりやすい数字ですが、月のAI運用費としてメモする前に、内訳を開いておきます。
$ hermes insights --days 30 | grep -E "Sessions:|Estimated:|Included:|Unknown:"
Sessions: 814 Messages: 36,821
Estimated: ~$314.56
Included: 391 session(s) (subscription — no provider invoice)
Unknown: 157 session(s) (no pricing data)
Estimatedは推計です。その下の2行は、金額に足されていない分の件数を表します。Includedの391セッションは定額プランの中で動いたので請求書が出ない分。Unknownの157セッションは、単価表に載っていないモデルを使った分です。
金額の出どころをモデル別に割る
hermes insights のモデル表はトークン数しか出しません。費用の出どころを知りたくて、~/.hermes/state.db をSQLiteの読み取り専用で開き、モデルごとに集計しました。スクリプト全文は記事の下に畳んであります。
$ python3 "$TMPDIR/usage_check.py"
== 2. モデル別の費用と価格の状態
claude-sonnet-5 estimated 479,301,120 $213.89
claude-sonnet-5 none 67,534,352 $29.43
claude-sonnet-5-5 estimated 175,978,722 $71.12
gpt-5.6-sol included 88,865,520 $0.0
gpt-5.6-sol none 14,261 $0.0
gpt-5.6-terra included 117,049,507 $0.0
gpt-5.6-terra none 5,920,903 $0.0
gpt-6-sol included 146,218,706 $0.0
grok-4.6 none 7,669,505 $0.0
grok-4.6 unknown 90,104,814 $0.0
grok-4.7 none 9,663,554 $0.0
grok-4.7 unknown 153,776,833 $0.0
Claudeの3行を足すと$314.44です。画像生成モデルの費用はこの集計では確かめていません。画面は$314.56です。つまり、あの数字はClaude 2モデルの推計と、ほぼ同じ意味でした。
同じ$0.0でも、中身は2種類あります。GPT系3モデルは、included(定額プランに含まれる)が合計352,133,733トークン。払っていないのではなく、月額の中に入っていて、1回ごとの金額に分けられないだけです。Grok系2モデルは、unknownが合計243,881,647トークン。こちらは単価表が無く、いくらか分からないまま$0と表示されています。
cronは件数が多い。だから安い、とは書けなかった
セッション数だけ見ると、cronが542件でslackが156件です。ところが --source を付けて費用を出すと、順番がひっくり返ります。
$ hermes insights --days 30 | grep -E "^ (cron|slack) "
cron 542 20,141 473,658,518
slack 156 14,029 678,988,276
$ hermes insights --days 30 --source cron | grep -E "Total tokens|Estimated:|Included:|Unknown:"
Total tokens: 474,481,095
Estimated: ~$49.70
Included: 289 session(s) (subscription — no provider invoice)
Unknown: 131 session(s) (no pricing data)
$ hermes insights --days 30 --source slack | grep -E "Total tokens|Estimated:"
Total tokens: 768,941,762
Estimated: ~$242.75
cron 542件(全814件の66.6%)で$49.70、slack 156件(19.2%)で$242.75。ここで「cronは安く済んでいる」と書きかけて、手が止まりました。cronのIncludedとUnknownを足すと420件です。542件のうち77.5%に、金額が付いていません。
そこで、価格の状態別にトークンを数え直しました(スクリプトの3つ目の集計です)。
| source | estimated(金額あり) | included(定額) | unknown(価格不明) | none(状態なし) |
|---|---|---|---|---|
| cron | 111,414,151 | 272,622,847 | 89,621,520 | 822,577 |
| slack | 478,214,358 | 57,779,089 | 142,994,829 | 89,953,486 |
cronのトークンの76.4%(定額と価格不明の合計)は、金額に入っていません。$49.70は、cronの費用の下限にすぎません。slackは62.2%に金額が付いているので、$242.75のほうが実態に近い数字です。cronとslackの費用を同じ目盛りで比べるのは、まだできません。
同じslackなのに、数字が2通り出た
もう1つ引っかかりました。Platforms表ではslackが678,988,276トークンです。ところが --source slack を付けると768,941,762トークンになります。同じ30日、同じslackです。差は89,953,486トークンあります。
スクリプトの1つ目の集計で、2つのテーブルを並べました。
== 1. sessions行 と 利用台帳(session_model_usage) のトークン合計
cron 542件 sessions行= 473,658,518 台帳= 474,481,095 差= 822,577 台帳の費用=$49.7
slack 156件 sessions行= 678,988,276 台帳= 768,941,762 差= 89,953,486 台帳の費用=$242.75
oneshot 77件 sessions行= 74,260,664 台帳= 74,306,544 差= 45,880 台帳の費用=$22.1
差の89,953,486トークンは、さきほどの価格の状態別の表で、slackの「none(状態なし)」と1桁も違わず一致します。cronの差822,577も、cronのnoneと同じです。
Platforms表はsessions行の合計。--source を付けると、モデル経路ごとの利用台帳(session_model_usage)を読みます。Hermes Agentのソース(agent/insights.py)でも、モデル別の集計は利用台帳から取り、台帳に足りない分だけsessions行から補う作りでした。slackでは台帳のほうが大きいので、補う分は出ません。sessions行に載っていないトークンが、台帳には入っている、ということです。
費用にも効きます。claude-sonnet-5のnone行は67,534,352トークンで$29.43。これがすべてslack分だとすると、sessions行で足し上げたslackの費用は、台帳の$242.75から$29.43を引いた$213.32になります。台帳より1割強少なく見えていた計算です。
状態なしの行が、なぜ生まれるのか。そこまでは追えていません。いまは台帳のほうが大きいので、台帳側を信じます。費用の判断にPlatforms表は使いません。
月末にもう一度打つ前に
同じコマンドでも、数字は動きました。この記事を書く間に、全体の推計は$314.21、$314.38、$314.45、$314.56と、数十分おきに上がっています。30日の窓の中で、まだ動いているセッションがあるためと見ています。月の記録にするなら、日付を決めて1回だけ打ち、そのときの出力ごと保存します。
- 画面の$は「Claudeの推計」とメモする。月の運用費の総額とは書かない
- Grok系の単価は、
insightsの外で調べる。プロバイダ側の請求画面を見るか、単価をこちらで決めて掛け算する - 定額プランの月額は
insightsに出ないので、自分で足す - cronの費用は、金額が付いた約23%分の下限として読む
これで「AI副業は黒字か赤字か」を言うには、売上と定額の月額が足りません。まず、費用の側の穴が3種類あると分かったところまでです。
集計スクリプト全文(usage_check.py)
import os, sqlite3, time
db = os.path.expanduser("~/.hermes/state.db")
c = sqlite3.connect(f"file:{db}?mode=ro", uri=True) # 読み取り専用で開く
cut = time.time() - 30 * 86400
USE = "u.input_tokens+u.output_tokens+u.cache_read_tokens+u.cache_write_tokens"
print("== 1. sessions行 と 利用台帳(session_model_usage) のトークン合計")
rows = {r[0]: r[1:] for r in c.execute(
"select source, count(*), sum(input_tokens+output_tokens+cache_read_tokens+cache_write_tokens) "
"from sessions where started_at >= ? group by source", (cut,))}
ledger = {r[0]: r[1:] for r in c.execute(
f"select s.source, sum({USE}), round(sum(coalesce(u.estimated_cost_usd,0)),2) "
"from session_model_usage u join sessions s on s.id = u.session_id "
"where s.started_at >= ? group by s.source", (cut,))}
for src in ("cron", "slack", "oneshot"):
n, t = rows[src]
lt, cost = ledger[src]
print(f"{src:8}{n:>5}件 sessions行={t:>12,} 台帳={lt:>12,} 差={lt - t:>11,} 台帳の費用=${cost}")
print("\n== 2. モデル別の費用と価格の状態")
for r in c.execute(
f"select u.model, coalesce(u.cost_status,'none'), sum({USE}), round(sum(coalesce(u.estimated_cost_usd,0)),2) "
"from session_model_usage u join sessions s on s.id = u.session_id "
"where s.started_at >= ? and u.model not like 'google/%' group by 1,2 order by 1,2", (cut,)):
print(f"{r[0]:18}{r[1]:10}{r[2]:>13,} ${r[3]}")
print("\n== 3. cron と slack の価格状態別トークン")
for r in c.execute(
f"select s.source, coalesce(u.cost_status,'none'), sum({USE}) "
"from session_model_usage u join sessions s on s.id = u.session_id "
"where s.started_at >= ? and s.source in ('cron','slack') group by 1,2 order by 1,2", (cut,)):
print(f"{r[0]:6}{r[1]:10}{r[2]:>13,}")


