Claude Code のサブエージェントは、これまで親のセッションの考える深さ(effort)を引き継いで動いていました。Claude Code 2.1.316 で足された環境変数 CLAUDE_CODE_SUBAGENT_EFFORT は、変更履歴によると、ほかに指定が無いときにサブエージェントが走る深さを、引き継ぎの代わりに決めるためのものです。親は high のままサブエージェントだけを low に下げると、トークン・時間・費用がどれだけ減るのか、問題が解けなくならないかを、手元で測りました。その技術検証の報告です。

結論

  • 設定は効きました。CLAUDE_CODE_SUBAGENT_EFFORT=low で起こすと、OpenTelemetry の api_request イベントの effort は、親が high、サブエージェントが low でした。
  • サブエージェントの出力トークンと時間は、少し難しい3問で約 17%、易しい3問で 6〜11% 減りました。どの形でも、問題はすべて解けました(各2回)。
  • それでも、合計の推定費用は 2〜5% しか減りませんでした。費用の大半は、サブエージェントごとにプロンプトをキャッシュに書き込んで読み直す分と、親の分です。
  • 同じ3問を親が自分で解くと、推定費用は分けたときの4〜7割で済みましたが、時間は 1.1〜3.1 倍かかりました。小さな作業をサブエージェントに分けるのは速さのためです。費用を下げたいなら、分けない方が効きます。

試した環境

  • Mac、Claude Code 2.1.316(公式の darwin-arm64 版)
  • モデルは既定の Opus(集計に出た名前は claude-opus-5-5)。会話の題を作る要求だけは claude-haiku-5-5 で、これは表に入れていません
  • ヘッドレス(claude -p)で起動。API キーの環境変数(ANTHROPIC_API_KEY・ANTHROPIC_AUTH_TOKEN)は外しました
  • サブスクリプションで測りました。表の費用は、Claude Code が要求ごとに出す見積もり(cost_usd)を足したもので、請求額ではありません

4つの形と測り方

形

形親の --effort環境変数サブエージェント
Ahighなし3つ。親の深さを引き継ぐ(これまでの振る舞い)
BhighCLAUDE_CODE_SUBAGENT_EFFORT=low3つ。low で走る
Clowなし3つ。親の深さを引き継ぐ
Dhighなし使わない。親が自分で3問を解く

B の起動コマンドは次のとおりです。

CLAUDE_CODE_SUBAGENT_EFFORT=low claude -p "<頼み>" --effort high \
  --output-format stream-json --verbose --permission-mode dontAsk \
  --allowedTools Agent Read Write Edit "Bash(python3 *)"

A と C は、環境変数を付けずに --effort だけを変えました。D は --allowedTools から Agent を外し、--disallowedTools Agent を足しました。

頼んだ内容と問題

A〜C では親に、1つのメッセージで Agent ツールを3回呼び、問題ごとにサブエージェントを1つずつ前面で(背景ではなく)走らせるよう頼みました。頼みの全文です。

This is a measurement run. Do exactly this and nothing else.
In ONE message, use the Agent tool three times to start three agents (foreground, not in the background), one per folder: intervals, durations, roman. Give each agent these instructions, with <folder> replaced by its folder:
"Implement solve() in <folder>/solution.py so that `python3 <folder>/test_solution.py` prints OK. Read the docstring and the test file first. Run the test with Bash. Fix and rerun until it prints OK (at most 3 runs). Reply with one line: <folder> PASS or <folder> FAIL."
Do not do the work yourself. After all three agents report back, reply with the three lines they returned.

D では、エージェントを起こさず、同じ3問を順に自分で解くよう頼みました。

問題はどれも、Python の solve() を書くものです。フォルダごとに docstring と test_solution.py を置き、python3 <folder>/test_solution.py が OK を出すまで直させました(最大3回)。終わった後に私たちがテストを走らせ、合否を確かめました。

組問題
易しい3問区間の結合/“1h30m15s” のような時間の文字列を秒に直す/ローマ数字を整数に直す
少し難しい3問四則の式の評価(eval() を使わない。割り算は C と同じく 0 の方へ切り捨て)/ワイルドカードの照合(?・*・バックスラッシュのエスケープ。長い入力でも指数時間の後戻りをしない)/“3[a2[c]]” を “accaccacc” に展開

少し難しい3問でも、フォルダ名は易しい3問のもの(intervals など)を使い回したので、頼みの文は同じです。どの形も2回ずつ走らせました。C は易しい3問だけで測っています。

数え方

測り方はClaude Code の背景のエージェントの要約を OpenTelemetry で数えた記事と同じです。OpenTelemetry のログを OTLP/HTTP の JSON で手元の受け口に送らせ、claude_code.api_request イベントを属性 query_source ごとに足しました。親は sdk、サブエージェントは agent:builtin:general-purpose として出ます。api_request には属性 effort もあるので、実際に効いた深さもここで確かめました。

CLAUDE_CODE_ENABLE_TELEMETRY=1
OTEL_METRICS_EXPORTER=none
OTEL_LOGS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=http/json
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://127.0.0.1:4318/v1/logs
OTEL_LOGS_EXPORT_INTERVAL=2000

はじめに B を1回だけ走らせ、effort が親 high・サブエージェント low と出ることを確かめてから、残りを回しました。

以下の表の「時間」は、起動から終わりまでの経過時間です。「子」はサブエージェント3つの合計を指します。「子の時間の合計」はサブエージェントの api_request の duration_ms を足したものです。3つが並んで走るため、経過時間より長くなります。

少し難しい3問:出力と時間は 17% 減ったが、合計の費用は 5%

形時間合格子の出力トークン子の時間の合計子の推定費用合計の推定費用
A 親 high・子は引き継ぎ18.0〜19.3 秒3/34,298〜4,34436.4〜36.8 秒$0.332〜0.333$0.493〜0.495
B 親 high・子 low15.7〜15.8 秒3/33,577〜3,61030.2〜30.8 秒$0.309〜0.310$0.471
D 親だけで解く37.2〜48.0 秒3/3—(親が 4,580〜5,671)——$0.302〜0.317

B では、サブエージェントの出力トークンと時間の合計が、どちらも約 17% 減りました。経過時間も 18.0〜19.3 秒から 15.7〜15.8 秒に縮みました。low でも3問とも、2回とも解けています。ところが、合計の推定費用は $0.493〜0.495 から $0.471 になっただけで、減り方は 5% ほど(約 $0.02)でした。

少し難しい3問で、B が A より減った割合。子の出力トークン 16.8%、子の時間の合計 16.7%、経過時間 15.5%、子の推定費用 6.9%、合計の推定費用 4.7%。

出力は 700 トークンあまり減っているのに、費用はほとんど動いていません。この食い違いは、易しい3問でも同じでした。

易しい3問:減り方は 6〜11%、費用の差は回ごとの揺れに埋もれる

易しい3問では、C(親も low)も測りました。

形時間合格子の出力トークン子の時間の合計子の推定費用合計の推定費用
A 親 high・子は引き継ぎ15.1〜15.3 秒3/32,838〜2,85126.0〜26.5 秒$0.298〜0.367$0.459〜0.528
B 親 high・子 low14.6〜16.1 秒3/32,539〜2,68021.9〜25.7 秒$0.290〜0.355$0.451〜0.516
C 親 low・子は引き継ぎ14.2〜15.3 秒3/32,516〜2,61923.2〜25.1 秒$0.280〜0.287$0.441〜0.449
D 親だけで解く18.5〜20.6 秒3/3—(親が 2,347〜2,579)——$0.219〜0.225

2回の平均で A と比べると、サブエージェントの出力トークンは B で 8%、C で 10% 減りました。時間の合計は B で 9%、C で 8% の減りです。B の出力の減りを回ごとに比べると、6〜11% でした。経過時間はどの形も 14.2〜16.1 秒の中に収まり、形による差は見えませんでした。

合計の推定費用は、A と B の平均の差が 2% でした。この組では、形どうしの差より、同じ形の中の揺れ(A で $0.459〜0.528)の方が大きく出ています。揺れの元はサブエージェントのキャッシュ書き込みでした。A と B の1回目だけが約 5.5 万トークンで、ほかの回は約 4 万トークンです。

回子のキャッシュ書き込み子の推定費用合計の推定費用
A 1回目55,436$0.367$0.528
A 2回目40,070$0.298$0.459
B 1回目55,255$0.355$0.516
B 2回目40,010$0.290$0.451
C 1回目39,678$0.280$0.441
C 2回目39,871$0.287$0.449

C の合計($0.441〜0.449)は A より1割ほど安く見えます。ただ、C の2回はどちらもキャッシュ書き込みが約 4 万の回でした。約 4 万の回どうしで比べると、子の推定費用の差は $0.01〜0.02 です。回によって書き込みが約 1.5 万トークン違った理由は、確かめていません。

費用の大半は、サブエージェントを起こす分

どこに費用がかかっているかを見るため、少し難しい3問を回ごとに分けました。

回子の要求の数子の出力子のキャッシュ読み子のキャッシュ書き込み子の推定費用親の推定費用
A 1回目104,344178,16742,111$0.333$0.162
A 2回目104,298179,29541,981$0.332$0.162
B 1回目93,610156,01041,254$0.310$0.162
B 2回目93,577156,01041,221$0.309$0.162

サブエージェント3つの出力は、合わせて数千トークンです。これに対し、キャッシュ書き込みは出力の約 10 倍、キャッシュ読みは約 40 倍のトークン数でした。子の費用の大半は、サブエージェントごとに道具の説明などのプロンプトをキャッシュに書き込む分と、それを読み直す分です。low にして減ったのは、出力、要求の数(10 回が 9 回に)、キャッシュ読み(約 17.8〜17.9 万が 15.6 万に)でした。キャッシュ書き込みは約 4.2 万から 4.1 万で、ほとんど変わっていません。子の推定費用の減りは 7% にとどまりました。

親の分は、どの回も要求2回・出力 613 トークン・$0.162 で、合計の3分の1ほどを占めます。今回の親は仕事を配って結果を返すだけなので、子の深さを変えてもこの分は動きません。

少し難しい3問の回ごとの推定費用。親は A・B とも 0.162 ドル。サブエージェントは A で 0.332〜0.333 ドル、B で 0.309〜0.310 ドル。合計は A が 0.493〜0.495 ドル、B が 0.471 ドル、親だけで解く D が 0.302〜0.317 ドル。

図の右端の D(親だけで解く)は、親の分だけで $0.302〜0.317 でした。サブエージェントを使う形より、はっきり安くなっています。

同じ重い荷を背負って小さな包みを一つずつ運ぶ三人と、荷を一つだけ背負って三つの包みを順に運ぶ一人

サブエージェントを使わず親が解くと:費用は4〜7割、時間は 1.1〜3.1 倍

D では Agent ツールを外し、親に3問を順に解かせました。

  • 推定費用:易しい3問で $0.219〜0.225、少し難しい3問で $0.302〜0.317。サブエージェントに分けた形(A〜C)の 41〜67% でした。
  • 経過時間:易しい3問で 18.5〜20.6 秒、少し難しい3問で 37.2〜48.0 秒。分けた形の 1.1〜3.1 倍です。3問を並べて走らせられないため、長くなります。

少し難しい3問で D の親が出した出力(4,580〜5,671 トークン)は、A のサブエージェント3つの合計(4,298〜4,344)より多いくらいです。一方、D のキャッシュ書き込みは 22,443〜23,235 トークンで、A の親と子を合わせた約 6 万の4割ほどでした。

少し難しい3問の回ごとの経過時間。A が 19.3 秒と 18.0 秒、B が 15.8 秒と 15.7 秒、親だけで解く D が 37.2 秒と 48.0 秒。

少し難しい3問の結果をまとめると、次の図のようになります。子の深さを変えても合計は 2 セントほどしか動きません。サブエージェントを使わない方が、費用は大きく下がります。

少し難しい3問での子の出力と合計の推定費用

親を low にすると、サブエージェントも low になる

C(親を --effort low、環境変数なし)では、api_request の effort は親もサブエージェントも low でした。サブエージェントは親の深さを引き継ぐので、親を下げれば子も下がります。今回は親が仕事を配るだけだったため、C の親の出力(613 トークン)と推定費用($0.162)は A・B と同じでした。

これまで子の深さを下げるには、親ごと下げるしかありませんでした。B(CLAUDE_CODE_SUBAGENT_EFFORT=low)なら、親は high のまま考えさせ、サブエージェントだけを下げられます。

時間を縮めたいか、費用を抑えたいか

今回の小さな問題で測った範囲では、目的で分けて考えると使いやすくなります。

  • 時間を縮めたい: サブエージェントに分け、並べて走らせます。そのうえで CLAUDE_CODE_SUBAGENT_EFFORT=low にすると、少し難しい3問では経過時間が 18.0〜19.3 秒から 15.7〜15.8 秒になりました。解けなくなった問題はありませんでした。
  • 費用を抑えたい: 子の深さを下げても、費用は 2〜5% しか動きません。小さな作業はサブエージェントに分けず親に順に解かせると、推定費用は分けたときの4〜7割になりました。その代わり、時間は延びます。

確かめていないこと

  • もっと重い作業(長く考える問題・大きなコードベース)で、low にすると解けなくなるか、費用の差が開くか。今回の問題は low でも解けました。
  • ばらつき。どの形も2回ずつしか走らせていません。易しい3問でキャッシュ書き込みが約 4 万と約 5.5 万に分かれた理由も、分かっていません。
  • 背景で走らせるサブエージェント(run_in_background)、ほかのモデル、対話の画面での振る舞い。
  • C(親も low)は、易しい3問でしか測っていません。

おわりに

CLAUDE_CODE_SUBAGENT_EFFORT=low はきちんと効き、サブエージェントの出力と時間を 6〜17% 削りました。ただ、今回の小さな問題では、費用の大半はサブエージェントを起こすこと自体にかかっていました。子の深さは主に速さと出力を左右し、費用はまず分けるかどうかで決まる、と見ておくのがよさそうです。

※ 環境変数、OpenTelemetry のイベントと属性、費用の見積もりは、執筆時点の Claude Code 2.1.316 の情報です。いまは変わっている可能性があります。