/dev-loop のようなループ志向の開発スキルをスワーム実行させるとき、一部の作業を
ローカルの小さいモデル(llama.cpp 経由の 27B クラス)に振り分ければ、実行速度を上げ、
トークン消費を削減できるのではないか。
この問いを詰めていくと、節約の成否は「どのモデルが安いか」ではなく その工程が高ボリューム・低判断かどうかの一点に収束した。その検討過程の記録である。
対象は dev-loop スキル だが、議論はエージェント開発ループ一般に当てはまる。
前提: subagent 単位の振り分けはできない
まず機構の話から。Claude Code には「このスワームの 1 体だけ別プロバイダに向ける」
というフックが存在しない。 Agent ツールの model も Workflow の opts.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 つある。
- セッション全体が対象になる。 一部の subagent だけ、という分離ができない。
- Claude Code のシステムプロンプト+ツールスキーマは数万トークン級。 27B クラスにこれを載せて多ターンのツール呼び出しを安定させるのは、 モデルの賢さ以前にコンテキスト長と tool-call 忠実度の勝負になる。
- サポートされた構成ではなく、壊れ方が読みにくい。
経路 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 マス(失敗ログの原因抽出)に飛びつく前に、 タダで決定的にできる削減を先に全部やる。
-q --tb=short/--tb=lineで出力自体を削る(コスト 0)--junitxmlを jq / python で処理して失敗テスト名を機械的に抽出 (コスト 0、幻覚リスク 0)- 失敗したテストの traceback だけを切り出す
ここまでやると、小さいモデルに残る仕事は「絞り込んだ traceback の原因説明」だけになり、 しばしば上位モデルが直接読んでも安い分量になる。 素の失敗ログが常時巨大なプロジェクト(E2E、統合テスト、大量の並列ケース)でないと、 挟む価値は出ない。
委譲の原則
ここまでで原則が言語化できる。
高ボリューム・低判断を出す。低ボリューム・高判断を残す。
この 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 # ← 上位モデルが読むのはここだけ
だがこれは委譲マトリクスの「レビュー指摘の反映」にあたる。 節約額が最小で、事故率が最大の工程を選んでいる。
- 生成物が diff なのでトークンをほとんど使わない → 節約額が小さい
- 「レビュアーがなぜ反対したのか」の理解を要求する → 判断が重い
- 小さいモデルの典型的な失敗は、指摘の字面を満たして別の何かを壊す 一見もっともらしい編集、あるいは部分適用
収束しないと赤字になる
さらに構造的な問題がある。修正が外れると上位モデルが再レビューする。 1 回のレビューは差分全体を読むコストである。
3 回外せば、上位モデルが最初から直すより、レビュー代のほうが高くつく。
損益分岐は一発合格率で決まる。測るべきはそこ一点で、目安としては 1 finding(レビューで挙がった個別の指摘)あたりの再レビューが平均 2 回を超えたら、 その分担は損。 これはベンチマークではなく設計上の見立てなので、回して実測するしかない。
それでも組むなら: 必須のルール
この分担を採るなら、以下は省略できない。
-
finding を機械的に実行可能な仕様に落とす。 レビュー出力を散文にしない。
file:line/ 何が誤りか / 修正後が満たすべき条件 / 検証コマンド、を構造化して書く。 小さいモデルは「このレビューに対応せよ」では外し、 「この関数の戻り値を X にし、pytest tests/foo.py::barが通ること」では通る。 つまり上位モデルの仕事は finding ごとの仕様書執筆に変わる。 -
1 finding = 1 呼び出しで隔離する。 まとめて渡すと失敗の切り分けができず、リトライが差分全体のやり直しになる。
-
テストを決定的なゲートに置く。 「テストが通らない編集は上位モデルに見せる前に破棄」。 exit code 判定なのでトークン 0 で最悪の試行を濾せる。
-
試行上限を切って必ずエスカレーションする。 同一 finding で 2〜3 回失敗したら上位モデルが自分で直す。 上限がないと無限ループになる。
-
役割を絶対に混ぜない。 小さいモデルは実行者、上位モデルは審判。 実行者に判定させない。
一番大事な設計ルール: 判定(verdict)を渡さない
全体を通して最大の危険はこれである。
「結果報告」を小さいモデルが作り、上位モデルがそれを信じる構造にすると、 証拠と判断の間に監査されていない圧縮器が入る。
27B が失敗を 1 件落とす、あるいは「全て通過」と要約するだけで、 上位モデルは「反証なし」と読む。これは dev-loop スキルが Verifier(検証担当の subagent) について警告する失敗モードと同型である。すなわち、黙って静的確認に縮退した報告を 「反証なし」と読み違える、というものだ。
分離する。
- pass/fail は exit code か junitxml から決定的に取る — モデルを通さない
- 小さいモデルが生成してよいのは説明文だけ — 判定は生成させない
- 説明が疑わしければ上位モデルが生ログを部分的に読み直せるよう、 ログファイルは消さず残す
安いモデルに委譲してよいのは証拠の圧縮であって、証拠からの結論ではない。
その前に: haiku ティアなら 0 インフラで同じ分担が組める
ここまでの機構を組む目的が単なるトークン削減なら、 haiku ティアで同じ分担が 0 インフラで組める。
Agent(model: "haiku") で実行者を立て、上位モデルが finding を書いて判定する。
前節までのルール 1〜5 はそのまま流用でき、ツール忠実度はローカル 27B より確実に高い。
Workflow を使うなら opts.effort: 'low' でさらに絞れる。
ローカルモデルが既存の安価ティアより優位なのは、 「トークンを外に出さないこと」と「レート制限のない並列度」だけである。 その 2 つが要件ならローカル版を組む意味があり、 単にコスト削減が目的なら安価ティア版を先に測るべきだ。
まとめ
- subagent 単位でローカルモデルに振る機構はない。ツール化するのが本命。
- 生データがモデルの文脈に入った時点で節約は消える。スクリプトがファイルを直接読む。
- 委譲の判断軸は高ボリューム・低判断。「安そうな工程」という直感は当たらない。
- モデルを使わない選択肢を先に潰す。 grep で済む判定に安いモデルを使うのは横滑り。
- 判定・敵対的レビュー・pass/fail は手放さない。 委譲してよいのは証拠の圧縮であって、証拠からの結論ではない。
- 速度改善は期待しない。 得られるのはコストとデータの局所性。
補足: ここで書いた「subagent 単位の振り分けはできない」は Claude Code の機構の話です。Codex には
[model_providers]と[agents]があり、サブエージェントに別プロバイダのモデルを割り当てる余地があります。その差と、両者を併用する場合の設計は 「Codex 裏技」を検証 にまとめました。ただし委譲の判断軸——証拠の圧縮は渡してよく、証拠からの結論は渡さない——は、どちらの製品でも変わりません。
