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のリクエストログを実測——system/messages/toolsの内訳とトークン配分

0
Posted at

目的

Claude CodeはClaudeモデル専用ではなく、Anthropic Messages API互換のエンドポイントを向き先にすることで、ローカルLLM(Ollama等)をバックエンドにしたユーザーインターフェースとして使うこともできます。

そこで自分のOllama環境にClaude Codeを繋いで、チャットで単純に

1+1は?

と聞いてみたのですが、やけにトークンの消費量が多いことに気づきました。
たった5文字しか入力していないのに、レスポンス側のusageを見るとinput_tokensが2万を超えていたのです。

本記事では、実際にOllama側へ送られた**リクエストボディ(JSON)レスポンス(SSEストリーム)**のログを解析し、Claude Codeが裏側で何を送っているのか、トークンの内訳を実測してみます。

前提

  • WSL2 (Ubuntu) 環境
  • Claude Code インストール済み
  • モデルの向き先をOllama(laguna-xs-2.1:latest)にリバースプロキシ経由で向けている
  • プロキシ側で、Claude Codeから送られるリクエストと、Ollamaから返るレスポンス(SSE形式)のそれぞれログを正とする

ログファイルの構造

まず、採取した2種類のファイルが何を表しているかを整理します。

タイプ 役割
リクエスト Claude Code → ローカルLLMへのリクエスト
modelmessagessystemtoolsなどを含む
レスポンス ローカルLLMからのレスポンス。Anthropic APIのストリーミングイベント形式(message_startcontent_block_deltamessage_stop)で、
thinking(思考過程)とtext(回答本文)が細切れに入っている

「1+1は?」だけで何トークン使われているか

CLAUDE.mdには以下の1文だけを設定した状態で検証しました。

CLAUDE.md
計算をする際は回答だけでなく、その過程も述べるように。

この状態で「1+1は?」と聞いたときのトークン量は以下の通りです。
なお、MCP、Skillは有効になっており、MCPサーバー(aws-knowledge)をはじめ、いくつか既に設定済みとなります。

❯ 1+1は?

  Thought for 3m 4s

計算の過程を述べますね。

問題: 1 + 1 = ?

計算のプロセス:
1. 最初の数である「1」を把握します
2. 次に加える数の「1」を考えます
3. 2つの「1」を合わせると、1つ目の1に1つ目の足し算としてカウントするだけで「2」になります

答え: 1 + 1 = 2
input_tokens output_tokens
約29,700 153

ユーザーが入力した文字はわずか5文字ですが、その裏で3万トークン近くが動いていることが確認できました。この内訳を、リクエストJSONの構造に沿って分解していきます。

リクエストJSONの構造

トークンの内訳を見る前に、リクエストJSON自体の階層構造を確認しておきます。トップレベルは以下の10個のキーで構成されていました。

{
  "model": "laguna-xs-2.1:latest",
  "messages": [...],
  "system": [...],
  "tools": [...],
  "metadata": {...},
  "max_tokens": 32000,
  "thinking": {...},
  "context_management": {...},
  "output_config": {...},
  "stream": true
}
キー 内容 トークン影響
model 向き先のモデル名(今回はlaguna-xs-2.1:latest
messages ユーザー発言・システムリマインダー(CLAUDE.mdやエージェント/Skill一覧)・会話履歴
system Claude Codeのシステムプロンプト本体(ハーネスの振る舞い、環境情報など)
tools 利用可能な全ツールのJSON Schema定義
metadata user_id(device_id・session_id等を含むJSON文字列)
max_tokens 出力の最大トークン数(32000)
thinking 拡張思考の設定({"type": "adaptive"}
context_management コンテキスト管理の設定(古い思考ブロックの扱いなど)
output_config 推論のeffortレベル({"effort": "xhigh"}など)
stream ストリーミング有無(true

このうちmetadatamax_tokensthinkingcontext_managementoutput_configstreamは、値自体は短い設定値なのでトークンへの影響はごくわずかでした。
トークン消費の実体はmessagessystemtoolsの3つに集約されるため、以降はこの3つを掘り下げます。

messages の中身

messagesは配列で、今回のリクエストでは2件のメッセージが入っていました。

"messages": [
  {
    "role": "user",
    "content": [
      { "type": "text", "text": "<system-reminder>...CLAUDE.mdの内容...</system-reminder>" },
      { "type": "text", "text": "1+1は?", "cache_control": { "type": "ephemeral" } }
    ]
  },
  {
    "role": "system",
    "content": "Available agent types for the Agent tool:\n- claude: ...\n\nThe following skills are available...\n- grill-me: ...\n"
  }
]
階層 内容
messages[0].role "user"
messages[0].content[0].text <system-reminder>でラップされたCLAUDE.mdの内容
messages[0].content[1].text 実際のユーザー発言「1+1は?」(ここにcache_controlが付く)
messages[1].role "system"
messages[1].content 文字列そのもの。エージェント一覧+Skill一覧がまとめて1本の長文で入っている

messages[0].content[1]が本来のユーザー入力ですが、わずか5文字です。
一方messages[1].contentは前後にエージェント一覧やSkill一覧を含む長大な1本の文字列になっており、後述するSkillのコストはすべてここに乗っています。

CLAUDE.mdが膨大だとそれだけで多くのトークン量が消費されるため、注意が必要です。

system の中身

systemも配列で、今回は3要素でした。

"system": [
  { "type": "text", "text": "x-anthropic-billing-header: cc_version=...;" },
  { "type": "text", "text": "You are Claude Code, Anthropic's official CLI for Claude.", "cache_control": {...} },
  { "type": "text", "text": "\nYou are an interactive agent...(ハーネスの振る舞い、環境情報など)", "cache_control": {...} }
]
階層 内容
system[0].text Billing用のヘッダー情報(cc_version等)
system[1].text 1行の自己紹介("You are Claude Code...")
system[2].text ハーネスの振る舞い・環境情報・メモリの指示等を含む本体(3要素中最大)

システムプロンプトとして、ハーネスの振る舞いなどを定義しており、テキスト量も一定増加しています。

tools の中身

toolsは配列で、1要素が1つのツールに対応します。

"tools": [
  {
    "name": "Agent",
    "description": "Launch a new agent to handle complex, multi-step tasks...",
    "input_schema": {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "description": { "description": "A short (3-5 word) description of the task", "type": "string" },
        "prompt": { "description": "The task for the agent to perform", "type": "string" },
        "subagent_type": { "description": "...", "type": "string" }
      }
    }
  },
  ...
]
階層 内容
tools[n].name ツール名(AgentBashSkillmcp__aws-knowledge__...など)
tools[n].description ツールの使い方の説明文。
ここが長いツールほどトークンを消費する(例: Workflowは説明文だけで2万文字超)
tools[n].input_schema パラメータのJSON Schema定義(properties配下に各パラメータのtypedescriptionが並ぶ)

独自に導入したMCPツール(mcp__aws-knowledge__aws___get_regional_availabilityなど)もこのtools配列にClaude Code組み込みのツールと全く同じ形式で並んで入ってきます。
つまりMCPサーバーを繋ぐと、そのサーバーが提供するツールの数だけtools[n]の要素が増える、ということになります。。

tools配列——つまりツール定義そのもの——が全体の9割近くを占めており
使わないツールは無効化することでトークン消費を抑えることができます。

補足: MCPを有効化すると何が増えるか

続いて、aws-knowledge(私が追加したMCPサーバー)とplugin:aws-core:aws-mcp(Built-in MCP)を有効化した状態で、同じ「1+1は?」を送り、リクエストログを再取得しました。

tools配列を有効化前後で比較すると、以下の8個が新たに追加されていました。

追加されたツール 文字数 推定トークン
WaitForMcpServers 881 210
mcp__aws-knowledge__aws___get_regional_availability 2,286 544
mcp__aws-knowledge__aws___list_regions 174 41
mcp__aws-knowledge__aws___read_documentation 2,468 588
mcp__aws-knowledge__aws___retrieve_skill 741 176
mcp__aws-knowledge__aws___search_documentation 1,738 414
mcp__ide__executeCode 667 159
mcp__ide__getDiagnostics 365 87
合計 9,320 約2,219

Skill有効時と合わせた最終的なtools配列は39個・109,895文字(約26,165トークン)となり、Skill無効時の31個・100,221文字(約23,862トークン)から、約9,700文字(約2,300トークン)増加しました。

Skillは何トークンを占めているか

自分のClaude Code環境にはgrill-meなどのSkillが有効化されています。
Skillそのものはユーザーが明示的に呼び出す機能ですが、呼び出していなくても、有効な全Skillの説明文が毎リクエストに乗ります
これはClaude Codeが「どのSkillを使うべきか」をターンごとに判断するため、カタログ全体を渡す必要があるためです。

ログ上では、この一覧はmessages配列のrole: "system"のメッセージ内に、エージェント一覧に続けて列挙されていました。

The following skills are available for use with the Skill tool:

- grill-me: Interview the user relentlessly about a plan or design...
- deep-research: Deep research harness — fan-out web searches...
- document-skills:xlsx: ...
- aws-core:amazon-bedrock: ...
- aws-core:aws-cdk: ...
(以下、有効な全Skillが続く)

自分の環境ではgrill-me以外にも、document-skills系・example-skills系・aws-core系など多数のSkillが同時に有効になっており、このセクション全体で約8,700〜8,900文字(約2,000〜2,100トークン) を占めていました。

tools同様、使わないSkillは無効化することでトークン消費を抑えることができます。

全体の内訳まとめ

1+1は? というリクエストだけでも、全体(system + messages + tools)の文字数を比較すると次のようになります(MCP, Skillはどちらも有効)。

状態 合計文字数 推定トークン
MCP, Skill 有効 125,456 約29,870

この値は、MCPツール定義やSkillの追加分やがそのままトークン消費として上乗せされている状態となります。

Hooksの影響について(今回は未検証)
今回はhooksを設定していなかったため実測はしていませんが、Skill/MCPとは少し性質が異なるので注釈だけ残しておきます。SkillやMCPは「有効化した時点で」ツールやカタログがtools配列・messages配列に常時乗り続けるのに対し、Hooksはsettings.jsonに設定しておくだけならリクエストJSONの構造(tools配列など)には何も追加されません。トークンに乗ってくるのは、Hookが発火して、その出力がClaudeへのコンテキストとして注入される場合のみです(PreToolUseのブロック理由、PostToolUseの追加コンテキスト、UserPromptSubmitの出力、SessionStartの注入内容など)。単に外部コマンドを実行するだけで応答をClaudeに返さないタイプのHook(例: Windows通知を飛ばすだけのStop/Notificationフック)であれば、トークン消費はほぼゼロのはずです。つまりHooksのコストは「常時固定のオーバーヘッド」ではなく「発火時・注入内容次第の可変コスト」という点が、Skill/MCPとの大きな違いです。

まとめ

影響度 要素 目安
tools配列(ツール定義全体) 全体の約87%、2万トークン超
Skillカタログ(有効な全Skillの説明文) 約2,000トークン
MCPツール定義(サーバー1つ増えるごとに数百〜数千) 約2,200トークン(aws-knowledge分のみ)
CLAUDE.md 1,000トークン未満

※繰り返しますが、ユーザーの使い方によってはこの数値が跳ね上がります。

「1+1は?」のような単純な質問でも、実際に払っているコストの大半はユーザーの発言ではなく、Claude Codeが毎ターン送るツール定義とSkill/MCPのカタログでした。
ローカルLLMでコストやレイテンシを気にする場合、以下が効果的な対策になりそうです。

  • 使わないSkillを無効化する(特にaws-core系のような、まとめて多数入っているカテゴリ)
  • 使わないMCPサーバーは繋がない、あるいは接続数を絞る
  • (Claude API本家であれば)cache_controlによるプロンプトキャッシュを活用する。ただし今回検証したOllama向けのレスポンスにはcache_read_input_tokens等のフィールドが存在せず、キャッシュ機構が機能している形跡はありませんでした

ローカルLLM運用ではAPIコストは気にならないかもしれませんが、推論速度(レイテンシ)やコンテキスト長の制約には直結するため、この「見えないオーバーヘッド」を把握しておくことは意味があると感じました。

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?