本文へスキップ
hdknr blog
戻る

ローカルモデルに何を任せるか — Claude Code の開発ループに小さいモデルを混ぜる設計

更新日:

/dev-loop のようなループ志向の開発スキルをスワーム実行させるとき、一部の作業を ローカルの小さいモデル(llama.cpp 経由の 27B クラス)に振り分ければ、実行速度を上げ、 トークン消費を削減できるのではないか。

この問いを詰めていくと、節約の成否は「どのモデルが安いか」ではなく その工程が高ボリューム・低判断かどうかの一点に収束した。その検討過程の記録である。

対象は dev-loop スキル だが、議論はエージェント開発ループ一般に当てはまる。

前提: subagent 単位の振り分けはできない

まず機構の話から。Claude Code には「このスワームの 1 体だけ別プロバイダに向ける」 というフックが存在しない。 Agent ツールの modelWorkflowopts.model も、 値は Claude のティア(opus / sonnet / haiku / fable)に限定された enum である。

したがって「ローカルモデルを混ぜる」は、必ず以下のいずれかの形を取る。

経路 A: モデルを「エージェント」ではなく「ツール」にする

llama-server の OpenAI 互換エンドポイントを薄い CLI か MCP サーバで包み、 Bash から叩く。これが本命。

# summarize-local は llama-server の /v1/chat/completions を叩く自作の薄いラッパ
summarize-local .claude/logs/ci-run-1234.log > .claude/logs/brief.md

トークン節約の成否はここで決まる。巨大な生データはスクリプト側がファイルから 直接読まなければならない。 Claude が一度読んでローカルモデルに渡す形にすると、 入力トークンはすでに消費済みなので節約はゼロになる。

Claude Code では Bash ツールの出力はそのまま文脈に入るので、 ファイルにリダイレクトし、Claude はそれを読まないという規律が必要になる。

経路 B: プロキシでティアをマッピング(実験的)

ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN で Claude Code 自体を変換プロキシ (LiteLLM 等)に向け、ANTHROPIC_DEFAULT_HAIKU_MODEL にローカルモデルの ID を 割り当てる。すると Agent(model: "haiku") がローカルに落ちる。

難点が 3 つある。

経路 C: ループの外でスワームを回す

機械的な fan-out(「20 ファイル × API 表面の抽出」など)を自前スクリプトで llama-server に並列投げし、集約結果だけ Claude に渡す。A の大規模版である。 レート制限がないぶん、並列度では API より有利になり得る。

速度への期待は補正が必要

先に期待値を潰しておく。実行速度はおそらく速くならない。

27B をローカル(Mac)で回すと、長いプロンプトの prefill を含めた実時間では クラウド API より遅いのが通常である。改善が出るのは「レート制限なしの高並列」か 「往復回数の削減」が効く場合だけだ。

得られるのは主に トークンコストと、データを外に出さないこと。 そこを狙わないなら、この検討自体に意味がない。

最初の直感は空振りする

「単体テストの実装は Opus、実行と結果報告は小さいモデル」という分担を考えてみる。 一見もっともらしいが、その切り方だと小さいモデルの担当分がほとんど残らない。

「実行と結果報告」を分解するとこうなる。

中身本当に必要なもの
テストを走らせるpytest / npm testモデル不要。Bash
pass/fail の判定exit code — モデル不要。決定的
失敗ログから原因箇所を抽出ここだけが LLM の仕事
受入基準を満たしたかの判定判断。ループの停止条件そのもの。渡してはいけない

工程を「安い作業」と思って束ねると、その中身の大半が そもそもモデルを必要としない決定的処理だったり、 絶対に手放してはいけない判断だったりする。分解しないと分からない。

順序を間違えないこと

残った 1 マス(失敗ログの原因抽出)に飛びつく前に、 タダで決定的にできる削減を先に全部やる。

ここまでやると、小さいモデルに残る仕事は「絞り込んだ traceback の原因説明」だけになり、 しばしば上位モデルが直接読んでも安い分量になる。 素の失敗ログが常時巨大なプロジェクト(E2E、統合テスト、大量の並列ケース)でないと、 挟む価値は出ない。

委譲の原則

ここまでで原則が言語化できる。

高ボリューム・低判断を出す。低ボリューム・高判断を残す。

この 2 軸で工程を並べると、直感と結論がずれる場所が見える。

トークン量と必要な判断の重さを 2 軸に取った 4 象限のマトリクス図。高ボリューム・低判断の象限には設計ドキュメントの要約や失敗ログの原因抽出が入り小さいモデルへの委譲が妥当、低ボリューム・低判断の象限は規約チェックや pass/fail 判定でそもそも LLM が不要、高判断の 2 象限は敵対的レビューやレビュー指摘の反映・受入基準の判定で上位モデルが持つべきことを示している

作業生成/入力トークン量必要な判断委譲の妥当性
長い設計ドキュメントの要約入力が巨大
失敗ログの原因抽出入力が巨大
規約遵守チェック小〜中△ — そもそも LLM 不要。grep で済む
レビュー指摘の反映diff は小さい
受入基準の判定
敵対的レビュー中〜大

「規約遵守チェック」の行は独立した教訓である。規約チェックの大半は決定的スクリプトで書くべきで、 grep で済む判定にモデルを使うのは横滑りにすぎない。安いモデルを検討する前に、 モデルを使わない選択肢を潰す。

「反映を任せる」が原則に反する理由

では逆向きの分担はどうか。判定と敵対的レビューを上位モデルが行い、 その反映からテストまでを小さいモデル、結果を再び上位モデルがレビューする。

構成としては「高価な審判/安価な実行者」という筋の通った形で、実装も成立する。 小さいモデルにファイルを書き換えさせるには外部エージェント (OpenAI 互換エンドポイントを叩けるコーディングエージェント)を立て、 Bash で subprocess として呼ぶ。

# 疑似コード。<coding-agent> は OpenAI 互換エンドポイントを叩ける
# コーディングエージェントに置き換える。worktree 内で実行する想定
<coding-agent> --model local/qwen --message "$(cat .claude/findings/f-03.md)" --yes
pytest -q > .claude/logs/r.log 2>&1; echo "exit=$?"
git diff   # ← 上位モデルが読むのはここだけ

だがこれは委譲マトリクスの「レビュー指摘の反映」にあたる。 節約額が最小で、事故率が最大の工程を選んでいる。

収束しないと赤字になる

さらに構造的な問題がある。修正が外れると上位モデルが再レビューする。 1 回のレビューは差分全体を読むコストである。

3 回外せば、上位モデルが最初から直すより、レビュー代のほうが高くつく。

損益分岐は一発合格率で決まる。測るべきはそこ一点で、目安としては 1 finding(レビューで挙がった個別の指摘)あたりの再レビューが平均 2 回を超えたら、 その分担は損。 これはベンチマークではなく設計上の見立てなので、回して実測するしかない。

それでも組むなら: 必須のルール

この分担を採るなら、以下は省略できない。

  1. finding を機械的に実行可能な仕様に落とす。 レビュー出力を散文にしない。file:line / 何が誤りか / 修正後が満たすべき条件 / 検証コマンド、を構造化して書く。 小さいモデルは「このレビューに対応せよ」では外し、 「この関数の戻り値を X にし、pytest tests/foo.py::bar が通ること」では通る。 つまり上位モデルの仕事は finding ごとの仕様書執筆に変わる。

  2. 1 finding = 1 呼び出しで隔離する。 まとめて渡すと失敗の切り分けができず、リトライが差分全体のやり直しになる。

  3. テストを決定的なゲートに置く。 「テストが通らない編集は上位モデルに見せる前に破棄」。 exit code 判定なのでトークン 0 で最悪の試行を濾せる。

  4. 試行上限を切って必ずエスカレーションする。 同一 finding で 2〜3 回失敗したら上位モデルが自分で直す。 上限がないと無限ループになる。

  5. 役割を絶対に混ぜない。 小さいモデルは実行者、上位モデルは審判。 実行者に判定させない。

一番大事な設計ルール: 判定(verdict)を渡さない

全体を通して最大の危険はこれである。

「結果報告」を小さいモデルが作り、上位モデルがそれを信じる構造にすると、 証拠と判断の間に監査されていない圧縮器が入る。

27B が失敗を 1 件落とす、あるいは「全て通過」と要約するだけで、 上位モデルは「反証なし」と読む。これは dev-loop スキルが Verifier(検証担当の subagent) について警告する失敗モードと同型である。すなわち、黙って静的確認に縮退した報告を 「反証なし」と読み違える、というものだ。

分離する。

安いモデルに委譲してよいのは証拠の圧縮であって、証拠からの結論ではない。

その前に: haiku ティアなら 0 インフラで同じ分担が組める

ここまでの機構を組む目的が単なるトークン削減なら、 haiku ティアで同じ分担が 0 インフラで組める。

Agent(model: "haiku") で実行者を立て、上位モデルが finding を書いて判定する。 前節までのルール 1〜5 はそのまま流用でき、ツール忠実度はローカル 27B より確実に高い。 Workflow を使うなら opts.effort: 'low' でさらに絞れる。

ローカルモデルが既存の安価ティアより優位なのは、 「トークンを外に出さないこと」と「レート制限のない並列度」だけである。 その 2 つが要件ならローカル版を組む意味があり、 単にコスト削減が目的なら安価ティア版を先に測るべきだ。

まとめ

補足: ここで書いた「subagent 単位の振り分けはできない」は Claude Code の機構の話です。Codex には [model_providers][agents] があり、サブエージェントに別プロバイダのモデルを割り当てる余地があります。その差と、両者を併用する場合の設計は 「Codex 裏技」を検証 にまとめました。ただし委譲の判断軸——証拠の圧縮は渡してよく、証拠からの結論は渡さない——は、どちらの製品でも変わりません。



前の記事
RDS for MySQL 8.0 → 8.4 を標準サポート終了当日に Blue/Green で移行した記録 — 実測値と落とし穴18個
次の記事
Kimi K3 は2.8兆パラメータより「忘れ方」が新しい — KDA で読む記憶アーキテクチャと実運用コスト