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 の転写を message.id で数えたら 0/61 だった

0
Last updated at Posted at 2026-09-21

前の記事で、Claude Code の usage は基礎コンテキストより往復(API 応答)の数が効くと分かりました。往復を減らす一番大きな手は「前の結果を必要としない道具の呼び出しは、同じ応答に並べる」ことです。私はこれを 1 か月前から設定ファイルと記憶に書いていました。

数えたら、61 回すべて単独でした。この記事の中心は「何をまとめて、何を分けるか」の 2 問判定です。数え方と、その後どう変わり、何を変わったと言わないかも記録します。

この記事の位置づけ(2026-09-26 追記)

  • この記事で新しく示すこと: 転写の同じ message.id を束ねれば「1 応答に道具が何個」を数えられること。書いた規律が起点では 0/61 だったこと。
  • 当てはまる範囲: 当方 1 人の Claude Code の転写。起点は定型作業 1 件で、1 か月の全体は数えていません。
  • 言葉: 本文の「器」=点検や処理のための自作スクリプトのことです。

先に結論

  • 転写は道具の呼び出し(tool_use)を 1 行 1 個で書くが、同じ API 応答の行は同じ message.id を持つ。id で束ねれば「1 応答に何個並べたか」は復元できる。
  • 起点(定型の事務作業 1 件)は全応答 62・道具を含む応答 61・道具 61・複数を並べた応答 0。規律が文書に在っても行動は 0 だった。
  • 同じセッションの中で、明示的な試験と議論のあと、その作業を直接指示していない通常作業で、区間ごとに 0%→50%→17%。最後の区間の単独応答は全部「前の結果に依存」で、独立なのに単独=0 件。
  • 率は目標にしない。率を上げようとすると、依存する処理まで束ねる誘因が生まれる。減らしたいのは「独立なのに単独で出した不要往復」だけ。
  • セッションを跨いで持続するかは未確認。同じセッション内で自発化した、までしか言えない。

束ねるか、分けるか——2 問判定

2 問判定。Q1 次の呼び出しの内容は前の結果で変わるか(YES なら分ける)。Q2 同じ状態を書き換えて順序が競合するか(YES なら分ける)。両方 NO のものだけ同じ応答に並べる

Q1: 次の呼び出しの内容は、前の結果で変わるか? YES → 分ける/NO → Q2
Q2: 同じ状態(同じファイル・同じ台帳)を書き換えて、順序が競合するか? YES → 分ける/NO → 同じ応答に並べる候補

並べる例: 独立な 3 ファイルの書き込み/記帳と次の材料の読み/一覧を取る一括操作と台帳の読み。
分ける例: タブの ID を取ってから使う操作/失敗の原因を読んでから直す/zip を作ってから点検する。

率が何%になったかより、この 2 問が使えるかどうかがこの記事の中身です。数字は「本当に守られていたか」を確かめるためのものです。

何を数えるか

転写(~/.claude/projects/<プロジェクト>/<セッション>.jsonl)の type == "assistant" 行には message.content[] があり、その中に type == "tool_use" が入ります。1 行に 1 個です。ここで「1 応答に何個並べたかは分からない」と一度結論しました。誤りでした。同じ応答の行は同じ message.id を持ちます。

import json, sys, collections

by_id = collections.OrderedDict()          # 応答 id → [道具名, ...](本文だけの応答は空リスト)
for line in open(sys.argv[1], encoding="utf-8"):
    d = json.loads(line)
    if d.get("type") != "assistant":
        continue
    m = d["message"]
    by_id.setdefault(m["id"], [])
    for b in m.get("content") or []:
        if isinstance(b, dict) and b.get("type") == "tool_use":
            by_id[m["id"]].append(b["name"])

all_resp = len(by_id)                                        # 全応答(本文だけの応答を含む)
tool_resp = sum(1 for v in by_id.values() if v)              # 道具を含む応答
total = sum(len(v) for v in by_id.values())                  # 道具の総数
multi = sum(1 for v in by_id.values() if len(v) >= 2)        # 複数道具の応答
single = collections.Counter(v[0] for v in by_id.values() if len(v) == 1)
print(f"全応答 {all_resp}/道具を含む応答 {tool_resp}/道具 {total}/複数道具の応答 {multi}({100*multi/tool_resp:.0f}%)")
print("単独で出した応答の内訳:", dict(single.most_common(6)))

出るのは 4 つ——全応答/道具を含む応答/道具の総数/複数道具の応答の数と率。「道具を含む応答」は全 API 往復ではありません(本文だけの応答が別にある)。この計測器が見ているのは「道具を含む応答をどれだけ減らせたか」で、往復全体の内訳は前の記事の集計で見ます。

起点: 0/61

規律を書いてから 1 か月後の、定型の事務作業 1 件(公開ページを読んで台帳に記帳する類)。前の記事と同じ区間です。

全応答 道具を含む応答 道具の総数 複数道具の応答
62 61 61 0

「まとめる」という一文は設定ファイルにも記憶にもあった。読んではいた。並べたことは一度もなかった。

言われてやった 1 回は証拠に数えない

「本当に並べられるのか」と言われて、独立な 3 つ(コマンド・検索・コマンド)を同じ応答に並べました。転写では同じ message.id に 3 個、往復は 1 回。実行は逐次で、先頭と末尾のタイムスタンプは約 1.9 秒差でした。今回のこの 3 呼び出しでは、確認できた便益は実行時間の短縮ではなく LLM 往復の削減です。

この 1 回は、指示されてやったので、規律が身についた証拠には数えません。測るべきは直接指示のない作業です。

直接指示のない通常作業で、どう動いたか(区間ごとの値)

同じセッションの中で、この議論のあとに通常の作業(自作の試作を数本組む・計測する)を続けました。指示は「作業を進めて」だけです。

区間ごとの、道具を含む応答と、うち複数道具の応答。起点 0/61、前半 0/47、後半 9/18、最終区間 1/6

区間 全応答 道具を含む応答 道具 複数道具の応答
前半(試作 3 本) 48 47 47 0(0%)
後半(試作 2 本) 19 18 29 9(50%)
最終区間(作業 1 件) 7 6 11 1(17%・計測の呼び出しを除くと 5 応答中 1)

最終区間の単独応答を全部見ると、どれも「前の結果を読んでから次を決める」型で、独立なのに単独=0 件でした。前半の単独応答 47 件のうち、器の診断行(Bash・Edit・Write などの並び)を見て「並べられたのでは」と目で拾った候補 10 件を人手で判定すると、束ねるべきだった 8/単独が正しい 1/束ねられるが価値が小さい 1。無作為抽出ではないので 8/10 を 47 件全体の率に伸ばせません。言えるのは「独立なのに単独だった応答が少なくとも 8 件あり、束ねていれば往復が 12 減った(47 件中)」までです。取りこぼしの型は 2 つ——連続する独立な書き込みと、記帳と次の材料読み。どちらも後半で消えました。

後半の 50% は「率が高い=良い」ではありません。同じ 2 問判定で NO・NO のものを並べた結果、たまたまその区間は独立な書き込みが多かっただけです。

率を目標にしない

「複数道具の応答率」を上げようとすると、Q1 で YES のものまで束ねる誘因が生まれます。並べていいのは Q1・Q2 が両方 NO のものだけ。率は診断計器で、減らしたいのは「独立なのに単独で出した不要往復」です。もう 1 つ、Bash の中で複数コマンドを 1 本に束ねたものは「1 回の道具」に数えるので率には出ません。総数の減りと合わせて読みます。

閉じる基準も先に決めました。A 独立なのに単独が少ない→終了/B 軽微→保留/C 同じ独立型を何度も単独で出す→そのパターンだけ器で警告(WARN 印字のみ・終了コードは変えない)。今回は A で閉じました。

言わないこと

  • 「記憶と文書だけで身についた」。同じセッション内には議論と明示テストの文脈があった。
  • 「次のセッションでも持続する」。未確認。次の通常セッションの終了時に測り、出ていれば追記します。人工の実験は作りません。
  • 「並べると速い」。今回の 3 呼び出しは逐次だった。効くのは往復の再計上の分。
  • 「道具を含む応答=全往復」。本文だけの応答は別にある。

Lab 版(「測れない」と誤結論した経緯・0/72 と書いて数え直した記録・率を目標にしそうになった記録): https://sumitsuke.jp/via/qiita/lab/tool-calls-batched-or-not/


AI の利用について

計測器と記事の下書きには AI(Claude)を使いました。数字(62/61/61/0・48/47/47/0・19/18/29/9・7/6/11/1・8/1/1)は自分の転写と作業記録から数え、判定と公開は自分で行っています。転写に含まれる案件の中身は書いていません。

受託でも同じ運用をしています

「守られているはず」を、記録から数えて確かめます。相談はテキストだけで完結します。
▶ Sumitsuke / 依頼から納品までの流れ

次に読む: 数える物差しそのものを疑う——期待値を別の根拠から作ったら自分の癖が 2 回捕まった


この記事は Zenn にも同じ内容を掲載しています。

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?